From 4c0e2e284a29cc3bf174418cd355ba28c67b7375 Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Sat, 23 Jul 2016 11:55:54 +0200 Subject: [PATCH] =?UTF-8?q?ORM:=20Gestion=20de=20la=20modification=20(avec?= =?UTF-8?q?=20possibilit=C3=A9=20de=20jointures)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- manager/ORM/Rows.php | 147 ++++++++++++++++++++++++++++++++++++++---- manager/ORM/Table.php | 4 +- test/automate.php | 25 ++++--- 3 files changed, 152 insertions(+), 24 deletions(-) diff --git a/manager/ORM/Rows.php b/manager/ORM/Rows.php index 3b6de41..8c3263f 100644 --- a/manager/ORM/Rows.php +++ b/manager/ORM/Rows.php @@ -18,7 +18,6 @@ /* Attributs */ private $where; // Tableau associatif contenant les conditions - private $whereOrder; // Ordonnanciation des ET/OU des conditions private $select; // Tableau contenant la liste des champs à afficher private $unique; // VRAI si on attend une valeur unique private $schema; // Tableau contenant les informations associées aux données @@ -37,16 +36,13 @@ /* (2) On initialise les conditions */ $this->where = []; - /* (3) On initialise le conteneur de l'ordre des conditions */ - $this->whereOrder = []; - - /* (4) On initialise les champs à retourner */ + /* (3) On initialise les champs à retourner */ $this->select = []; - /* (5) On initialise le caractère 'unique' du résultat */ + /* (4) On initialise le caractère 'unique' du résultat */ $this->unique = false; - /* (6) On initialise les jointures */ + /* (5) On initialise les jointures */ $this->joined = []; } @@ -194,7 +190,7 @@ } /* (2) On vérifie que la colonne existe */ - if( !array_key_exists($column_name, $this->schema['columns']) ) + if( !isset($this->schema['columns'][$column_name]) ) return $this; // si n'existe pas, on ne fait rien @@ -256,7 +252,7 @@ /* (2) On vérifie que chaque champ existe, sinon on le retire */ foreach($fields as $f=>$field) - if( !array_key_exists($field, $this->schema['columns']) ) + if( !isset($this->schema['columns'][$field]) ) unset($fields[$f]); /* (3) Permet d'avoir les indices de 0 à count-1 */ @@ -345,14 +341,137 @@ - /* MODIFIE DES ENTREES + /* MODIFIE DES ENTREES (SANS MODIFICATION DE CLE PRIMAIRE POSSIBLE) * * @updates Tableau associatif contenant les nouvelles valeurs * - * @return this Retourne l'objet courant (modifié) + * @return updated Retourne si TRUE/FALSE la modification a bien été faite * */ - public function edit($updates){} + public function edit($updates){ + /* [0] Vérification des paramètres + =========================================================*/ + /* (1) Si c'est pas un tableau, erreur */ + if( !is_array($updates) ) + return $this; + + /* (2) On retire les champ inconnus / clés primaires */ + $cleared = []; + + // Pour chaque entrée du tableau + foreach($updates as $field=>$value) + if( isset($this->schema['columns'][$field]) && !$this->schema['columns'][$field]['primary'] ) // Champ existe et n'est pas clé primaire + $cleared[$field] = $value; + + /* (3) On vérifie les types des champs */ + foreach($cleared as $field=>$value){ + + $type = $this->schema['columns'][$field]['type']; + + // {1} Si de type INT/FLOAT et pas numérique, on retire le champ // + if( in_array($type, ['int', 'float']) && !is_numeric($value) ) + unset($cleared[$field]); + + // {2} Si de type TEXT/VARCHAR et pas string, on retire le champ // + if( in_array($type, ['text', 'varchar']) && !is_string($value) ) + unset($cleared[$field]); + + } + + /* (4) Si on a plus de champ, on retourne l'object courant */ + if( count($cleared) == 0 ) + return $this; + + + /* [1] Rédaction de la clause UPDATE + =========================================================*/ + /* (1) On initialise la requête */ + $requestS = "UPDATE ".$this->schema['table']."\n"; + + + + /* [2] Rédaction de la clause SET + =========================================================*/ + /* (5) On met tout les champs à modifier */ + $c = 0; + foreach($cleared as $field=>$value){ + if( $c == 0 ) $requestS .= 'SET '.$field.' = :update_'.$field; + else $requestS .= "\n, ".$field.' = :update_'.$field; + $c++; + } + + $requestS .= "\n"; + + + + /* [3] On rédige la clause WHERE/AND + =========================================================*/ + /* (1) On met les conditions locales */ + $c = 0; + foreach($this->where as $field=>$conditions) + foreach($conditions as $cdt=>$value){ + if( $c == 0 ) $requestS .= 'WHERE '.$this->schema['table'].'.'.$field.' '.$value[1].' :'.$this->schema['table'].'_x_'.$field.'_'.$cdt."\n"; + else $requestS .= 'AND '.$this->schema['table'].'.'.$field.' '.$value[1].' :'.$this->schema['table'].'_x_'.$field.'_'.$cdt."\n"; + + $c++; + } + + /* (2) On ajoute les jointures */ + foreach($this->joined as $localField=>$rows){ + if( $c == 0 ) $requestS .= 'WHERE '; + else $requestS .= 'AND '; + + // {1} Clause SELECT interne // + $requestS .= $this->schema['table'].'.'.$localField." = (\n\tSELECT "; + + // Jointure du SELECT, champ joint lié au champ local + $requestS .= $rows->schema['table'].'.'.$this->schema['columns'][$localField]['references'][1]."\n"; + + // {2} Clause FROM interne // + $requestS .= "\tFROM ".$this->schema['columns'][$localField]['references'][0]."\n"; + + // {3} Clause WHERE/AND interne // + $c2 = 0; + foreach($rows->where as $field=>$conditions) + foreach($conditions as $cdt=>$value){ + if( $c2 == 0 ) $requestS .= "\tWHERE ".$rows->schema['table'].'.'.$field.' '.$value[1].' :'.$rows->schema['table'].'_x_'.$field.'_'.$cdt."\n"; + else $requestS .= "\tAND ".$rows->schema['table'].'.'.$field.' '.$value[1].' :'.$rows->schema['table'].'_x_'.$field.'_'.$cdt."\n"; + $c2++; + } + + $requestS .= "\tLIMIT 1)\n"; + } + + + /* [4] On exécute la requête et 'bind' les paramètres + =========================================================*/ + /* (0) On prépare la requête */ + $request = Database::getPDO()->prepare($requestS.';'); + $binded = []; + + /* (1) On bind tous les paramètres locaux */ + foreach($this->where as $field=>$conditions) + foreach($conditions as $cdt=>$value) + $binded[':'.$this->schema['table'].'_x_'.$field.'_'.$cdt] = $value[0]; + + /* (3) On bind tous les paramètres des jointures */ + foreach($this->joined as $rows) + foreach($rows->where as $field=>$conditions) + foreach($conditions as $cdt=>$value) + $binded[':'.$rows->schema['table'].'_x_'.$field.'_'.$cdt] = $value[0]; + + /* (4) On bind les nouvelles valeurs */ + foreach($cleared as $field=>$value) + $binded[':update_'.$field] = $value; + + /* [6] On exécute la requête et retourne le résultat + =========================================================*/ + /* (1) On exécute la requête */ + $updated = $request->execute($binded); + + /* (2) On retourne l'état de la requête */ + return $updated; + } @@ -471,7 +590,7 @@ /* [6] On exécute la requête et 'bind' les paramètres =========================================================*/ /* (0) On prépare la requête */ - $request = Database::getPDO()->prepare($requestS); + $request = Database::getPDO()->prepare($requestS.';'); $binded = []; /* (1) On bind tous les paramètres locaux */ @@ -562,7 +681,7 @@ foreach($entry as $index=>$value) // Si dans le schéma on applique le type - if( array_key_exists($index, $this->schema['columns']) ){ + if( isset($this->schema['columns'][$index]) ){ if( $this->schema['columns'][$index]['type'] == 'int' ) $formatted[$i][$index] = intval( $value ); diff --git a/manager/ORM/Table.php b/manager/ORM/Table.php index 34a697b..5e31eac 100644 --- a/manager/ORM/Table.php +++ b/manager/ORM/Table.php @@ -62,8 +62,8 @@ foreach($columnsResult as $col){ // On formatte le type // $type = $col['Type']; - if( preg_match('/^(int|varchar|text)/i', $type, $m) ) - $type = ($m[1] == 'int') ? 'int' : 'text'; + if( preg_match('/^(int|float|varchar|text)/i', $type, $m) ) + $type = strtolower($m[1]); // On ajoute la colonne // $columns[$col['Field']] = [ diff --git a/test/automate.php b/test/automate.php index b0df116..ead930c 100755 --- a/test/automate.php +++ b/test/automate.php @@ -344,18 +344,27 @@ $warehouse = Table::get('warehouse') // Access to table 'warehouse' - ->getByName('stef-montauban'); // condition : name = 'my-warehouse' + ->whereName(['s%', Rows::COND_LIKE]); // condition : name = 'my-warehouse' + $myUser = Table::get('user') // Access to table 'user' - ->whereId([3, Rows::COND_SUP]) // PRIMARY KEY (if composed, all arguments in array) - ->whereId([100, Rows::COND_INF]) // PRIMARY KEY (if composed, all arguments in array) - ->whereUsername(['g%', Rows::COND_LIKE]) // Dynamic getter 'getByMySuperColumn' -> 'my_super_column' - ->select(['mail', 'username', 'firstname']) // Select clause - ->select('id_user') // Select clause (added) - ->join('id_warehouse', $warehouse) // joins warehouse (with name 'my-warehouse') to column 'id_warehouse' + ->whereId([3, Rows::COND_INF]) // PRIMARY KEY (if composed, all arguments in array) + // ->whereId([100, Rows::COND_INF]) // PRIMARY KEY (other condition on same field) + // ->whereUsername(['jo%', Rows::COND_LIKE]) // Dynamic getter 'getByMySuperColumn' -> 'my_super_column' + // ->select(['mail', 'username', 'firstname']) // Select clause + // ->select('id_user') // Select clause (added) + ->join('id_warehouse', $warehouse) // joins warehouse (with name 'my-warehouse') to column 'id_warehouse' // ->unique() // unique result - ->fetch(); // Result + + + // SELECT + // ->fetch(); // Result + + // UPDATE + ->edit([ + 'id_warehouse' => '8' + ]); var_dump($myUser);