Source for file IsMySQLListClass.class.php

Documentation is available at IsMySQLListClass.class.php

  1. <?php
  2. /**
  3.  * R.E. DBObjects
  4.  *
  5.  * @author Takács Ákos (Rimelek), programmer [at] rimelek [dot] hu
  6.  * @copyright Copyright (C) 2010, Takács Ákos
  7.  * @version 2.1
  8.  * @license http://www.gnu.org/licenses/lgpl.html
  9.  * @package REDBObjects
  10.  */
  11.  
  12. /**
  13.  * @ignore
  14.  */
  15. require_once dirname(__FILE__).'/../ADBListClass.class.php';
  16.  
  17. /**
  18.  * @ignore
  19.  */
  20. require_once dirname(__FILE__).'/../IIsDBListClass.class.php';
  21.  
  22. /**
  23.  * @ignore
  24.  */
  25. require_once dirname(__FILE__).'/../IIsDBClass.class.php';
  26.  
  27. /**
  28.  * @ignore
  29.  */
  30. require_once dirname(__FILE__).'/IsMySQLClass.class.php';
  31.  
  32. /**
  33.  * Lista osztály
  34.  *
  35.  * Jelen verzió már tartalmazza a listakezeléshez szükséges legalapvetőbb
  36.  * eljárásokat, tulajdonságokat. <br />
  37.  * Ebbe beleértendők a következők:<br />
  38.  * <ul>
  39.  *    <li>Lista inicializálása: {@link init()}</li>
  40.  *    <li>Egy oldal inicializálása: {@link page()}</li>
  41.  *    <li>Új elem felvétele: {@link add()}</li>
  42.  *    <li>Rekord törlése: {@link delete()}</li>
  43.  *    <li>Listán való iteráció (foreach ciklus használata az objektumon)</li>
  44.  * </ul>
  45.  *
  46.  * <code>
  47.  * require_once 'REDBObjects/REDBObjects.class.php';
  48.  * REDBObjects::uses('mysql');
  49.  *
  50.  * mysql_connect('localhost', 'root', 'password');
  51.  * mysql_select_db('teszt');
  52.  *
  53.  * $list->tableName_signal = 'T_'; //Ez az alapértelmezett is
  54.  * $list->table_field_sep = '__'; //az alapértelmezett az egy darab _ jel
  55.  *
  56.  * $list->page('teszt', 10);
  57.  * foreach ($list as $key => $object)
  58.  * {
  59.  *    print $object->T_teszt__id.', '.$object->field.'<br />'.PHP_EOL;
  60.  *    if ($object->id == 2)
  61.  *    {
  62.  *        $object->field = 'P';
  63.  *        $object->update();
  64.  *    }
  65.  * }
  66.  * </code>
  67.  *
  68.  * @property string $tableName_signal Táblanevet jelző prefix
  69.  * @property string $table_field_sep Táblanevet és mezőnevet elválasztó jel
  70.  *
  71.  * @author Takács Ákos (Rimelek), programmer [at] rimelek [dot] hu
  72.  * @copyright Copyright (C) 2010, Takács Ákos
  73.  * @license http://www.gnu.org/licenses/lgpl.html
  74.  * @package REDBObjects
  75.  */
  76. class IsMySQLListClass extends ADBListClass implements IIsDBListClassIteratorArrayAccess
  77. {
  78.     /**
  79.      * Lista elemeit tároló tömb
  80.      *
  81.      * @var IIsDBClass[] 
  82.      */
  83.     public $records=array();
  84.  
  85.     /**
  86.      * A listában tárolandó objektum típus
  87.      *
  88.      * @var string 
  89.      */
  90.     protected $className = '';
  91.  
  92.     /**
  93.      * A lekérdezésre illeszkedő rekordok száma
  94.      *
  95.      * @var int 
  96.      */
  97.     protected $count=null;
  98.  
  99.     /**
  100.      * Adott limit mellett a megjelenítéshez szükséges oldalak minimális száma
  101.      *
  102.      * @var int 
  103.      */
  104.     protected $pages=1;
  105.  
  106.     /**
  107.      * Aktuális oldal száma, ha már lekértünk egy oldalt.
  108.      * @var int 
  109.      */
  110.     protected $page=null;
  111.  
  112.     /**
  113.      * Aktuális tábla index az iterációnál
  114.      *
  115.      * @var int 
  116.      * @ignore
  117.      */
  118.     protected $itTableIndex=0;
  119.     
  120.     /**
  121.      * Aktuális mezőindex az iterációnál
  122.      *
  123.      * @var int 
  124.      * @ignore
  125.      */
  126.     protected $itFieldIndex=0;
  127.  
  128.     /**
  129.     *    A megvalósítandó táblák listája.
  130.     *    Még a megváltoztatás előtt. (Aliasok)
  131.     *
  132.     *    @var array 
  133.     */
  134.     public $defaultTablelist=array();
  135.  
  136.     /**
  137.      * Védett táblák listája. Ezekből a táblákból nem törölhető
  138.      * rekord a {@link delete()} metódussal.
  139.      * @var array 
  140.      */
  141.     protected $protectedTables = array();
  142.  
  143.     /**
  144.      * Az sql kód from utáni része, amivel inicializálva lett a lista
  145.      * @var string 
  146.      */
  147.     protected $sql = "";
  148.  
  149.     /**
  150.      * Limit, ami az inicializáláskor lett megadva
  151.      * @var int 
  152.      */
  153.     protected $limit = 0;
  154.  
  155.     /**
  156.      * Konstruktor
  157.      *
  158.      * @param array $tablelist 
  159.      * @param string $className 
  160.      */
  161.     function __construct($tablelist,$className='IsMySQLClass')
  162.     {
  163.         $this->tablelist = $this->defaultTableList $tablelist;
  164.         $this->className = $className;
  165.         //lekérdezi a lehetséges mezőneveket.
  166.         $this->getFields();
  167.  
  168.     }
  169.  
  170.     /**
  171.      *
  172.      * @ignore
  173.      * @return int 
  174.      */
  175.     public function count()
  176.     {
  177.         return count($this->records);
  178.     }
  179.  
  180.     /**
  181.      *
  182.      * @param string $sql FROM utáni sql kód (Limit nélkül)
  183.      * @param int $limit limit
  184.      */
  185.     protected function setPagesAndCount($sql$limit)
  186.     {
  187.         $this->sql = $sql;
  188.         $this->limit = $limit;
  189.         //Lekérdezésre illeszkedő sorok száma limit nélkül
  190.         $count mysql_fetch_rowmysql_query"select count(*) from $sql) );
  191.         $this->count=$count[0];
  192.         //Ha megadtuk a limitet
  193.         if ($limit{
  194.             //Az oldalszámot ki kell számolni
  195.             $this->pages=ceil($this->count / $limit);
  196.         }
  197.     }
  198.  
  199.     /**
  200.      * Aktuális oldalszám szerint lista inicializálása
  201.      *
  202.      * @see $pagevar
  203.      * @param $sql FROM utáni sql kód
  204.      * @param $limit Hány rekord legyen egy oldalon
  205.      * @param int $page Oldalszém. Elhagyása esetén az url-ből veszi az oldalszámot.
  206.      */
  207.     public function page($sql$limit$page=null)
  208.     {
  209.         $this->setPagesAndCount($sql$limit);
  210.         $page $page !== null ? (int)$page $this->pageNumber();
  211.         $maxpage $this->countPages();
  212.         if ($page <= 0)
  213.         {
  214.             $page 1;
  215.         }
  216.         else if ($page >= $maxpage)
  217.         {
  218.             $page $maxpage;
  219.         }
  220.  
  221.         $offset ($page-1$limit;
  222.         $this->page = $page;
  223.         $this->init($sql$offset$limit);
  224.     }
  225.  
  226.     /**
  227.      * Lista inicializálása
  228.      *
  229.      *
  230.      * @param $psql FROM utáni sql kód (limit nélkül)
  231.      * @param $offset Ennyi rekordot ugrik át a listában
  232.      * @param $limit Ennyi rekordot kérdez le az offset értéktől kezdve
  233.      */
  234.     public function init($psql,&$offset=0,$limit=0)
  235.     {
  236.         $afields array();
  237.         $this->records = array();
  238.         //végig kell menni a táblalistánés összeállítani a lekérdezendő mezőlistát
  239.         foreach($this->tablelist as $tableName=>$fieldList)
  240.         {
  241.             //egy táblán belül az összes mező felvétele táblanevet tartalmazó aliassal
  242.             foreach ($fieldList as $field)
  243.             {
  244.                 $afields["`$tableName`.`$field` as `$tableName.$field`";
  245.             }
  246.             //ha az elsődleges kulcs mezőt nem kértük le, akkor automatikusan lekérdezéshez adódik
  247.             if (!isset($fieldList[key($this->priKeys[$tableName])]))
  248.             {
  249.                 $afields["`$tableName`.`".
  250.                     key($this->priKeys[$tableName]).
  251.                     "` as `$tableName.".key($this->priKeys[$tableName])."`";
  252.  
  253.             }
  254.         }
  255.  
  256.         if ($this->page === null)
  257.         {
  258.             $this->setPagesAndCount($psql$limit);
  259.         }
  260.         //lekérdezendő mezőnevek megadása
  261.         $fields implode(",\n",$afields);
  262.         $i=0;
  263.         //sql lekérdezés limit nélkül
  264.         $sql "select $fields from $psql";
  265.  
  266.         //Ha ez után az eltolás mértéke nagyobb, mint amennyi rekord van
  267.         if ($offset >= $this->count{
  268.             //Az eltolást az utolsó oldal első elemére állítja
  269.             $offset ($this->pages-1)*$limit;
  270.         }
  271.         if ($offset  0{
  272.             $offset 0;
  273.         }
  274.         if ($this->count==0{
  275.             $this->pages=1;
  276.         }
  277.         //Ha megadták a limitet
  278.         if ($limit{
  279.             //Akkor már hozzá lehet fűzni az sql lekérdezéshez a korrigált offsettel
  280.             $sql .= " limit $offset$limit";
  281.         }
  282.  
  283.         $query mysql_query($sql);
  284.         $record=null;
  285.  
  286.         //Az ADBClass absztrakt osztály tulajdonságainak lekérdezése
  287.         $ref new ReflectionClass('ADBClass');
  288.         $props $ref->getDefaultProperties();
  289.         //A listában tárolandó objektumtípus lekérdezése a későbbi példányosítás miatt.
  290.         $IIsDBClass new ReflectionClass($this->className);
  291.         while($fetch mysql_fetch_assoc($query)) {
  292.             //objektumok létrehozása
  293.             //Egy példány létrehozása a listában tárolandó objektumtípusból
  294.             $record $IIsDBClass->newInstance($this->defaultTablelist,true);
  295.  
  296.             $afields array();
  297.             //itt az eredményt be kell tölteni a properties tulajdonságba
  298.             foreach($this->tablelist as $tableName=>$fieldList)
  299.             {
  300.                 foreach ($fieldList as $field)
  301.                 {
  302.                     $this->properties[$tableName][$field$fetch[$tableName.'.'.$field];
  303.                 }
  304.                 //az elsődleges kulcsok értékeit külön is tárolni kell egy tömbben
  305.                 $this->priKeys[$tableName][key($this->priKeys[$tableName])=
  306.                     $fetch[$tableName.'.'.key($this->priKeys[$tableName])];
  307.             }
  308.  
  309.             //Az összes olyan tulajdonság beállítása az új objektumnak, ami a lista objektummal közös
  310.             foreach ($props as $prop=>$value{
  311.                 $record->$prop $this->$prop;
  312.             }
  313.             $record->isSqlQuery true;
  314.             //Új elem felvétele a listába
  315.             $this->records[$record;
  316.         }
  317.     }
  318.  
  319.     /**
  320.      * Új rekordok hozzáadása több táblához
  321.      *
  322.      * Az add() metódus segítségével egyszerűen hozzáadhatunk az adatbázishoz egy új rekordot.<br />
  323.      * Csak egy értékekkel feltöltött, példányosított {@link IsMySQLClass} típusú objektumra van szükség.
  324.      *
  325.      * <code>
  326.      * require_once 'REDBObjects/REDBObjects.class.php';
  327.      * REDBObjects::uses('mysql');
  328.      *
  329.      * mysql_connect('localhost', 'root', 'password');
  330.      * mysql_select_db('teszt');
  331.      * 
  332.      * class MyClass extends IsMySQLClass {}
  333.      * class MyList extends IsMySQLListClass {}
  334.      * $tablelist = array(
  335.      *    'table1'=>array('field1','field2'),
  336.      *    'table2'=>array('field3','field4'));
  337.      * $object = new MyClass($tablelist);
  338.      * $object->keyName = 'id';
  339.      * $list = new MyList($tablelist,'MyClass');
  340.      * $object->field1 = 'value1';
  341.      * $object->field3 = 'value3';
  342.      * // A tulajdonságokat lekérdezhetővé teszi,de nem frissíti az adatbázist,
  343.      * // mivel nincs is mit
  344.      * $object->update(false);
  345.      * $list->add($object);
  346.      * </code>
  347.      *
  348.      * @param IIsDBClass $object Listához adandó objektum
  349.      * @param bool $append Ha true, nem csak adatbázisba veszi fel az elemet,
  350.      *                 Hanem azonnal hozzáfűzi a recordlistához. Lekérdezhetővé téve.
  351.      * @return int Autoincrement azonosító
  352.      */
  353.     function add(IIsDBClass $object$append=false)
  354.     {
  355.         //ciklusban végigmegy a táblákon
  356.         $props $object->properties;
  357.         $first true;
  358.         $last_id 0;
  359.         foreach ($props as $tableName=>&$fields)
  360.         {
  361.             //újabb ciklusban a mezőkön
  362.             $fieldNames array();
  363.             $fieldValues array();
  364.             if (!$first)
  365.             {
  366.                 $fields[$object->keyName$object->keyValue;
  367.             }
  368.             foreach ($fields as $fieldName => $fieldValue)
  369.             {
  370.                 //a mezőneveket és az értékeiket külön tömbbe tölti.
  371.                 $fieldNames["`$fieldName`";
  372.                 $fieldValues["'$fieldValue'";
  373.             }
  374.             //vesszővel elválasztott formátumba konvertálja az értékek és nevek tömbjeit
  375.             $fieldValues implode(', ',$fieldValues);
  376.             $fieldNames implode(', ',$fieldNames);
  377.             //felviszi a táblába az új sort a megadott mezőkkel
  378.             $t = isset($this->tableAliases[$tableName]$this->tableAliases[$tableName$tableName;
  379.             mysql_query("insert into `$t` ($fieldNames) values($fieldValues)");
  380.             if ($first)
  381.             {
  382.                 $first false;
  383.                 //szükség lehet az elsődleges kulcsra, ha a kapcsoló mező auto_increment
  384.                 $last_id mysql_insert_id();
  385.                 //visszaadja a kapott objektumnak a kapcsoló mező értékét, hogy felhasználható legyen az init() metódusban
  386.                 $object->keyValue $object->keyName == key($object->priKeys[$tableName])) $last_id :
  387.                         $fields[$object->keyName];
  388.             }
  389.         }
  390.         $this->count++;
  391.         if ($append)
  392.         {
  393.             $this->records[$object;
  394.         }
  395.         return $last_id;
  396.     }
  397.  
  398.     /**
  399.      * @return int Lekérdezésre illeszkedő rekordok száma
  400.      */
  401.     function countRecords()
  402.     {
  403.         return (int)$this->count;
  404.     }
  405.  
  406.     /**
  407.      * @return int Lekérdezésre illeszekőd oldalak száma a limitnek megfelelően
  408.      */
  409.     function countPages()
  410.     {
  411.         return (int)$this->pages;
  412.     }
  413.  
  414.     /**
  415.      * {@link countPages()} aliasa
  416.      * @return int 
  417.      */
  418.     public function maxpage()
  419.     {
  420.         return $this->countPages();
  421.     }
  422.  
  423.     /**
  424.      * A táblalista szerint az összes lehetséges mező nevének lekérdezése,
  425.      * és beállítása tulajdonságnak
  426.      */
  427.     protected function getFields()
  428.     {
  429.         //a táblákat végigjárva az összes mezőjének nevét lekérdezi, így az indexek mindig léteznek,
  430.         //és az update() metódus akor is kiszűri a nem létező neveket, ha nem volt inicializálva az objektum
  431.         $fields array();
  432.         foreach($this->tablelist as $tableName => $fieldList)
  433.         {
  434.             $tn $from $tableName;
  435.             $exp explode(' ',$tableName);
  436.             if (count($exp== and trim(strtolower($exp[1])) == 'as' )
  437.             {
  438.                 $from trim($exp[0]);
  439.                 $this->tableAliases[$exp[2]] $from;
  440.                 $alias trim($exp[2]);
  441.                 $this->tablelist[$alias$this->tablelist[$tableName];
  442.                 unset($this->tablelist[$tableName]);
  443.                 $tableName $alias;
  444.             }
  445.             $query mysql_query("show columns from `".$from."`");
  446.             $in false;
  447.             while ($field mysql_fetch_assoc($query))
  448.             {
  449.  
  450.                 $this->properties[$tableName][$field['Field']] '';
  451.                 //ha az összes mezőt * karakterrel jelöltük
  452.                 if (($_in $in!== false or $in (array_search('*',$fieldList!== false) )
  453.                 //var_dump($tableName, $in , $_in,$fieldList);
  454.                     //akkor törölhető a lista és felvehetők az mezőnevek egyenként
  455.                     if ($_in === false)
  456.                     {
  457.                         $this->tablelist[$tableNamearray();
  458.                     //var_dump($field['Field']);
  459.                     $this->tablelist[$tableName][$field['Field'];
  460.  
  461.                 }
  462.                 //Ha ez az elsődleges kulcs mező, akkor visszaadja a primary_key
  463.                 //tulajdonságnak, hogy a kapcsoló mező elsődleges kulcs
  464.                 if ($this->keyName == $field['Field'])
  465.                 {
  466.                     $this->primary_key = $field['Field'];
  467.                 }
  468.                 //minden elsődleges kulcs mező értékét külön is tároljuk,
  469.                 //ezért előtte biztositjuk a helyet neki üres értékkel
  470.                 if ($field['Key'== 'PRI')
  471.                 {
  472.                     $this->priKeys[$tableNamearray($field['Field']=>'');
  473.                 }
  474.  
  475.             }// var_dump($this->tablelist);
  476.             //Mivel elsődleges kulcs mezőkre mindenképp szükség van,
  477.             //ezért kivételt kell dobni, ha egy tábla nem tartalmaz olyan mezőt.
  478.             if !isset($this->priKeys[$tableName]) )
  479.             {
  480.                 require_once dirname(__FILE__).'/../exceptions/IncompatibleTable.class.php';
  481.                 throw new IncompatibleTable("Egyedi elsődleges kulcs mező használata kötelező! Tábla: ".$tableName);
  482.             }
  483.         }
  484.     }
  485.  
  486.     /**
  487.      * Egy táblát le lehet vele védeni, hogy a megvalósított listában egy törlés
  488.      * esetén abból a táblából ne lehessen semmit sem kitörölni. Hasznos, ha például
  489.      * egy üzenetlistából törlünk felhasználói azonosító alapján a {@link delete()} -el,
  490.      * és nem szeretnénk, hogy a felhasználó is törlődjön.
  491.      *
  492.      * @param string $table Levédendő tábla neve. Akár {@link $tableName_signal} -al együtt
  493.      */
  494.     public function protectTable($table)
  495.     {
  496.         $this->protectedTables[$table$table;
  497.     }
  498.  
  499.     /**
  500.      *
  501.      * @see protectTable()
  502.      * @param string $table Feloldandó tábla neve
  503.      */
  504.     public function unProtectTable($table)
  505.     {
  506.         unset($this->protectedTables[$table]);
  507.     }
  508.  
  509.     /**
  510.      * Rekord törlés mezőn értéke
  511.      *
  512.      * <code>
  513.      * $list->delete('T_tablename_fieldname','value');
  514.      * </code>
  515.      *
  516.      * @see IIsDBListClass::delete()
  517.      * @return mixed true, ha sikeres a törlés, egyébként a MySQL hibaüzenet
  518.      */
  519.     public function delete($keyName,$keyValue)
  520.     {
  521.         $table "";
  522.         $field "";
  523.         $i=0;
  524.         $keyValue mysql_real_escape_string($keyValue);
  525.         $keyName mysql_real_escape_string($keyName);
  526.         //Ha a mezőnevet nem a táblanévvel együtt adtuk meg
  527.         if (!$this->sep_table_field($keyName,$table,$field)) {
  528.             //minden nem védett táblából a megfelelő rekordok törlése
  529.             foreach ($this->tablelist as $t => &$f)
  530.             {
  531.                 if (isset($this->protectedTables[$t])) continue;
  532.                 $table (isset($this->tableAliases[$t])) $this->tableAliases[$t$t;
  533.                 mysql_query("delete from `".$table."` where `$keyName` = '$keyValue'");
  534.                 $i+=mysql_affected_rows();
  535.  
  536.             }
  537.             $this->setPagesAndCount($this->sql$this->limit);
  538.             return $i;
  539.         }
  540.         if (isset($this->protectedTables[$table])) return 0;
  541.         if(isset($this->tableAliases[$table]))
  542.         {
  543.             $table $this->tableAliases[$table];
  544.         }
  545.         //ha konkrétan egy adott táblából kell törölni
  546.         mysql_query("delete from `$table` where `".$field."`='".$keyValue."'");
  547.         $this->setPagesAndCount($this->sql$this->limit);
  548.         return mysql_affected_rows();
  549.     }
  550.  
  551.     /**
  552.      * Az iteráció alaphelyzetbe állítása
  553.      * @ignore
  554.      */
  555.     public function rewind()
  556.     {
  557.         reset($this->records);
  558.     }
  559.     /**
  560.      * Az aktuális elem visszaadása
  561.      *
  562.      * @return IsMySQLClass 
  563.      * @ignore
  564.      */
  565.     public function current()
  566.     {
  567.         return current($this->records);
  568.     }
  569.  
  570.     /**
  571.      * Következő elem visszaadása
  572.      *
  573.      * @return IsMySQLClass 
  574.      * @ignore
  575.      */
  576.     public function next()
  577.     {
  578.         return next($this->records);
  579.     }
  580.  
  581.     /**
  582.      * Aktuális elem kulcsának visszaadása
  583.      *
  584.      * @return int 
  585.      * @ignore
  586.      */
  587.     public function key()
  588.     {
  589.         return key($this->records);
  590.     }
  591.  
  592.     /**
  593.      * Iteráció kilépési feltétele
  594.      *
  595.      * @return bool 
  596.      * @ignore
  597.      */
  598.     public function valid()
  599.     {
  600.         return ($this->current(!== false);
  601.     }
  602.  
  603.     /**
  604.      * Létezik-e egy megadott index a listában
  605.      *
  606.      * @param string $index 
  607.      * @return bool 
  608.      * @ignore
  609.      */
  610.     public function offsetExists($index)
  611.     {
  612.         return isset($this->records[$index]);
  613.     }
  614.  
  615.     /**
  616.      * Adott indexű elem lekérdezése
  617.      *
  618.      * @param string $index 
  619.      * @return IsMySQLClass 
  620.      * @ignore
  621.      */
  622.     public function offsetGet($index)
  623.     {
  624.         return $this->records[$index];
  625.     }
  626.     
  627.     /**
  628.      * Adott indexű elem értékének beállítása
  629.      *
  630.      * @param string $index 
  631.      * @param mixed $value 
  632.      * @ignore
  633.      */
  634.     public function offsetSet($index,$value)
  635.     {
  636.         
  637.     }
  638.  
  639.     /**
  640.      * Adott indexű elem érvénytelenítése
  641.      *
  642.      * @param string $index 
  643.      * @ignore
  644.      */
  645.     public function offsetUnset($index)
  646.     {
  647.         
  648.     }
  649.  
  650.     /**
  651.      *
  652.      * @param string $var 
  653.      * @return mixed 
  654.      * @ignore
  655.      */
  656.     public function  __get($var)
  657.     {
  658.         if ($var == 'tableName_signal' or $var == 'table_field_sep')
  659.         {
  660.             return $this->$var;
  661.         }
  662.         return null;
  663.     }
  664.  
  665.     /**
  666.      *
  667.      * @param string $var 
  668.      * @param mixed $value 
  669.      * @ignore
  670.      */
  671.     public function __set($var$value)
  672.     {
  673.         if ($var == 'tableName_signal' or $var == 'table_field_sep')
  674.         {
  675.             $this->$var $value;
  676.             return;
  677.         }
  678.         $this->$var $value;
  679.     }
  680. }
  681. ?>

Documentation generated on Fri, 02 Apr 2010 17:34:19 +0200 by phpDocumentor 1.4.1