Gestion des alias dans `orm/Rows` + Gestion de la reconnaissance des types des champs à partir du "vrai" champ concerné (fonctionne aussi avec les fonctions d'aggrégation)

This commit is contained in:
xdrm-brackets 2016-11-05 16:13:31 +01:00
parent fe569b5b31
commit a56bd2cc61
6 changed files with 185 additions and 89 deletions

View File

@ -141,7 +141,7 @@
ManagerError::setHttpCode($this->error); ManagerError::setHttpCode($this->error);
// Type de contenu // Type de contenu
// header('Content-Type: application/json'); header('Content-Type: application/json; charset=utf-8');
// On rajoute l'erreur au message // On rajoute l'erreur au message
$returnData = array_merge( $returnData = array_merge(

View File

@ -208,8 +208,10 @@
for( $i = 0 ; $i < count($fetchData) ; $i++ ) // pour tout les utilisateurs for( $i = 0 ; $i < count($fetchData) ; $i++ ) // pour tout les utilisateurs
foreach($fetchData[$i] as $col => $val){ // pour toutes les entrées foreach($fetchData[$i] as $col => $val){ // pour toutes les entrées
if( !\mb_detect_encoding($val, 'UTF-8') ) if( \mb_detect_encoding($val) === 'UTF-8' )
$fetchData[$i][$col] = utf8_encode($val); $fetchData[$i][$col] = utf8_encode($val);
else
$fetchData[$i][$col] = utf8_encode(utf8_decode($val));
if( is_int($col) ){ // Si indice numerique if( is_int($col) ){ // Si indice numerique
if( $nextEquivalent ) // Si suit un indice textuel if( $nextEquivalent ) // Si suit un indice textuel
@ -229,8 +231,10 @@
// on supprime les doublons des entrées (indice numérique) // on supprime les doublons des entrées (indice numérique)
foreach($fetchData as $i=>$val){ // pour toutes les entrées foreach($fetchData as $i=>$val){ // pour toutes les entrées
if( !\mb_detect_encoding($val, 'UTF-8') ) if( \mb_detect_encoding($val) === 'UTF-8' )
$fetchData[$i] = utf8_encode($val); $fetchData[$i] = utf8_encode($val);
else
$fetchData[$i] = utf8_encode(utf8_decode($val));
if( is_int($i) ){ // Si indice numerique if( is_int($i) ){ // Si indice numerique
if( $nextEquivalent ) // Si suit un indice textuel if( $nextEquivalent ) // Si suit un indice textuel

View File

@ -31,6 +31,10 @@
const SEL_DISTINCT = true; const SEL_DISTINCT = true;
// {3} Gestion du Order By //
const ORDER_ASC = '__ASC__';
const ORDER_DESC = '__DESC__';
// {3} Constantes d'insertion // // {3} Constantes d'insertion //
const INSERT_DEFAULT = '__DEFAULT__'; // Valeur DEFAULT (pour insertion) const INSERT_DEFAULT = '__DEFAULT__'; // Valeur DEFAULT (pour insertion)
@ -38,6 +42,7 @@
private $driver; // Database driver label private $driver; // Database driver label
private $where; // Tableau associatif contenant les conditions private $where; // Tableau associatif contenant les conditions
private $select; // Tableau contenant la liste des champs à afficher private $select; // Tableau contenant la liste des champs à afficher
private $orderby; // Tableau contenant la liste des orderby
private $unique; // VRAI si on attend une valeur unique private $unique; // VRAI si on attend une valeur unique
private $schema; // Tableau contenant les informations associées aux données private $schema; // Tableau contenant les informations associées aux données
private $joined; // Tableau contenant les Rows liés private $joined; // Tableau contenant les Rows liés
@ -50,7 +55,7 @@
* *
*/ */
public function __construct($schema, $driver=null){ public function __construct($schema, $driver=null){
/* (1) On enregistre le driver */ /* (1) Database Driver */
$this->driver = $driver; $this->driver = $driver;
/* (2) On récupère les informations */ /* (2) On récupère les informations */
@ -62,10 +67,13 @@
/* (4) On initialise les champs à retourner */ /* (4) On initialise les champs à retourner */
$this->select = []; $this->select = [];
/* (5) On initialise le caractère 'unique' du résultat */ /* (5) On initialise l'ordonnancement' */
$this->orderby = [];
/* (6) On initialise le caractère 'unique' du résultat */
$this->unique = false; $this->unique = false;
/* (6) On initialise les jointures */ /* (7) On initialise les jointures */
$this->joined = []; $this->joined = [];
} }
@ -240,11 +248,12 @@
* @field<String> Libellé du champ à afficher * @field<String> Libellé du champ à afficher
* @func<CONST> Fonction d'aggrégation (ou NULL) * @func<CONST> Fonction d'aggrégation (ou NULL)
* @distinct<Boolean> Clause DISTINCT * @distinct<Boolean> Clause DISTINCT
* @alias<String> Alias du champ
* *
* @return this<Rows> Retourne l'object courant * @return this<Rows> Retourne l'object courant
* *
*/ */
public function select($field=null, $func=null, $distinct=false){ public function select($field=null, $func=null, $distinct=false, $alias=null){
/* [1] On formatte les champs /* [1] On formatte les champs
=========================================================*/ =========================================================*/
/* (1) On vérifie le type de @field */ /* (1) On vérifie le type de @field */
@ -265,6 +274,9 @@
/* (4) On met la valeur par défaut à @distinct si type mauvais */ /* (4) On met la valeur par défaut à @distinct si type mauvais */
$distinct = !is_bool($distinct) ? false : $distinct; $distinct = !is_bool($distinct) ? false : $distinct;
/* (5) Si @alias incorrect, on met @field par défaut */
if( !is_string($alias) )
$alias = $field;
/* [2] On enregistre le champ /* [2] On enregistre le champ
=========================================================*/ =========================================================*/
@ -273,13 +285,13 @@
foreach($this->schema['columns'] as $f=>$c) foreach($this->schema['columns'] as $f=>$c)
if( !isset($this->select[$f]) ) if( !isset($this->select[$f]) )
$this->select[$f] = [$func, $distinct]; $this->select[$f] = [$func, $distinct, $alias];
/* (2) Si aucun SELECT pour ce champ, on le crée */ /* (2) Si aucun SELECT pour ce champ, on le crée */
}else{ }else{
if( !isset($this->select[$field]) ) if( !isset($this->select[$field]) )
$this->select[$field] = [$func, $distinct]; $this->select[$field] = [$func, $distinct, $alias];
} }
@ -289,6 +301,48 @@
} }
/* SELECTIONNE L'ORDONNANCEMENT DES RESULTATS
*
* @field<String> Libellé du champ à afficher
* @order<CONST> Gestion de l'ordre ASC/DESC (ou NULL)
*
* @return this<Rows> Retourne l'object courant
*
*/
public function orderby($field=null, $order=null){
/* [1] On formatte les champs
=========================================================*/
/* (1) On vérifie le type de @field */
if( !is_string($field) )
return $this;
/* (2) On vérifie que la colonne @field existe, sinon on quitte */
if( !isset($this->schema['columns'][$field]) && $field != '*' )
return $this;
/* (3) On vérifie @order */
$orderList = [self::ORDER_ASC, self::ORDER_DESC];
// Valeur si NULL
$order = is_null($order) ? $orderList[0] : $order;
// Si ordre non référencée, on quitte
if( !in_array($order, $orderList) )
return $this;
/* [2] On enregistre le champ
=========================================================*/
/* (1) On crée le ORDER_BY pour ce champ */
$this->orderby[$field] = $order;
/* [3] On retourne l'object courant
=========================================================*/
return $this;
}
/* JOINT UNE SECONDE TABLE () /* JOINT UNE SECONDE TABLE ()
* *
* @localField<String> Nom d'une colonne locale * @localField<String> Nom d'une colonne locale
@ -513,7 +567,6 @@
return $updated; return $updated;
} }
/* AJOUTE UNE ENTREE DANS LA TABLE /* AJOUTE UNE ENTREE DANS LA TABLE
* *
* @entry<Array> Tableau associatif de la forme (colonne => valeur) * @entry<Array> Tableau associatif de la forme (colonne => valeur)
@ -748,7 +801,6 @@
$joinedFetched[$field] = $data['object']->fetch(false); $joinedFetched[$field] = $data['object']->fetch(false);
/* [1] On rédige la clause SELECT /* [1] On rédige la clause SELECT
=========================================================*/ =========================================================*/
/* (1) On formatte les données */ /* (1) On formatte les données */
@ -774,7 +826,6 @@
$requestS['SELECT'] = SQLBuilder::SELECT($selectTables); $requestS['SELECT'] = SQLBuilder::SELECT($selectTables);
/* [2] On rédige la clause FROM /* [2] On rédige la clause FROM
========================================================*/ ========================================================*/
/* (0) On initialise la clause */ /* (0) On initialise la clause */
@ -790,7 +841,6 @@
$requestS['FROM'] = array_merge($data['request']['FROM'], $requestS['FROM']); $requestS['FROM'] = array_merge($data['request']['FROM'], $requestS['FROM']);
/* [5] On rédige la clause WHERE/AND /* [5] On rédige la clause WHERE/AND
=========================================================*/ =========================================================*/
/* (1) On met les conditions locales */ /* (1) On met les conditions locales */
@ -823,8 +873,6 @@
} }
/* [6] Clause GROUP BY /* [6] Clause GROUP BY
=========================================================*/ =========================================================*/
/* (0) On initialise la liste des @rows non aggrégés */ /* (0) On initialise la liste des @rows non aggrégés */
@ -856,7 +904,27 @@
if( count($groupBy) > 0) if( count($groupBy) > 0)
$requestS['GROUPBY'] = SQLBuilder::GROUPBY($groupBy); $requestS['GROUPBY'] = SQLBuilder::GROUPBY($groupBy);
/* [6] Clause ORDER BY
=========================================================*/
/* (1) On formatte les données */
$orderTables = [];
/* (2) On ajoute les champs locaux */
if( count($this->orderby) > 0 )
$orderTables[$this->schema['table']] = $this->orderby;
/* (4) On ajoute les champs des jointures (récursif)*/
foreach($joinedFetched as $field=>$data){
foreach($data['request']['ORDERBY'] as $table=>$fields) // pour chaque ensemble de champ de chaque table
foreach($fields as $field=>$orderBy) // Pour chaque orderby de chaque champ
if( count($orderBy) > 0 )
$orderTables[$table][$field] = $orderBy;
}
/* (3) On génère la clause SELECT */
$requestS['ORDERBY'] = SQLBuilder::ORDERBY($orderTables);
/* [6] Clause LIMIT /* [6] Clause LIMIT
=========================================================*/ =========================================================*/
@ -876,6 +944,7 @@
$request = DatabaseDriver::getPDO($this->driver)->prepare($requestString); $request = DatabaseDriver::getPDO($this->driver)->prepare($requestString);
// var_dump($requestString); // var_dump($requestString);
/* [8] On exécute la requête et retourne le résultat /* [8] On exécute la requête et retourne le résultat
=========================================================*/ =========================================================*/
/* (1) On exécute la requête */ /* (1) On exécute la requête */
@ -937,32 +1006,45 @@
if( !$twoDimensions ) if( !$twoDimensions )
$formatted = [$formatted]; $formatted = [$formatted];
/* (2) On retire les indices numériques */
/* (2) On récupère les noms des champs à partir des select (alias) */
// {1} On récupère les colonnes locales // // {1} On récupère les colonnes locales //
$existingColumns = $this->schema['columns']; $existingColumns = [];
foreach($this->select as $field=>$data)
$existingColumns[$data[2]] = $this->schema['columns'][$field];
// {2} On ajoute les colonnes des jointures // // {2} On ajoute les colonnes des jointures //
foreach($this->joined as $j) foreach($this->joined as $j)
$existingColumns = array_merge( $existingColumns, $j['object']->schema['columns'] ); foreach($j['object']->select as $field=>$data)
$existingColumns[$data[2]] = $j['object']->schema['columns'][$field];
// {3} On vérifie chaque clé, si c'est une colonne qui existe // // {3} On vérifie chaque clé, si c'est une colonne qui existe //
foreach($formatted as $i=>$entry) foreach($formatted as $i=>$entry)
// Pour chaque champ // Pour chaque champ
foreach($entry as $index=>$value) foreach($entry as $index=>$value){
// Si la colonne existe on applique le type // Si la colonne existe on applique le type
if( isset($existingColumns[$index]) ){ if( isset($existingColumns[$index]) ){
if( $existingColumns[$index]['type'] == 'int' ) if( $existingColumns[$index]['type'] == 'int' )
$formatted[$i][$index] = intval( $value ); $formatted[$i][$index] = intval( $value );
else if( $existingColumns[$index]['type'] == 'float' ) elseif( $existingColumns[$index]['type'] == 'float' )
$formatted[$i][$index] = floatval( $value ); $formatted[$i][$index] = floatval( $value );
// String utf8 management
elseif( \mb_detect_encoding($value) === 'UTF-8' )
$formatted[$i][$index] = utf8_encode($value);
else
$formatted[$i][$index] = utf8_encode(utf8_decode($value));
// Si pas non plus une aggrégation et si indice numérique, on le retire // Si pas non plus une aggrégation et si indice numérique, on le retire
}else if( !preg_match('/^agg_.+/', $index) && is_numeric($index) ) }else if( !preg_match('/^agg_.+/', $index) && is_numeric($index) )
unset($formatted[$i][$index]); unset($formatted[$i][$index]);
}
/* (3) On remet 1 dimension si 1 dimension à la base */ /* (3) On remet 1 dimension si 1 dimension à la base */
if( !$twoDimensions ) if( !$twoDimensions )

View File

@ -21,10 +21,16 @@
} }
/* CONSTRUIT LA REQUETE FORMATTEE "ORDER BY" AVEC UNE LISTE DE CHAMPS
*
* @tables<Array> Liste de champs : [table => fields]
*
* @return sql<Array> Renvoie un tableau formatté
*
*/
public static function ORDERBY($tables){
return $tables;
}
/* CONSTRUIT LA REQUETE FORMATTEE "GROUP BY" AVEC UNE LISTE DE CHAMPS /* CONSTRUIT LA REQUETE FORMATTEE "GROUP BY" AVEC UNE LISTE DE CHAMPS
* *
@ -38,10 +44,6 @@
} }
/* CONSTRUIT LA REQUETE FORMATTEE "FROM" AVEC UNE LISTE DE TABLES /* CONSTRUIT LA REQUETE FORMATTEE "FROM" AVEC UNE LISTE DE TABLES
* *
* @tables<Array> Liste de tables OU SQL PUR * @tables<Array> Liste de tables OU SQL PUR
@ -54,10 +56,6 @@
} }
/* CONSTRUIT LA REQUETE FORMATTEE "UPDATE" AVEC LA TABLE EN QUESTION /* CONSTRUIT LA REQUETE FORMATTEE "UPDATE" AVEC LA TABLE EN QUESTION
* *
* @table<String> Table en question * @table<String> Table en question
@ -70,10 +68,6 @@
} }
/* CONSTRUIT LA REQUETE FORMATTEE "DELETE" AVEC LA TABLE EN QUESTION /* CONSTRUIT LA REQUETE FORMATTEE "DELETE" AVEC LA TABLE EN QUESTION
* *
* @table<String> Table en question * @table<String> Table en question
@ -86,10 +80,6 @@
} }
/* CONSTRUIT LA REQUETE TEXTUELLE "IN" AVEC UNE LISTE DE TABLES /* CONSTRUIT LA REQUETE TEXTUELLE "IN" AVEC UNE LISTE DE TABLES
* *
* @field<Array> Tableau contenant [table, field] * @field<Array> Tableau contenant [table, field]
@ -123,13 +113,7 @@
} }
return $sql.")"; return $sql.")";
} } /* CONSTRUIT LA REQUETE TEXTUELLE "WHERE" AVEC UNE LISTE DE TABLES
/* CONSTRUIT LA REQUETE TEXTUELLE "WHERE" AVEC UNE LISTE DE TABLES
* *
* @field<Array> Tableau contenant [table, field] * @field<Array> Tableau contenant [table, field]
* @valeur<Array> Valeurs de la clause WHERE [valeur, opérateur] * @valeur<Array> Valeurs de la clause WHERE [valeur, opérateur]
@ -160,13 +144,7 @@
return $sql; return $sql;
} } /* CONSTRUIT LA REQUETE FORMATTEE "SET" AVEC UNE LISTE DE TABLES
/* CONSTRUIT LA REQUETE FORMATTEE "SET" AVEC UNE LISTE DE TABLES
* *
* @values<Array> Tableau de la forme [ field=>value, field2=>value2 ] * @values<Array> Tableau de la forme [ field=>value, field2=>value2 ]
* @bound<Arary> Tableau associatif contenant les variables "bindés" -> ajout des champs * @bound<Arary> Tableau associatif contenant les variables "bindés" -> ajout des champs
@ -196,13 +174,7 @@
} }
return $sql; return $sql;
} } /* CONSTRUIT LA REQUETE FORMATTEE "LIMIT" AVEC UN NOMBRE D'ENTREES
/* CONSTRUIT LA REQUETE FORMATTEE "LIMIT" AVEC UN NOMBRE D'ENTREES
* *
* @count<int> Nombre limite * @count<int> Nombre limite
* *
@ -223,18 +195,6 @@
return $sql; return $sql;
} }
/* CONSTRUIT LA REQUETE A PARTIR D'UNE REQUETTE FORMATTEE /* CONSTRUIT LA REQUETE A PARTIR D'UNE REQUETTE FORMATTEE
* *
* @request<Arary> Requête formattée * @request<Arary> Requête formattée
@ -258,7 +218,7 @@
case 'SELECT': case 'SELECT':
$sql .= "SELECT "; $sql .= "SELECT ";
$c = 0; $c = 0;
foreach($statements as $table=>$fields) foreach($statements as $table=>$fields){
foreach($fields as $field=>$select){ foreach($fields as $field=>$select){
/* (1) On construit le nom du champ */ /* (1) On construit le nom du champ */
@ -274,7 +234,11 @@
/* (4) On ajoute l'alias */ /* (4) On ajoute l'alias */
if( isset($select[0]) && !is_null($select[0]) ) // si défini
if( isset($select[2]) )
$fieldStr = "$fieldStr as ".$select[2];
// si func et non défini
elseif( isset($select[0]) && !is_null($select[0]) )
$fieldStr = "$fieldStr as agg_$field"; $fieldStr = "$fieldStr as agg_$field";
else else
$fieldStr = "$fieldStr"; $fieldStr = "$fieldStr";
@ -283,6 +247,7 @@
$c++; $c++;
} }
}
$sql .= "\n"; $sql .= "\n";
break; break;
@ -336,7 +301,6 @@
case 'UPDATE': case 'UPDATE':
$sql .= "UPDATE $statements\n"; $sql .= "UPDATE $statements\n";
break; break;
break;
/* (7) Clause SET /* (7) Clause SET
@ -364,17 +328,35 @@
$sql .= "\n"; $sql .= "\n";
break; break;
/* (9) Clause ORDER BY
---------------------------------------------------------*/
case 'ORDERBY':
// si aucun ORDER BY, on quitte
if( count($statements) == 0 )
continue;
$sql .= 'ORDER BY ';
$c = 0;
foreach($statements as $table=>$fields)
foreach($fields as $field=>$order){
if( $c > 0 ) $sql .= ', ';
$sql .= "$table.$field ". substr($order, 2, -2);
$c++;
}
$sql .= "\n";
break;
} }
} }
/* [2] On retourne le résultat /* [2] On retourne le résultat
=========================================================*/ =========================================================*/
return $sql; return $sql;

