ORM: fetch avec condition 'IN' ajoutée + Délégation au manager \manager\ORM\SQLBuilder

This commit is contained in:
xdrm-brackets 2016-07-24 12:00:49 +02:00
parent 9d6ad3bc36
commit 81ff8d158e
7 changed files with 270 additions and 224 deletions

View File

@ -1,78 +0,0 @@
<?php
// namespace \manager\ORM;
class Row{
/* Attributs */
private $data; // Tableau contenant les valeurs des champs
private $schema; // Tableau contenant les informations associées aux données
/* CONSTRUCTEUR
*
* @schema<Array> Tableau contenant les informations de la requête
*
*/
public function __construct($schema){
/* (1) On récupère les informations */
$this->schema = $schema;
}
/* RETOURNE UNIQUEMENT LES CHAMPS SELECTIONNES
*
* @fields<Array> Libellé du champ à afficher
*
* @return data<Array> Tableau contenant les champs sélectionnés
* @return data<mixed> Valeur du champ sélectionné (si 1 seul champ)
*
*/
public function select($fields){}
/* MODIFIE UNE ENTREE
*
* @updates<Array> Tableau associatif contenant les nouvelles valeurs
*
* @return this<Row> Retourne l'objet courant (modifié)
*
*/
public function edit($updates){}
/* SUPPRIME UNE ENTREE
*
* @return status<Boolean> Retourne si TRUE ou FALSE l'entrée a bien été supprimée
*
*/
public function delete(){}
/* SUIT UNE CLE ETRANGERE
*
* @foreign<String> Nom de la table dans laquelle la clé étrangère est PRIMAIRE
*
* @return associated<Row> Retourne une instance 'Row' associée à l'entrée en cours (Unique car primaire)
*
*/
public function associated($foreign){}
}
?>

View File

