Entity.class.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. <?php
  2. require_once(dirname(__FILE__).'/../constant.php');
  3. /**
  4. Classe mère de tous les modèles (classe entitées) liées a la base de donnée,
  5. cette classe est configuré pour agir avec une base SQLite, mais il est possible de redefinir ses codes SQL pour l'adapter à un autre SGBD sans affecter
  6. le reste du code du projet.
  7. @author: idleman
  8. @version 2
  9. **/
  10. class Entity
  11. {
  12. public $debug = false,$pdo = null;
  13. public static $lastError = '';
  14. public static $lastQuery = '';
  15. function __construct(){
  16. $this->connect();
  17. }
  18. function connect(){
  19. $this->pdo = Database::instance();
  20. if(!isset($this->TABLE_NAME)) $this->TABLE_NAME = strtolower(get_called_class());
  21. }
  22. public function __toString(){
  23. foreach($this->toArray() as $key=>$value){
  24. echo $key.' : '.$value.','.PHP_EOL;
  25. }
  26. }
  27. public static function debug(){
  28. return array(self::$lastQuery,self::$lastError);
  29. }
  30. public function __sleep()
  31. {
  32. return array_keys($this->toArray());
  33. }
  34. public function __wakeup()
  35. {
  36. $this->connect();
  37. }
  38. function toArray(){
  39. $fields = array();
  40. foreach($this->fields as $field=>$type)
  41. $fields[$field]= $this->$field;
  42. return $fields;
  43. }
  44. function fromArray($array){
  45. foreach($array as $field=>$value)
  46. $this->$field = $value;
  47. }
  48. function sgbdType($type){
  49. $types = array();
  50. $types['string'] = $types['timestamp'] = $types['date'] = 'VARCHAR(255)';
  51. $types['longstring'] = 'TEXT';
  52. $types['key'] = 'INTEGER NOT NULL PRIMARY KEY';
  53. $types['object'] = $types['integer'] = 'bigint(20)';
  54. $types['boolean'] = 'INTEGER(1)';
  55. $types['blob'] = ' BLOB';
  56. $types['default'] = 'TEXT';
  57. return isset($types[$type]) ? $types[$type] : $types['default'];
  58. }
  59. public function closeDatabase(){
  60. //$this->close();
  61. }
  62. public static function tableName(){
  63. $class = get_called_class();
  64. $instance = new $class();
  65. return ENTITY_PREFIX.$instance->TABLE_NAME;
  66. }
  67. // GESTION SQL
  68. /**
  69. * Verifie l'existence de la table en base de donnée
  70. * @author Valentin CARRUESCO
  71. * @category manipulation SQL
  72. * @param <String> créé la table si elle n'existe pas
  73. * @return true si la table existe, false dans le cas contraire
  74. */
  75. public static function checkTable($autocreate = false){
  76. $class = get_called_class();
  77. $instance = new $class();
  78. $query = 'SELECT count(*) as numRows FROM sqlite_master WHERE type="table" AND name=?';
  79. $statement = $instance->customQuery($query,array($instance->tableName()));
  80. if($statement!=false){
  81. $statement = $statement->fetchArray();
  82. if($statement['numRows']==1){
  83. $return = true;
  84. }
  85. }
  86. if($autocreate && !$return) self::create();
  87. return $return;
  88. }
  89. public static function install($classDirectory){
  90. foreach(glob($classDirectory.DIRECTORY_SEPARATOR.'*.class.php') as $file){
  91. $infos = explode('.',basename($file));
  92. $class = array_shift($infos);
  93. if (!class_exists($class) || !method_exists ($class , 'create') || $class==get_class()) continue;
  94. $class::create();
  95. }
  96. }
  97. /**
  98. * Methode de creation de l'entité
  99. * @author Valentin CARRUESCO
  100. * @category manipulation SQL
  101. * @return Aucun retour
  102. */
  103. public static function create(){
  104. $class = get_called_class();
  105. $instance = new $class();
  106. $query = 'CREATE TABLE IF NOT EXISTS `'.ENTITY_PREFIX.$instance->TABLE_NAME.'` (';
  107. foreach($instance->fields as $field=>$type)
  108. $query .='`'.$field.'` '. $instance->sgbdType($type).' ,';
  109. $query = substr($query,0,strlen($query)-1);
  110. $query .= ');';
  111. $instance->customExecute($query);
  112. }
  113. public static function drop(){
  114. $class = get_called_class();
  115. $instance = new $class();
  116. $query = 'DROP TABLE `'.$instance->tableName().'`;';
  117. $instance->customExecute($query);
  118. }
  119. /**
  120. * Methode d'insertion ou de modifications d'elements de l'entité
  121. * @author Valentin CARRUESCO
  122. * @category manipulation SQL
  123. * @param Aucun
  124. * @return Aucun retour
  125. */
  126. public function save(){
  127. $data = array();
  128. if(isset($this->id) && $this->id>0){
  129. $query = 'UPDATE `'.ENTITY_PREFIX.$this->TABLE_NAME.'` SET ';
  130. foreach($this->fields as $field=>$type){
  131. $value = $this->{$field};
  132. $query .= '`'.$field.'`=?,';
  133. $data[] = $value;
  134. }
  135. $query = substr($query,0,strlen($query)-1);
  136. $data[] = $this->id;
  137. $query .= ' WHERE `id`=?;';
  138. }else{
  139. $query = 'INSERT INTO `'.$this->tableName().'`(';
  140. foreach($this->fields as $field=>$type){
  141. if($type!='key')
  142. $query .='`'.$field.'`,';
  143. }
  144. $query = substr($query,0,strlen($query)-1);
  145. $query .=')VALUES(';
  146. foreach($this->fields as $field=>$type){
  147. if($type=='key') continue;
  148. $query .='?,';
  149. $data[] = $this->{$field};
  150. }
  151. $query = substr($query,0,strlen($query)-1);
  152. $query .=');';
  153. }
  154. $this->customExecute($query,$data);
  155. $this->id = (!isset($this->id) || !(is_numeric($this->id))?$this->pdo->lastInsertId():$this->id);
  156. }
  157. /**
  158. * Méthode de modification d'éléments de l'entité
  159. * @author Valentin CARRUESCO
  160. * @category manipulation SQL
  161. * @param <Array> $colonnes=>$valeurs
  162. * @param <Array> $colonnes (WHERE) =>$valeurs (WHERE)
  163. * @param <String> $operation="=" definis le type d'operateur pour la requete select
  164. * @return Aucun retour
  165. */
  166. public static function change($columns,$columns2=null,$operation='='){
  167. $class = get_called_class();
  168. $instance = new $class();
  169. $data = array();
  170. $query = 'UPDATE `'.$instance->tableName().'` SET ';
  171. foreach ($columns as $column=>$value){
  172. $query .= '`'.$column.'`=?,';
  173. $data[] = $value;
  174. }
  175. $query = substr($query,0,strlen($query)-1);
  176. if($columns2!=null){
  177. $query .=' WHERE ';
  178. foreach ($columns2 as $column=>$value){
  179. $query .= '`'.$column.'`'.$operation.'?,';
  180. $data[] = $value;
  181. }
  182. $query = substr($query,0,strlen($query)-1);
  183. }
  184. $instance->customExecute($query,$data);
  185. }
  186. /**
  187. * Méthode de selection de tous les elements de l'entité
  188. * @author Valentin CARRUESCO
  189. * @category manipulation SQL
  190. * @param <String> $ordre=null
  191. * @param <String> $limite=null
  192. * @return <Array<Entity>> $Entity
  193. */
  194. public static function populate($order=null,$limit=null){
  195. $results = self::loadAll(array(),$order,$limit,'=');
  196. return $results;
  197. }
  198. /**
  199. * Méthode de selection multiple d'elements de l'entité
  200. * @author Valentin CARRUESCO
  201. * @category manipulation SQL
  202. * @param <Array> $colonnes (WHERE)
  203. * @param <Array> $valeurs (WHERE)
  204. * @param <String> $ordre=null
  205. * @param <String> $limite=null
  206. * @param <String> $operation="=" definis le type d'operateur pour la requete select
  207. * @return <Array<Entity>> $Entity
  208. */
  209. public static function loadAll($columns=array(),$order=null,$limit=null,$operation="=",$selColumn='*'){
  210. $objects = array();
  211. $whereClause = '';
  212. $data = array();
  213. if($columns!=null && sizeof($columns)!=0){
  214. $whereClause .= ' WHERE ';
  215. $i = false;
  216. foreach($columns as $column=>$value){
  217. if($i){$whereClause .=' AND ';}else{$i=true;}
  218. $whereClause .= '`'.$column.'`'.$operation.'?';
  219. $data[] = $value;
  220. }
  221. }
  222. $class = get_called_class();
  223. $instance = new $class();
  224. $query = 'SELECT '.$selColumn.' FROM `'.$instance->tableName().'` '.$whereClause.' ';
  225. if($order!=null) $query .='ORDER BY '.$order.' ';
  226. if($limit!=null) $query .='LIMIT '.$limit.' ';
  227. $query .=';';
  228. return $instance->customQuery($query,$data,true);
  229. }
  230. public static function loadAllOnlyColumn($selColumn,$columns,$order=null,$limit=null,$operation="="){
  231. $objects = self::loadAll($columns,$order,$limit,$operation,$selColumn);
  232. if(count($objects)==0)$objects = array();
  233. return $objects;
  234. }
  235. /**
  236. * Méthode de selection unique d'élements de l'entité
  237. * @author Valentin CARRUESCO
  238. * @category manipulation SQL
  239. * @param <Array> $colonnes (WHERE)
  240. * @param <Array> $valeurs (WHERE)
  241. * @param <String> $operation="=" definis le type d'operateur pour la requete select
  242. * @return <Entity> $Entity ou false si aucun objet n'est trouvé en base
  243. */
  244. public static function load($columns,$operation='='){
  245. $objects = self::loadAll($columns,null,'1',$operation);
  246. if(!isset($objects[0]))$objects[0] = false;
  247. return $objects[0];
  248. }
  249. /**
  250. * Méthode de selection unique d'élements de l'entité
  251. * @author Valentin CARRUESCO
  252. * @category manipulation SQL
  253. * @param <Array> $colonnes (WHERE)
  254. * @param <Array> $valeurs (WHERE)
  255. * @param <String> $operation="=" definis le type d'operateur pour la requete select
  256. * @return <Entity> $Entity ou false si aucun objet n'est trouvé en base
  257. */
  258. public static function getById($id,$operation='='){
  259. return self::load(array('id'=>$id),$operation);
  260. }
  261. /**
  262. * Methode de comptage des éléments de l'entité
  263. * @author Valentin CARRUESCO
  264. * @category manipulation SQL
  265. * @return<Integer> nombre de ligne dans l'entité'
  266. */
  267. public static function rowCount($columns=null)
  268. {
  269. $class = get_called_class();
  270. $instance = new $class();
  271. $whereClause ='';
  272. $data = array();
  273. if($columns!=null){
  274. $whereClause = ' WHERE ';
  275. $i=false;
  276. foreach($columns as $column=>$value){
  277. if($i){$whereClause .=' AND ';}else{$i=true;}
  278. $whereClause .= '`'.$column.'`=?';
  279. $data[] = $value;
  280. }
  281. }
  282. $query = 'SELECT COUNT(id) resultNumber FROM '.$instance->tableName().$whereClause;
  283. $execQuery = $instance->customQuery($query,$data);
  284. $row = $execQuery->fetch();
  285. return $row['resultNumber'];
  286. }
  287. /**
  288. * Methode de définition de l'éxistence d'un moins un des éléments spécifiés en base
  289. * @author Valentin CARRUESCO
  290. * @category manipulation SQL
  291. * @return<boolean> existe (true) ou non (false)
  292. */
  293. public static function exist($columns=null)
  294. {
  295. $result = self::rowCount($columns);
  296. return ($result!=0);
  297. }
  298. public static function deleteById($id){
  299. self::delete(array('id'=>$id));
  300. }
  301. /**
  302. * Méthode de supression d'elements de l'entité
  303. * @author Valentin CARRUESCO
  304. * @category manipulation SQL
  305. * @param <Array> $colonnes (WHERE)
  306. * @param <Array> $valeurs (WHERE)
  307. * @param <String> $operation="=" definis le type d'operateur pour la requete select
  308. * @return Aucun retour
  309. */
  310. public static function delete($columns,$operation='=',$limit=null){
  311. $class = get_called_class();
  312. $instance = new $class();
  313. $whereClause = '';
  314. $i=false;
  315. $data = array();
  316. foreach($columns as $column=>$value){
  317. if($i){$whereClause .=' AND ';}else{$i=true;}
  318. $whereClause .= '`'.$column.'`'.$operation.'?';
  319. $data[]=$value;
  320. }
  321. $query = 'DELETE FROM `'.ENTITY_PREFIX.$instance->TABLE_NAME.'` WHERE '.$whereClause.' '.(isset($limit)?'LIMIT '.$limit:'').';';
  322. $instance->customExecute($query,$data);
  323. }
  324. public function customExecute($query,$data = array()){
  325. self::$lastQuery = $query;
  326. $stm = $this->pdo->prepare($query);
  327. try{
  328. $stm->execute($data);
  329. }catch(Exception $e){
  330. self::$lastError = $this->pdo->errorInfo();
  331. throw new Exception($e->getMessage());
  332. }
  333. }
  334. public static function staticQuery($query,$data = array(),$fill = false){
  335. $class = get_called_class();
  336. $instance = new $class();
  337. return $instance->customQuery($query,$data,$fill);
  338. }
  339. public function customQuery($query,$data = array(),$fill = false){
  340. self::$lastQuery = $query;
  341. $results = $this->pdo->prepare($query);
  342. $results->execute($data);
  343. if(!$results){
  344. self::$lastError = $this->pdo->errorInfo();
  345. return false;
  346. }else{
  347. if(!$fill) return $results;
  348. $class = get_class($this);
  349. $objects = array();
  350. while($queryReturn = $results->fetch() ){
  351. $object = new $class();
  352. foreach($this->fields as $field=>$type){
  353. if(isset($queryReturn[$field]))
  354. $object->{$field} = $queryReturn[$field];
  355. }
  356. $objects[] = $object;
  357. unset($object);
  358. }
  359. return $objects == null?array() : $objects;
  360. }
  361. }
  362. public function __get($name)
  363. {
  364. $pos = strpos($name,'_object');
  365. if($pos!==false){
  366. $field = strtolower(substr($name,0,$pos));
  367. if(array_key_exists($field,$this->fields)){
  368. $class = ucfirst($field);
  369. return $class::getById($this->{$field});
  370. }
  371. }
  372. throw new Exception("Attribut ".get_class($this)."->$name non existant");
  373. }
  374. }
  375. ?>