View File

@ -81,7 +81,7 @@
$R->get('(.+)@([a-f0-9]{6})(\.svg)', function($matches){ $R->get('(.+)@([a-f0-9]{6})(\.svg)', function($matches){
$path = __PUBLIC__.'/'.$matches[0].$matches[2]; $path = __PUBLIC__.'/'.$matches[0].$matches[2];
header('Content-Type: image/svg+xml'); header('Content-Type: image/svg+xml; charset=utf-8');
// On crée la partie ajoutée // On crée la partie ajoutée
$stylesheet = "\n<style type='text/css'>\n"; $stylesheet = "\n<style type='text/css'>\n";

View File

@ -10,19 +10,47 @@
use \database\core\Repo; use \database\core\Repo;
use \database\core\DatabaseDriver; use \database\core\DatabaseDriver;
use \orm\core\Table; use \orm\core\Table;
use \orm\core\Rows;
debug(); debug();
/* [2] Requests on lab-surveys /* [2] Requests on lab-surveys
=========================================================*/ =========================================================*/
$lisst = Table::get('laboratoires', 'lab-surveys')
// ->select('idLaboratoire')
->whereIntitule('LISST');
$etudes = Table::get('etudes', 'lab-surveys') $etudes = Table::get('etudes', 'lab-surveys')
->select('*'); // ->select('idEtude')
->join('idLaboratoire', $lisst)
->orderby('idEtude')
->unique();
var_dump($etudes->fetch()); $fiches = Table::get('fiches', 'lab-surveys')
->select('idFiche')
->orderby('idFiche')
->join('idEtude', $etudes);
$questions = Table::get('questionsFiches', 'lab-surveys')
->select('idQuestionFiche')
->select('intitule', null, null, 'question')
->orderby('idQuestionFiche')
// ->unique()
->join('idFiche', $fiches);
$repAtt = Table::get('reponsesAttenduesFiches', 'lab-surveys')
->select('intitule', Rows::SEL_CONCAT, null, 'reponses')
->orderby('idReponseAttendueFiche')
->join('idQuestionFiche', $questions);
$sujets = Table::get('sujets', 'lab-surveys')
->select('idSujet')
->select('pseudo');
var_dump( $v=$repAtt->fetch() );
?> ?>