@ -3,19 +3,21 @@
namespace manager\ORM;
use \manager\Database;
use \manager\ORM\SQLBuilder;
class Rows{
/* CONSTANTES */
const COND_EQUAL = '=';
const COND_NOTEQ = '<>';
const COND_INF = '<';
const COND_SUP = '>';
const COND_INFEQ = '<=';
const COND_SUPEQ = '>=';
const COND_LIKE = 'LIKE';
const COND_EQUAL = '__=__';
const COND_NOTEQ = '__<>__';
const COND_INF = '__<__';
const COND_SUP = '__>__';
const COND_INFEQ = '__<=__';
const COND_SUPEQ = '__>=__';
const COND_LIKE = '__LIKE__';
const COND_IN = '__IN__';
const DEFAULT = '__DEFAULT__'; // Valeur DEFAULT (pour insertion)
@ -79,76 +81,62 @@
/* [2] Si clé simple
=========================================================*/
if( count($keys) == 1 ){
/* (1) On met au même format qu'une clé composée */
if( count($keys) == 1 )
$primary = [ $primary ];
/* (1) Si on a juste la valeur, on ajoute le type de condition */
if( !is_array($primary) )
$primary = [ $primary, self::COND_EQUAL ];
/* (2) Si type INT et pas numérique */
if( $this->schema['columns'][$keys[0]]['type'] == 'int' && !is_numeric($primary[0]) )
return $this;
/* (3) Si type FLOAT et pas numérique */
if( $this->schema['columns'][$keys[0]]['type'] == 'float' && !is_numeric($primary[0]) )
return $this;
/* (4) Si type STRING et pas string */
if( $this->schema['columns'][$keys[0]]['type'] == 'text' && !is_string($primary[0]) )
return $this;
/* (5) Si type OK, on enregistre la condition */
// {1} Si aucune condition pour ce champ, on crée un tableau //
if( !isset($this->where[$keys[0]]) )
$this->where[$keys[0]] = [];
// {2} On ajoute la condition //
$this->where[$keys[0]][] = $primary;
/* [3] Si clé composée
=========================================================*/
}else{
$defaultWhere = $this->where;
/* (1) Pour chaque clé, On vérifie les TYPES */
foreach($keys as $i=>$key){
$inCond = is_array($primary[$i]) && count($primary[$i]) >= 2 && is_array($primary[$i][0]) && $primary[$i][1] == self::COND_IN;
/* (2) Si c'est un paramètre seul, on ajoute par défaut self::COND_EQUAL */
/* (1) Si c'est une condition "IN"
---------------------------------------------------------*/
if( $inCond ){
/* (1) On vérifie le type de chaque valeur du IN */
$type = $this->schema['columns'][$key]['type'];
foreach($primary[$i][0] as $value){
if( $type == 'int' && !is_numeric($value) ){ $this->where = $defaultWhere; return $this; }
if( $type == 'float' && !is_numeric($value) ){ $this->where = $defaultWhere; return $this; }
if( in_array($type, ['text', 'varchar']) && !is_string($value) ){ $this->where = $defaultWhere; return $this; }
}
/* (2) Si c'est une condition "simple"
---------------------------------------------------------*/
}else{
/* (1) Si le type de condition est manquant, on met EQUAL par défaut */
if( !is_array($primary[$i]) )
$primary[$i] = [ $primary[$i], self::COND_EQUAL ];
/* (3) Si type INT et pas numérique */
if( $this->schema['columns'][$column_name]['type'] == 'int' && !is_numeric($primary[$i][0]) ){
$this->where = $defaultWhere; // On réinitialise les conditions si au moins 1 est fausse
return $this;
/* (2) On vérifie le type de chaque valeur */
$type = $this->schema['columns'][$key]['type'];
if( $type == 'int' && !is_numeric($primary[$i][0]) ){ $this->where = $defaultWhere; return $this; }
if( $type == 'float' && !is_numeric($primary[$i][0]) ){ $this->where = $defaultWhere; return $this; }
if( in_array($type, ['text', 'varchar']) && !is_string($primary[$i][0]) ){ $this->where = $defaultWhere; return $this; }
}
/* (4) Si type FLOAT et pas numérique */
if( $this->schema['columns'][$column_name]['type'] == 'float' && !is_numeric($primary[$i][0]) ){
$this->where = $defaultWhere; // On réinitialise les conditions si au moins 1 est fausse
return $this;
}
/* (5) Si type STRING et pas string */
if( $this->schema['columns'][$column_name]['type'] == 'text' && !is_string($primary[$i][0]) ){
$this->where = $defaultWhere; // On réinitialise les conditions si au moins 1 est fausse
return $this;
}
/* (6) Si type OK, on enregistre la condition */
// {1} Si aucune condition pour ce champ, on crée un tableau //
if( !isset($this->where[$key]) )
$this->where[$key] = [];
// {2} On ajoute la condition //
/* (7) On ajoute la condition */
$this->where[$key][] = $primary[$i];
}
}
/* [4] On renvoie l'object courant
@ -413,8 +401,8 @@
$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";
if( $c == 0 ) $requestS .= 'WHERE '.$this->schema['table'].'.'.$field.' '.substr($value[1], 2, -2).' :'.$this->schema['table'].'_x_'.$field.'_'.$cdt."\n";
else $requestS .= 'AND '.$this->schema['table'].'.'.$field.' '.substr($value[1], 2, -2).' :'.$this->schema['table'].'_x_'.$field.'_'.$cdt."\n";
$c++;
}
@ -437,8 +425,8 @@
$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";
if( $c2 == 0 ) $requestS .= "\tWHERE ".$rows->schema['table'].'.'.$field.' '.substr($value[1], 2, -2).' :'.$rows->schema['table'].'_x_'.$field.'_'.$cdt."\n";
else $requestS .= "\tAND ".$rows->schema['table'].'.'.$field.' '.substr($value[1], 2, -2).' :'.$rows->schema['table'].'_x_'.$field.'_'.$cdt."\n";
$c2++;
}
@ -627,8 +615,8 @@
$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";
if( $c == 0 ) $requestS .= 'WHERE '.$this->schema['table'].'.'.$field.' '.substr($value[1], 2, -2).' :'.$this->schema['table'].'_x_'.$field.'_'.$cdt."\n";
else $requestS .= 'AND '.$this->schema['table'].'.'.$field.' '.substr($value[1], 2, -2).' :'.$this->schema['table'].'_x_'.$field.'_'.$cdt."\n";
$c++;
}
@ -651,8 +639,8 @@
$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";
if( $c2 == 0 ) $requestS .= "\tWHERE ".$rows->schema['table'].'.'.$field.' '.substr($value[1], 2, -2).' :'.$rows->schema['table'].'_x_'.$field.'_'.$cdt."\n";
else $requestS .= "\tAND ".$rows->schema['table'].'.'.$field.' '.substr($value[1], 2, -2).' :'.$rows->schema['table'].'_x_'.$field.'_'.$cdt."\n";
$c2++;
}
@ -709,92 +697,72 @@
/* [1] On rédige la clause SELECT
=========================================================*/
/* (1) On initialise la requête */
$requestS = "SELECT ";
/* (1) On formatte les données */
$selectTables = [];
$c = 0;
/* (2) Sinon, on sélectionne les champs locaux */
foreach($this->select as $field){
if( $c == 0 ) $requestS .= $this->schema['table'].'.'.$field;
else $requestS .= ', '.$this->schema['table'].'.'.$field;
$c++;
}
/* (2) On ajoute les champs locaux */
$selectTables[$this->schema['table']] = $this->select;
/* (3) Sinon, on sélectionne les champs de jointure */
/* (3) On ajoute les champs des jointures */
foreach($this->joined as $rows)
foreach($rows->select as $field){
if( $c == 0 ) $requestS .= $rows->schema['table'].'.'.$field;
else $requestS .= ', '.$rows->schema['table'].'.'.$field;
$c++;
}
$selectTables[$rows->schema['table']] = $rows->select;
/* (4) On génère la clause SELECT */
$requestS = SQLBuilder::SELECT($selectTables)."\n";
/* [2] On rédige la clause FROM
========================================================*/
/* (1) Table locale */
$requestS .= "\nFROM ".$this->schema['table'];
/* (2) Tables de jointure */
foreach($this->joined as $j=>$rows)
$requestS .= ", ".$rows->schema['table'];
/* (3) Retour à la ligne */
$requestS .= "\n";
$requestS .= SQLBuilder::FROM( array_keys($selectTables) )."\n";
/* [5] On rédige la clause WHERE/AND
=========================================================*/
/* (0) On initialise le conteneur des variables "bindés" */
$binded = [];
/* (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";
if( $value[1] === self::COND_IN ) // Si condition IN
$requestS .= SQLBuilder::IN([$this->schema['table'], $field], $value[0], $c, $binded)."\n";
else // Sinon
$requestS .= SQLBuilder::WHERE([$this->schema['table'], $field], $value, $c, $binded)."\n";
$c++;
}
/* (2) On ajoute les jointures */
foreach($this->joined as $localField=>$rows){
foreach($this->joined as $localField=>$rows)
if( $c == 0 ) $requestS .= 'WHERE '.$this->schema['table'].'.'.$localField.' = '.$this->schema['columns'][$localField]['references'][0].'.'.$this->schema['columns'][$localField]['references'][1]."\n";
else $requestS .= 'AND '.$this->schema['table'].'.'.$localField.' = '.$this->schema['columns'][$localField]['references'][0].'.'.$this->schema['columns'][$localField]['references'][1]."\n";
$c++;
}
/* (3) On ajoute les conditions des jointures */
foreach($this->joined as $rows)
foreach($rows->where as $field=>$conditions)
foreach($conditions as $cdt=>$value){
if( $c == 0 ) $requestS .= 'WHERE '.$rows->schema['table'].'.'.$field.' '.$value[1].' :'.$rows->schema['table'].'_x_'.$field.'_'.$cdt."\n";
else $requestS .= 'AND '.$rows->schema['table'].'.'.$field.' '.$value[1].' :'.$rows->schema['table'].'_x_'.$field.'_'.$cdt."\n";
if( $value[1] === self::COND_IN ) // Si condition IN
$requestS .= SQLBuilder::IN([$rows->schema['table'], $field], $value[0], $c, $binded)."\n";
else // Sinon
$requestS .= SQLBuilder::WHERE([$rows->schema['table'], $field], $value, $c, $binded)."\n";
$c++;
}
/* [6] On exécute la requête et 'bind' les paramètres
/* [6] On exécute la requête
=========================================================*/
/* (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];
/* [6] On exécute la requête et retourne le résultat
/* [7] On exécute la requête et retourne le résultat
=========================================================*/
/* (1) On exécute la requête */
$request->execute($binded);

152
manager/ORM/SQLBuilder.php Normal file
View File

@ -0,0 +1,152 @@
<?php
namespace manager\ORM;
use \manager\Database;
use \manager\ORM\Rows;
class SQLBuilder{
/* CONSTRUIT LA REQUETE TEXTUELLE "SELECT" AVEC UNE LISTE DE CHAMPS
*
* @tables<Array> Liste de tables contenant des champs
*
* @return sql<String> Renvoie la clause remplie
*
*/
public static function SELECT($tables){
/* [0] Initialisation
=========================================================*/
$sql = 'SELECT ';
/* [1] On construit la requête
=========================================================*/
$c = 0;
foreach($tables as $table=>$fields)
foreach($fields as $field){
if( $c > 0 ) $sql .= ', ';
$sql .= $table.'.'.$field;
$c++;
}
return $sql;
}
/* CONSTRUIT LA REQUETE TEXTUELLE "FROM" AVEC UNE LISTE DE TABLES
*
* @tables<Array> Liste de tables
*
* @return sql<String> Renvoie la clause remplie
*
*/
public static function FROM($tables){
/* [0] Initialisation
=========================================================*/
$sql = 'FROM ';
/* [1] On construit la requête
=========================================================*/
$c = 0;
foreach($tables as $table){
if( $c > 0 ) $sql .= ', ';
$sql .= $table;
$c++;
}
return $sql;
}
/* CONSTRUIT LA REQUETE TEXTUELLE "IN" AVEC UNE LISTE DE TABLES
*
* @field<Array> Tableau contenant [table, field]
* @array<Array> Valeurs de la clause IN
* @offset<int> Permet de rendre la condition unique (nommage des variables)
* @binded<Arary> Tableau associatif contenant les variables "bindés" -> ajout des champs
*
* @return sql<String> Renvoie la clause remplie
*
*/
public static function IN($field, $array, $offset=0, &$binded){
/* [0] Initialisation
=========================================================*/
$sql = ( $offset == 0 ) ? 'WHERE ' : 'AND ';
/* [1] On construit la requête
=========================================================*/
/* (1) Champ */
$sql .= $field[0].'.'.$field[1].' IN (';
/* (2) Valeurs */
$c = 0;
foreach($array as $i=>$value){
if( $c > 0 ) $sql .= ', ';
$sql .= ':'.$field[0].'_x_'.$field[1].'_'.$offset.'_'.$i;
$binded[':'.$field[0].'_x_'.$field[1].'_'.$offset.'_'.$i] = $value;
$c++;
}
return $sql.")";
}
/* CONSTRUIT LA REQUETE TEXTUELLE "WHERE" AVEC UNE LISTE DE TABLES
*
* @field<Array> Tableau contenant [table, field]
* @valeur<Array> Valeurs de la clause WHERE [valeur, opérateur]
* @offset<int> Permet de rendre la condition unique (nommage des variables)
* @binded<Arary> Tableau associatif contenant les variables "bindés" -> ajout des champs
*
* @return sql<String> Renvoie la clause remplie
*
*/
public static function WHERE($field, $value, $offset=0, &$binded){
/* [0] Initialisation
=========================================================*/
$sql = ( $offset == 0 ) ? 'WHERE ' : 'AND ';
/* [1] On construit la requête
=========================================================*/
/* (1) Chamo */
$sql .= $field[0].'.'.$field[1].' ';
/* (2) Opérateur */
$sql .= substr($value[1], 2, -2).' ';
/* (3) Variable */
$sql .= ':'.$field[0].'_x_'.$field[1].'_'.$offset;
$binded[':'.$field[0].'_x_'.$field[1].'_'.$offset] = $value[0];
return $sql;
}
}
?>

View File

@ -357,7 +357,7 @@
/* [4] On récupère la liste des MODULES (puces)
=========================================================*/
$chipsReq = new Repo('chip/getAll');
$chipsReq = new Repo('chip/getAll', [$_SESSION['WAREHOUSE']['id']]);
$chips = ($chipsReq->error==0) ? $chipsReq->answer() : [];

View File

@ -4,13 +4,29 @@
use \manager\Database;
use \manager\Repo;
use \manager\ManagerError;
use \manager\repo\cluster as clusterRepo;
use \manager\ORM\Table;
use \manager\ORM\Rows;
class chip extends parentRepo{
protected static function table_name(){ static $table_name = 'chip'; return $table_name; }
/* RENVOIE LA LISTE DES CARTES/PUCES DISPONIBLES EN FONCTION DES MODULES DE L'ENTREPOT
*
* @return chips<Array> Liste des puces/cartes disponibles
*
*/
public static function getAll($id_warehouse){
/* [1] On récupère les modules de l'entrepot courant
=========================================================*/
$module = Table::get('module');
// ->where
/* [2] On retourne le résultat
=========================================================*/
}
}

View File

@ -98,6 +98,7 @@
/* [1] On récupère les modules
=========================================================*/
$module = Table::get('module')
->select('id_module')
->select('name');
$merge = Table::get('module_merge')

View File

@ -12,6 +12,7 @@
use \manager\ORM\Table;
use \manager\ORM\Rows;
use \manager\ORM\Row;
use \manager\ORM\SQLBuilder;
debug();
@ -344,23 +345,24 @@
/* [1] FETCH
=========================================================*/
// $warehouse =
// Table::get('warehouse') // Access to table 'warehouse'
// ->whereName(['stef-montauban', Rows::COND_NOTEQ]); // condition : name = 'my-warehouse'
//
//
// $myUser =
// Table::get('user') // Access to table 'user'
// ->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'
$warehouse =
Table::get('warehouse') // Access to table 'warehouse'
->whereName(['stef-montauban', Rows::COND_EQUAL]); // condition : name = 'my-warehouse'
$myUser =
Table::get('user') // Access to table 'user'
->whereId([100, Rows::COND_INF]) // PRIMARY KEY (other condition on same field)
->whereId([[1,4,6,9], Rows::COND_IN]) // PRIMARY KEY (other condition on same field)
->whereUsername(['%e%', 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
// SELECT
// ->fetch(); // Result
->fetch(); // Result
var_dump($myUser);
/* [2] Modification
=========================================================*/
@ -427,19 +429,4 @@
// ->delete();
$id_warehouse = 7;
$id_user_cluster = 2;
////////////////////////////
$module = Table::get('module')
->select('name');
$merge = Table::get('module_merge')
->whereIdWarehouse($id_warehouse)
->join('id_module', $module);
$modules = $merge->fetch();
var_dump($modules);
?>