2016-07-21 19:12:53 +00:00
|
|
|
<?php
|
|
|
|
|
2016-07-21 20:05:30 +00:00
|
|
|
namespace manager\ORM;
|
|
|
|
|
|
|
|
use \manager\Database;
|
2016-07-21 19:12:53 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Rows{
|
|
|
|
|
2016-07-23 07:42:35 +00:00
|
|
|
|
|
|
|
/* CONSTANTES */
|
|
|
|
const COND_EQUAL = '=';
|
2016-07-23 10:07:13 +00:00
|
|
|
const COND_NOTEQ = '<>';
|
2016-07-23 07:42:35 +00:00
|
|
|
const COND_INF = '<';
|
|
|
|
const COND_SUP = '>';
|
|
|
|
const COND_INFEQ = '<=';
|
|
|
|
const COND_SUPEQ = '>=';
|
2016-07-23 08:01:01 +00:00
|
|
|
const COND_LIKE = 'LIKE';
|
2016-07-23 07:42:35 +00:00
|
|
|
|
2016-07-21 19:12:53 +00:00
|
|
|
/* Attributs */
|
2016-07-23 08:12:53 +00:00
|
|
|
private $where; // Tableau associatif contenant les 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
|
|
|
|
private $joined; // Tableau contenant les Rows liés
|
2016-07-21 19:12:53 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* CONSTRUCTEUR
|
|
|
|
*
|
|
|
|
* @schema<Array> Tableau contenant les informations de la requête
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
public function __construct($schema){
|
2016-07-21 20:05:30 +00:00
|
|
|
/* (1) On récupère les informations */
|
2016-07-21 19:12:53 +00:00
|
|
|
$this->schema = $schema;
|
2016-07-21 20:05:30 +00:00
|
|
|
|
|
|
|
/* (2) On initialise les conditions */
|
|
|
|
$this->where = [];
|
2016-07-22 17:51:03 +00:00
|
|
|
|
2016-07-23 09:55:54 +00:00
|
|
|
/* (3) On initialise les champs à retourner */
|
2016-07-22 17:51:03 +00:00
|
|
|
$this->select = [];
|
2016-07-22 21:55:18 +00:00
|
|
|
|
2016-07-23 09:55:54 +00:00
|
|
|
/* (4) On initialise le caractère 'unique' du résultat */
|
2016-07-22 21:55:18 +00:00
|
|
|
$this->unique = false;
|
2016-07-22 22:41:38 +00:00
|
|
|
|
2016-07-23 09:55:54 +00:00
|
|
|
/* (5) On initialise les jointures */
|
2016-07-22 22:41:38 +00:00
|
|
|
$this->joined = [];
|
2016-07-21 19:12:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-07-23 08:12:53 +00:00
|
|
|
/* FILTRE LES ENTREES D'UNE TABLE AVEC LA CLE PRIMAIRE SPECIFIEE
|
2016-07-21 19:12:53 +00:00
|
|
|
*
|
|
|
|
* @primary<mixed> Clé primaire simple
|
|
|
|
* OU
|
|
|
|
* @primary<Array> Clé primaire composée
|
|
|
|
*
|
|
|
|
* @return Rows<Rows> Tableau contenant toutes les entrées de la table
|
|
|
|
*
|
|
|
|
*/
|
2016-07-23 08:12:53 +00:00
|
|
|
public function whereId($primary){
|
2016-07-21 20:05:30 +00:00
|
|
|
/* [0] Vérification des paramètres
|
|
|
|
=========================================================*/
|
|
|
|
if( $primary == null )
|
|
|
|
return $this;
|
|
|
|
|
2016-07-21 19:12:53 +00:00
|
|
|
/* [1] On récupère les clés primaires
|
|
|
|
=========================================================*/
|
|
|
|
$keys = [];
|
|
|
|
|
|
|
|
foreach($this->schema['columns'] as $k=>$v)
|
2016-07-21 20:05:30 +00:00
|
|
|
if( $v['primary'] ) $keys[] = $k;
|
2016-07-21 19:12:53 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* [2] Si clé simple
|
|
|
|
=========================================================*/
|
|
|
|
if( count($keys) == 1 ){
|
|
|
|
|
2016-07-23 07:42:35 +00:00
|
|
|
/* (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]) )
|
2016-07-21 19:12:53 +00:00
|
|
|
return $this;
|
|
|
|
|
2016-07-23 07:42:35 +00:00
|
|
|
/* (4) Si type STRING et pas string */
|
|
|
|
if( $this->schema['columns'][$keys[0]]['type'] == 'text' && !is_string($primary[0]) )
|
2016-07-21 19:12:53 +00:00
|
|
|
return $this;
|
|
|
|
|
2016-07-23 07:42:35 +00:00
|
|
|
/* (5) Si type OK, on enregistre la condition */
|
2016-07-23 08:01:01 +00:00
|
|
|
// {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;
|
2016-07-21 19:12:53 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* [3] Si clé composée
|
|
|
|
=========================================================*/
|
|
|
|
}else{
|
|
|
|
|
|
|
|
$defaultWhere = $this->where;
|
|
|
|
|
|
|
|
/* (1) Pour chaque clé, On vérifie les TYPES */
|
2016-07-21 20:05:30 +00:00
|
|
|
foreach($keys as $i=>$key){
|
2016-07-21 19:12:53 +00:00
|
|
|
|
2016-07-23 07:42:35 +00:00
|
|
|
|
|
|
|
/* (2) Si c'est un paramètre seul, on ajoute par défaut self::COND_EQUAL */
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* (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
|
2016-07-21 19:12:53 +00:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2016-07-23 07:42:35 +00:00
|
|
|
/* (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
|
2016-07-21 19:12:53 +00:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2016-07-23 07:42:35 +00:00
|
|
|
/* (6) Si type OK, on enregistre la condition */
|
2016-07-23 08:01:01 +00:00
|
|
|
// {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 //
|
|
|
|
$this->where[$key][] = $primary[$i];
|
2016-07-21 19:12:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* [4] On renvoie l'object courant
|
|
|
|
=========================================================*/
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-07-23 08:12:53 +00:00
|
|
|
/* FILTRAGE DYNAMIQUES
|
2016-07-21 19:12:53 +00:00
|
|
|
*
|
|
|
|
* @method<String> Nom de la méthode
|
2016-07-23 07:42:35 +00:00
|
|
|
* @parameter<mixed> Valeur du paramètre
|
|
|
|
* @parameter<Array> Valeur du paramètre + type de vérification (tableau)
|
2016-07-21 19:12:53 +00:00
|
|
|
*
|
|
|
|
* @return this<Rows> Retourne l'object courant
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
public function __call($m, $a){
|
|
|
|
/* [0] On vérifie que la requête est du type 'getBy{Attribute}'
|
|
|
|
=========================================================*/
|
2016-07-23 08:12:53 +00:00
|
|
|
if( !preg_match('/^where(.+)$/', $m, $regex) ) // si requête incorrecte, on ne fais rien
|
2016-07-21 19:12:53 +00:00
|
|
|
return $this;
|
|
|
|
|
|
|
|
|
|
|
|
/* [1] On récupère le nom de la colonne
|
|
|
|
=========================================================*/
|
|
|
|
$column_name = '';
|
|
|
|
|
|
|
|
/* (1) formatte la requête 'MyAttribute' -> 'my_attribute' */
|
|
|
|
for( $l = 0 ; $l < strlen($regex[1]) ; $l++ ){
|
|
|
|
$letter = $regex[1][$l];
|
|
|
|
|
|
|
|
// Si la lettre est en majuscule mais que c'est pas la première
|
|
|
|
if( strtoupper($letter) == $letter && $l > 0 )
|
|
|
|
$column_name .= '_';
|
|
|
|
|
|
|
|
$column_name .= strtolower($letter);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* (2) On vérifie que la colonne existe */
|
2016-07-23 09:55:54 +00:00
|
|
|
if( !isset($this->schema['columns'][$column_name]) )
|
2016-07-21 19:12:53 +00:00
|
|
|
return $this; // si n'existe pas, on ne fait rien
|
|
|
|
|
|
|
|
|
|
|
|
/* [2] On vérifie le type du paramètre
|
|
|
|
=========================================================*/
|
|
|
|
/* (1) Si aucun param, on quitte */
|
|
|
|
if( count($a) == 0 )
|
|
|
|
return $this;
|
|
|
|
|
2016-07-23 07:42:35 +00:00
|
|
|
/* (2) Si c'est un paramètre seul, on ajoute par défaut self::COND_EQUAL */
|
|
|
|
if( !is_array($a[0]) )
|
|
|
|
$a[0] = [ $a[0], self::COND_EQUAL ];
|
|
|
|
|
|
|
|
/* (3) Si type INT et pas numérique */
|
|
|
|
if( $this->schema['columns'][$column_name]['type'] == 'int' && !is_numeric($a[0][0]) )
|
|
|
|
return $this;
|
|
|
|
|
|
|
|
/* (4) Si type FLOAT et pas numérique */
|
|
|
|
if( $this->schema['columns'][$column_name]['type'] == 'float' && !is_numeric($a[0][0]) )
|
2016-07-21 19:12:53 +00:00
|
|
|
return $this;
|
|
|
|
|
2016-07-23 07:42:35 +00:00
|
|
|
/* (5) Si type STRING et pas string */
|
|
|
|
if( $this->schema['columns'][$column_name]['type'] == 'text' && !is_string($a[0][0]) )
|
2016-07-21 19:12:53 +00:00
|
|
|
return $this;
|
|
|
|
|
2016-07-21 20:05:30 +00:00
|
|
|
|
2016-07-23 07:42:35 +00:00
|
|
|
|
2016-07-21 20:05:30 +00:00
|
|
|
/* [3] Si type OK, on enregistre la condition
|
|
|
|
=========================================================*/
|
2016-07-23 08:01:01 +00:00
|
|
|
/* (1) Si aucune condition pour ce champ, on crée un tableau */
|
|
|
|
if( !isset($this->where[$column_name]) )
|
|
|
|
$this->where[$column_name] = [];
|
|
|
|
|
|
|
|
/* (2) On ajoute la condition */
|
|
|
|
$this->where[$column_name][] = $a[0];
|
|
|
|
|
|
|
|
|
2016-07-21 19:12:53 +00:00
|
|
|
|
2016-07-23 07:42:35 +00:00
|
|
|
// On retourne l'object courant
|
2016-07-21 20:05:30 +00:00
|
|
|
return $this;
|
2016-07-21 19:12:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-07-22 17:51:03 +00:00
|
|
|
/* SELECTIONNE UNIQUEMENT LES CHAMPS SELECTIONNES
|
2016-07-21 19:12:53 +00:00
|
|
|
*
|
|
|
|
* @fields<Array> Libellé du champ à afficher
|
|
|
|
*
|
2016-07-22 17:51:03 +00:00
|
|
|
* @return this<Rows> Retourne l'object courant
|
2016-07-21 19:12:53 +00:00
|
|
|
*
|
|
|
|
*/
|
2016-07-21 20:05:30 +00:00
|
|
|
public function select($fields=[]){
|
2016-07-22 17:51:03 +00:00
|
|
|
/* [1] On formatte les champs
|
2016-07-21 20:05:30 +00:00
|
|
|
=========================================================*/
|
|
|
|
/* (1) On met en tableau quoi qu'il en soit */
|
|
|
|
$fields = is_array($fields) ? $fields : [$fields];
|
|
|
|
|
|
|
|
/* (2) On vérifie que chaque champ existe, sinon on le retire */
|
|
|
|
foreach($fields as $f=>$field)
|
2016-07-23 09:55:54 +00:00
|
|
|
if( !isset($this->schema['columns'][$field]) )
|
2016-07-21 20:05:30 +00:00
|
|
|
unset($fields[$f]);
|
|
|
|
|
|
|
|
/* (3) Permet d'avoir les indices de 0 à count-1 */
|
|
|
|
sort($fields);
|
|
|
|
|
|
|
|
|
2016-07-22 17:51:03 +00:00
|
|
|
/* [2] On enregistre la liste des champs
|
|
|
|
=========================================================*/
|
|
|
|
foreach($fields as $f=>$field)
|
|
|
|
if( !in_array($field, $this->select) ) // On ajoute si pas déja
|
|
|
|
$this->select[] = $field;
|
|
|
|
|
|
|
|
|
|
|
|
/* [3] On retourne l'object courant
|
|
|
|
=========================================================*/
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-07-22 22:41:38 +00:00
|
|
|
/* JOINT UNE SECONDE TABLE ()
|
|
|
|
*
|
|
|
|
* @field<String> Nom d'une colonne
|
|
|
|
* @rows<Rows> Rows d'une autre table
|
|
|
|
*
|
|
|
|
* @return this<Rows> Retourne l'object courant
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
public function join($field, $rows){
|
|
|
|
/* [0] Vérification des paramètres
|
|
|
|
=========================================================*/
|
|
|
|
if( !is_string($field) || !($rows instanceof Rows) )
|
|
|
|
return $this;
|
|
|
|
|
|
|
|
|
|
|
|
/* [1] On vérifie que la clé étrangère est correcte
|
|
|
|
=========================================================*/
|
|
|
|
/* (1) On vérifie que la colonne existe et qu'elle est étrangère*/
|
|
|
|
if( !isset($this->schema['columns'][$field]['references']) )
|
|
|
|
return $this;
|
|
|
|
|
|
|
|
/* (2) On vérifie que la table de @rows est correcte */
|
|
|
|
if( $this->schema['columns'][$field]['references'][0] != $rows->schema['table'] )
|
|
|
|
return $this;
|
|
|
|
|
|
|
|
|
|
|
|
/* [2] On enregistre la référence
|
|
|
|
=========================================================*/
|
|
|
|
$this->joined[$field] = $rows;
|
|
|
|
|
|
|
|
|
|
|
|
/* [3] On retourne l'object courant
|
|
|
|
=========================================================*/
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-07-22 21:55:18 +00:00
|
|
|
/* PERMET DE DIRE QUE L'ON VEUT UN RESULTAT UNIQUE
|
|
|
|
*
|
|
|
|
* @return this<Rows> Retourne l'object courant
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
public function unique(){
|
|
|
|
/* [1] On enregistre le choix
|
|
|
|
=========================================================*/
|
|
|
|
$this->unique = true;
|
|
|
|
|
|
|
|
|
|
|
|
/* [2] On retourne l'object courant
|
|
|
|
=========================================================*/
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-07-23 09:55:54 +00:00
|
|
|
/* MODIFIE DES ENTREES (SANS MODIFICATION DE CLE PRIMAIRE POSSIBLE)
|
2016-07-22 17:51:03 +00:00
|
|
|
*
|
|
|
|
* @updates<Array> Tableau associatif contenant les nouvelles valeurs
|
|
|
|
*
|
2016-07-23 09:55:54 +00:00
|
|
|
* @return updated<Boolean> Retourne si TRUE/FALSE la modification a bien été faite
|
2016-07-22 17:51:03 +00:00
|
|
|
*
|
|
|
|
*/
|
2016-07-23 09:55:54 +00:00
|
|
|
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;
|
|
|
|
}
|
2016-07-22 17:51:03 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* SUPPRIME LES ENTREES
|
|
|
|
*
|
|
|
|
* @return status<Boolean> Retourne si TRUE ou FALSE les entrées ont bien été supprimées
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
public function delete(){}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* RETOURNE LES DONNEES / NULL si une erreur survient
|
|
|
|
*
|
|
|
|
* @unique<Boolean> VRAI si on veut un seul résultat (itérateur)
|
|
|
|
*
|
|
|
|
* @return data<Array> Tableau contenant les champs sélectionnés
|
|
|
|
* @return data<mixed> Valeur du champ sélectionné (si 1 seul champ)
|
|
|
|
*
|
|
|
|
*/
|
2016-07-22 21:55:18 +00:00
|
|
|
public function fetch($unique=null){
|
|
|
|
/* [0] Initialisation des paramètres
|
|
|
|
=========================================================*/
|
|
|
|
$unique = !is_bool($unique) ? $this->unique : $unique;
|
|
|
|
|
2016-07-21 20:05:30 +00:00
|
|
|
|
2016-07-22 22:41:38 +00:00
|
|
|
/* [1] On rédige la clause SELECT
|
2016-07-21 20:05:30 +00:00
|
|
|
=========================================================*/
|
|
|
|
/* (1) On initialise la requête */
|
|
|
|
$requestS = "SELECT ";
|
|
|
|
|
2016-07-22 22:41:38 +00:00
|
|
|
/* (2) Si aucun SELECT local, on prend tout */
|
|
|
|
$c = 0;
|
|
|
|
if( count($this->select) == 0 ){
|
|
|
|
$requestS .= $this->schema['table'].".*";
|
|
|
|
$c++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* (3) Si aucun SELECT de jointure, on prend tout */
|
|
|
|
foreach($this->joined as $rows)
|
|
|
|
if( count($rows->select) == 0 ){
|
|
|
|
if( $c == 0 ) $requestS .= $rows->schema['table'].".*";
|
|
|
|
else $requestS .= ', '.$rows->schema['table'].".*";
|
|
|
|
$c++;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* (5) 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++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* (5) Sinon, on sélectionne les champs de jointure */
|
|
|
|
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++;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-21 20:05:30 +00:00
|
|
|
|
2016-07-22 22:41:38 +00:00
|
|
|
/* [2] On rédige la clause FROM
|
|
|
|
========================================================*/
|
|
|
|
/* (1) Table locale */
|
|
|
|
$requestS .= "\nFROM ".$this->schema['table'];
|
2016-07-21 19:12:53 +00:00
|
|
|
|
2016-07-22 22:41:38 +00:00
|
|
|
/* (2) Tables de jointure */
|
|
|
|
foreach($this->joined as $j=>$rows)
|
|
|
|
$requestS .= ", ".$rows->schema['table'];
|
2016-07-21 20:05:30 +00:00
|
|
|
|
2016-07-22 22:41:38 +00:00
|
|
|
/* (3) Retour à la ligne */
|
|
|
|
$requestS .= "\n";
|
2016-07-21 20:05:30 +00:00
|
|
|
|
|
|
|
|
2016-07-22 22:41:38 +00:00
|
|
|
|
|
|
|
/* [5] On rédige la clause WHERE/AND
|
|
|
|
=========================================================*/
|
|
|
|
/* (1) On met les conditions locales */
|
2016-07-21 20:05:30 +00:00
|
|
|
$c = 0;
|
2016-07-23 08:01:01 +00:00
|
|
|
foreach($this->where as $field=>$conditions)
|
2016-07-21 20:05:30 +00:00
|
|
|
|
2016-07-23 08:01:01 +00:00
|
|
|
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++;
|
|
|
|
}
|
2016-07-21 20:05:30 +00:00
|
|
|
|
2016-07-22 22:41:38 +00:00
|
|
|
/* (2) On ajoute les jointures */
|
|
|
|
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++;
|
|
|
|
}
|
2016-07-21 20:05:30 +00:00
|
|
|
|
2016-07-22 22:41:38 +00:00
|
|
|
/* (3) On ajoute les conditions des jointures */
|
|
|
|
foreach($this->joined as $rows)
|
2016-07-23 08:01:01 +00:00
|
|
|
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";
|
2016-07-22 22:41:38 +00:00
|
|
|
|
2016-07-23 08:01:01 +00:00
|
|
|
$c++;
|
|
|
|
}
|
2016-07-21 20:05:30 +00:00
|
|
|
|
|
|
|
|
2016-07-22 22:41:38 +00:00
|
|
|
/* [6] On exécute la requête et 'bind' les paramètres
|
2016-07-21 20:05:30 +00:00
|
|
|
=========================================================*/
|
2016-07-22 22:41:38 +00:00
|
|
|
/* (0) On prépare la requête */
|
2016-07-23 09:55:54 +00:00
|
|
|
$request = Database::getPDO()->prepare($requestS.';');
|
2016-07-21 20:05:30 +00:00
|
|
|
$binded = [];
|
|
|
|
|
2016-07-22 22:41:38 +00:00
|
|
|
/* (1) On bind tous les paramètres locaux */
|
2016-07-23 08:01:01 +00:00
|
|
|
foreach($this->where as $field=>$conditions)
|
|
|
|
foreach($conditions as $cdt=>$value)
|
|
|
|
$binded[':'.$this->schema['table'].'_x_'.$field.'_'.$cdt] = $value[0];
|
2016-07-21 20:05:30 +00:00
|
|
|
|
2016-07-22 22:41:38 +00:00
|
|
|
/* (3) On bind tous les paramètres des jointures */
|
|
|
|
foreach($this->joined as $rows)
|
2016-07-23 08:01:01 +00:00
|
|
|
foreach($rows->where as $field=>$conditions)
|
|
|
|
foreach($conditions as $cdt=>$value)
|
|
|
|
$binded[':'.$rows->schema['table'].'_x_'.$field.'_'.$cdt] = $value[0];
|
2016-07-21 20:05:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2016-07-22 22:41:38 +00:00
|
|
|
/* [6] On exécute la requête et retourne le résultat
|
2016-07-21 20:05:30 +00:00
|
|
|
=========================================================*/
|
2016-07-22 22:41:38 +00:00
|
|
|
/* (1) On exécute la requête */
|
|
|
|
$request->execute($binded);
|
|
|
|
|
|
|
|
|
|
|
|
/* (2) Si unique */
|
2016-07-22 17:51:03 +00:00
|
|
|
if( $unique )
|
|
|
|
return $this->format( $request->fetch() );
|
|
|
|
|
2016-07-22 22:41:38 +00:00
|
|
|
/* (3) Si tout */
|
2016-07-22 17:51:03 +00:00
|
|
|
return $this->format( $request->fetchAll() );
|
2016-07-21 19:12:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-07-22 17:51:03 +00:00
|
|
|
|
|
|
|
/* ON FORMATTE LES DONNEES DE SORTIE
|
2016-07-21 19:12:53 +00:00
|
|
|
*
|
2016-07-22 17:51:03 +00:00
|
|
|
* @data<Array> Données / Tableau de données
|
2016-07-21 19:12:53 +00:00
|
|
|
*
|
2016-07-22 17:51:03 +00:00
|
|
|
* @return formatted<Array> Données formattées / Tableau de données formatté
|
2016-07-21 19:12:53 +00:00
|
|
|
*
|
|
|
|
*/
|
2016-07-22 17:51:03 +00:00
|
|
|
private function format($data){
|
|
|
|
/* [0] On initialise le processus
|
|
|
|
=========================================================*/
|
|
|
|
/* (0) Initialisation du retour */
|
|
|
|
$formatted = $data;
|
2016-07-21 19:12:53 +00:00
|
|
|
|
2016-07-22 17:51:03 +00:00
|
|
|
/* (1) On vérifie qu'il s'agit d'un tableau (non vide) */
|
|
|
|
if( !is_array($formatted) || count($formatted) < 1 )
|
|
|
|
return $formatted;
|
2016-07-21 19:12:53 +00:00
|
|
|
|
2016-07-22 17:51:03 +00:00
|
|
|
/* (2) On regarde si c'est des données simples */
|
|
|
|
$twoDimensions = is_array($formatted[0]);
|
2016-07-21 19:12:53 +00:00
|
|
|
|
2016-07-22 17:51:03 +00:00
|
|
|
/* (3) On regarde s'il s'agit d'un Tableau de données en bonne et due forme */
|
|
|
|
if( $twoDimensions ){
|
|
|
|
$sameKeys = true; // VRAI si chaque entrée a les mêmes clés
|
|
|
|
$last_keys = null; // Clés de l'entrée précédente
|
2016-07-21 19:12:53 +00:00
|
|
|
|
2016-07-22 17:51:03 +00:00
|
|
|
foreach($formatted as $i=>$entry){
|
|
|
|
if( !is_null($last_keys) && count(array_diff(array_keys($entry), $last_keys)) > 0 ){ // Si différent du précédent, ducoup on est pas bon
|
|
|
|
$sameKeys = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
$last_keys = array_keys($entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Si pas les mêmes clés, on a une erreur
|
|
|
|
if( !$sameKeys )
|
|
|
|
return $formatted;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* [1] On retire les doublons à indices numériques
|
|
|
|
=========================================================*/
|
|
|
|
/* (1) Si 1 dimensions, on met en 2 pour traiter tout de la même manière */
|
|
|
|
if( !$twoDimensions )
|
|
|
|
$formatted = [$formatted];
|
|
|
|
|
|
|
|
/* (2) On retire les indices numériques */
|
|
|
|
|
|
|
|
// Pour chaque entrée
|
|
|
|
foreach($formatted as $i=>$entry)
|
|
|
|
|
|
|
|
// Pour chaque champ
|
|
|
|
foreach($entry as $index=>$value)
|
|
|
|
|
|
|
|
// Si dans le schéma on applique le type
|
2016-07-23 09:55:54 +00:00
|
|
|
if( isset($this->schema['columns'][$index]) ){
|
2016-07-22 17:51:03 +00:00
|
|
|
|
|
|
|
if( $this->schema['columns'][$index]['type'] == 'int' )
|
|
|
|
$formatted[$i][$index] = intval( $value );
|
|
|
|
else if( $this->schema['columns'][$index]['type'] == 'float' )
|
|
|
|
$formatted[$i][$index] = floatval( $value );
|
|
|
|
|
|
|
|
}else // Si pas dans le schéma, on le retire
|
|
|
|
unset($formatted[$i][$index]);
|
|
|
|
|
|
|
|
|
|
|
|
/* (3) On remet 1 dimension si 1 dimension à la base */
|
|
|
|
if( !$twoDimensions )
|
|
|
|
$formatted = $formatted[0];
|
|
|
|
|
|
|
|
/* [2] On retourne le résultat
|
|
|
|
=========================================================*/
|
|
|
|
return $formatted;
|
|
|
|
|
|
|
|
}
|
2016-07-21 19:12:53 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
?>
|