SMMP/manager/ORM/Rows.php

428 lines
11 KiB
PHP
Raw Normal View History

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{
/* Attributs */
public $where; // Tableau associatif contenant les conditions
public $select; // Tableau contenant la liste des champs à afficher
public $unique; // VRAI si on attend une valeur unique
public $schema; // Tableau contenant les informations associées aux données
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 = [];
/* (3) On initialise les champs à retourner */
$this->select = [];
/* (4) On initialise le caractère 'unique' du résultat */
$this->unique = false;
2016-07-21 19:12:53 +00:00
}
/* RETOURNE LES ENTREES D'UNE TABLE AVEC LA CLE PRIMAIRE SPECIFIEE
*
* @primary<mixed> Clé primaire simple
* OU
* @primary<Array> Clé primaire composée
*
* @return Rows<Rows> Tableau contenant toutes les entrées de la table
*
*/
public function getById($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 ){
/* (1) Si type INT et pas numérique */
2016-07-21 20:05:30 +00:00
if( $this->schema['columns'][$keys[0]]['type'] == 'int' && !is_numeric($primary) )
2016-07-21 19:12:53 +00:00
return $this;
/* (2) Si type STRING et pas string */
2016-07-21 20:05:30 +00:00
if( $this->schema['columns'][$keys[0]]['type'] == 'text' && !is_string($primary) )
2016-07-21 19:12:53 +00:00
return $this;
/* (3) Si type OK, on enregistre la condition */
2016-07-21 20:05:30 +00:00
$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
/* (2) Si type INT et pas numérique */
if( $this->schema['columns'][$key]['type'] == 'int' && !is_numeric($primary[$i]) ){
$this->where = $defaultWhere; // On réinitialise les données si au moins 1 clé est fausse
return $this;
}
/* (3) Si type STRING et pas string */
if( $this->schema['columns'][$key]['type'] == 'text' && !is_string($primary[$i]) ){
$this->where = $defaultWhere; // On réinitialise les données si au moins 1 clé est fausse
return $this;
}
/* (3) Si type OK, on enregistre la condition */
$this->where[$key] = $primary[$i];
}
}
/* [4] On renvoie l'object courant
=========================================================*/
return $this;
}
/* GETTERS DYNAMIQUES
*
* @method<String> Nom de la méthode
* @parameters<Array> Tableau contenant les paramètres
*
* @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}'
=========================================================*/
if( !preg_match('/^getBy(.+)$/', $m, $regex) ) // si requête incorrecte, on ne fais rien
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 */
if( !array_key_exists($column_name, $this->schema['columns']) )
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;
/* (2) Si type INT et pas numérique */
if( $this->schema['columns'][$column_name]['type'] == 'int' && !is_numeric($a[0]) )
return $this;
/* (3) Si type STRING et pas string */
if( $this->schema['columns'][$column_name]['type'] == 'text' && !is_string($a[0]) )
return $this;
2016-07-21 20:05:30 +00:00
/* [3] Si type OK, on enregistre la condition
=========================================================*/
$this->where[$column_name] = $a[0];
2016-07-21 19:12:53 +00:00
2016-07-21 20:05:30 +00:00
return $this;
2016-07-21 19:12:53 +00:00
}
/* SELECTIONNE UNIQUEMENT LES CHAMPS SELECTIONNES
2016-07-21 19:12:53 +00:00
*
* @fields<Array> Libellé du champ à afficher
*
* @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=[]){
/* [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)
if( !array_key_exists($field, $this->schema['columns']) )
unset($fields[$f]);
/* (3) Permet d'avoir les indices de 0 à count-1 */
sort($fields);
/* [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;
}
/* 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;
}
/* MODIFIE DES ENTREES
*
* @updates<Array> Tableau associatif contenant les nouvelles valeurs
*
* @return this<Rows> Retourne l'objet courant (modifié)
*
*/
public function edit($updates){}
/* 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)
*
*/
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
/* [1] On rédige la requête
=========================================================*/
/* (1) On initialise la requête */
$requestS = "SELECT ";
/* (2) Si aucun champ, on sélectionne tous les champs */
if( count($this->select) == 0 )
2016-07-21 20:05:30 +00:00
$requestS .= "* ";
/* (3) Sinon, on sélectionne les champs que l'on veut */
else
foreach($this->select as $f=>$field)
2016-07-21 20:05:30 +00:00
if( $f == 0 ) $requestS .= $field;
else $requestS .= ', '.$field;
2016-07-21 19:12:53 +00:00
2016-07-21 20:05:30 +00:00
/* (4) Clause FROM */
$requestS .= "\nFROM ".$this->schema['table']."\n";
/* (5) On ajoute les conditions */
$c = 0;
foreach($this->where as $field=>$value){
if( $c == 0 ) $requestS .= ' WHERE '.$field.' = :'.$field."\n";
else $requestS .= ' AND '.$field.' = :'.$field."\n";
$c++;
}
/* (6) On prépare la requête */
$request = Database::getPDO()->prepare($requestS);
/* [5] On exécute la requête et 'bind' les paramètres
=========================================================*/
/* (1) On bind tous les paramètres */
$binded = [];
foreach($this->where as $field=>$value)
$binded[':'.$field] = $value;
/* (2) On exécute la requête */
$request->execute($binded);
/* [6] On retourne le résultat
=========================================================*/
/* (1) Si unique */
if( $unique )
return $this->format( $request->fetch() );
/* (2) Si tout */
return $this->format( $request->fetchAll() );
2016-07-21 19:12:53 +00:00
}
/* ON FORMATTE LES DONNEES DE SORTIE
2016-07-21 19:12:53 +00:00
*
* @data<Array> Données / Tableau de données
2016-07-21 19:12:53 +00:00
*
* @return formatted<Array> Données formattées / Tableau de données formatté
2016-07-21 19:12:53 +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
/* (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
/* (2) On regarde si c'est des données simples */
$twoDimensions = is_array($formatted[0]);
2016-07-21 19:12:53 +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
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
if( array_key_exists($index, $this->schema['columns']) ){
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
}
?>