ORM Commencé

This commit is contained in:
xdrm-brackets 2016-07-21 21:12:53 +02:00
parent 3cd8871406
commit 81c42a609f
10 changed files with 613 additions and 24 deletions

View File

@ -318,8 +318,7 @@
// Sur la même ligne répartis équitablement // Sur la même ligne répartis équitablement
& > span, & > span{
& > span.row{
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: space-around; justify-content: space-around;
@ -334,11 +333,6 @@
} }
} }
& > span.column{
flex-direction: row;
padding: 0 .5em;
}
button{ button{
flex: auto; flex: auto;
width: 5em; width: 5em;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -3,7 +3,7 @@
namespace manager; namespace manager;
class DataBase{ class Database{
/* ATTRIBUTS STATIQUES */ /* ATTRIBUTS STATIQUES */
public static $config_path = [ public static $config_path = [

View File

@ -83,6 +83,13 @@
// Mauvais chemin de template // Mauvais chemin de template
const UnknownTemplate = 21; const UnknownTemplate = 21;
/* Erreur de l'ORM */
// Table n'existe pas
const UnknownTable = 22;
// Pas permissions de lire le schéma
const NotAllowedSchema = 23;
/* Erreur au niveau javascript */ /* Erreur au niveau javascript */
//const JavascriptError = 20; // -> géré en js //const JavascriptError = 20; // -> géré en js

314
manager/ORM.php Normal file
View File

@ -0,0 +1,314 @@
<?php
use \manager\Database;
use \manager\ManagerError;
namespace manager;
// CLASSE MAITRE
class ORM{
// Constantes
const UNIQUE = 0x0d3f378e6a8;
// Informations de l'utilisateur
private $data;
public $error;
// Informations de la base de données
private $schema;
private static $database = 'stefproject';
/* CONSTRUCTEUR DE LA CLASSE
*
* @table<String> Nom de la table à selectionner
*
* @return this<ORM> Retourne une instance de l'ORM
*
*/
public function __construct($table_name){
/* [0] Initialisation des attributs
=========================================================*/
$this->init();
/* [1] On vérifie que la table existe
=========================================================*/
/* (1) Requête */
$checkTable = Database::getPDO()->query("SHOW tables FROM ".self::$database);
$checkTableResult = Database::delNumeric( $checkTable->fetchAll() );
/* (2) On met en forme les données */
$tables = [];
foreach($checkTableResult as $table)
$tables[] = $table['Tables_in_'.self::$database];
/* (3) Si n'existe pas, on renvoie une erreur */
if( !in_array($table_name, $tables) ){
$this->error = ManagerError::UnknownTable;
return;
}
/* (4) On enregistre les données */
$this->data['table'] = $table_name;
/* [2] Si la table existe, on récupère ses données
=========================================================*/
/* (1) On récupère les colonnes */
$getColumns = Database::getPDO()->query("SHOW columns FROM ".self::$database.'.'.$table_name);
$columnsResult = Database::delNumeric( $getColumns->fetchAll() );
/* (2) On met en forme les données */
$columns = [];
foreach($columnsResult as $col){
// On formatte le type //
$type = $col['Type'];
if( preg_match('/^(int|varchar|text)/i', $type, $m) )
$type = $m[1];
// On ajoute la colonne //
$columns[$col['Field']] = [
'type' => $type,
'primary' => $col['Key'] == 'PRI'
];
}
/* (3) Si on trouve rien, on envoie une erreur */
if( !is_array($columns) || count($columns) == 0 ){
$this->error = ManagerError::UnknownTable;
return;
}
/* (4) On enregistre les colonnes */
$this->schema['columns'] = $columns;
}
/* GESTION DES GETTERS dynamiques
*
*
*/
public function __call($method, $params){
// Si $this->data['table'] NULL
if( is_null($this->data['table']) ) return false;
/* [1] Getters dynamiques
=========================================================*/
if( preg_match('/^get(.+)$/', $method, $matches) )
return $this->dynamicGetter($matches[1], $params);
}
/* GETTERS DYNAMIQUES
*
* @keywords<String> Nom du getter du type 'getAll' ou 'getX' avec 'X' une colonne de la table en question
* @params<Array> Liste des arguments, $args[0] est la valeur du getter (sauf pour 'getAll')
*
* @return lines<Array> Retourne le résultat du fetchAll()
*
*/
private function dynamicGetter($selector, $params){
/* [3] On vérifie la requête
=========================================================*/
/* (1) On formatte la requête 'MyNewColumn' -> 'my_new_column' */
$column_name = '';
// On retire le By.... s'il y est
if( preg_match('/^By(.+)$/', $selector, $m) ) $selector = $m[1];
// On transforme les majuscules en _
for( $l = 0 ; $l < strlen($selector) ; $l++ ){
$letter = $selector[$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 trouve le type de getter */
$getAll = $column_name == 'all'; // Si 'getAll'
$getById = $column_name == 'id'; // Si 'getById'
$getSomething = count($params) > 0 && array_key_exists($column_name, $this->schema['columns']); // Si 'getX', et 'X' dans la liste des colonnes
/* (3) Et le type de résultat attendu */
$fetchUnique = $params[count($params)-1] == self::UNIQUE;
/* (4) Si ni 'getAll' ni 'getSomething' -> erreur */
if( !$getById && !$getAll && !$getSomething ) return false;
/* [4] On rédige la requête
=========================================================*/
$getRequestString = 'SELECT * FROM '.$this->data['table'];
/* (1) getById
---------------------------------------------------------*/
if( $getById ){
/* (1) On récupère les 'champs' formant la CLÉ PRIMAIRE */
$primary = [];
foreach($this->schema['columns'] as $k=>$v)
if( $v['primary'] ) $primary[] = $k;
/* (2) S'il manque un paramètre, on retourne une erreur */
if( count($params) < count($primary) )
return false;
/* (3) On ajoute les conditions pour chaque clé primaire */
foreach($primary as $i=>$primary_key)
if( $i == 0 ) $getRequestString .= ' WHERE '.$primary_key.' = :primary'.$i;
else $getRequestString .= ' AND '.$primary_key.' = :primary'.$i;
/* (2) get{Attribut}
---------------------------------------------------------*/
}else if( $getSomething )
$getRequestString .= ' WHERE '.$column_name.' = :value';
/* (3) getAll
---------------------------------------------------------*/
// Aucune condition
/* (4) Ordre de selection
---------------------------------------------------------*/
$getRequestString .= ' ORDER BY 1 ASC';
/* [5] On prépare la requête
=========================================================*/
$getRequest = Database::getPDO()->prepare($getRequestString);
/* [6] On exécute la requête
=========================================================*/
/* (1) getById
---------------------------------------------------------*/
if( $getById ){
/* (1) On ajoute les variables pour chaque valeur donnée */
$pdo_vars = [];
foreach($primary as $i=>$primary_key)
$pdo_vars[':primary'.$i] = $params[$i];
/* (2) On exécute la requête */
$getRequest->execute( $pdo_vars );
/* (2) get{Attribut}
---------------------------------------------------------*/
}else
// Valeur unique
$getRequest->execute([
':value' => $getSomething ? $params[0] : null
]);
/* [7] On récupère le résultat
=========================================================*/
/* (1) getById -> Réponse unique */
if( $getById ){
$result = $getRequest->fetch();
if( $result === false )
if( $fetchUnique ) return null;
else return [];
else
if( $fetchUnique ) return Database::delNumeric($result, true);
else return [Database::delNumeric($result, true)];
/* (2) Autre -> Réponse multiple */
}else{
$result = Database::delNumeric( $getRequest->fetchAll() );
if( $fetchUnique )
if( count($result) < 1 ) return null;
else return $result[0];
else return $result;
}
}
/* EFFACE/INITIALISE LES DONNEES DE L'ORM
*
*/
private function init(){
$this->data = [];
$this->schema = [];
}
};
// // USE CASE :: ACCESS TABLE
// ORM::Table = ORM::Table('user');
//
// // USE CASE :: getBy{ATTRIBUTE}
// ORM::Row = ORM::Table->getByUsername('someUsername'); // ORM_FETCH by default
// ORM::Row = ORM::Table->getByUsername('someUsername', ORM_FETCH);
// ORM::Column = ORM::Table->getByUsername('someUsername', ORM_FETCHALL);
//
// // USE CASE :: getById -> primary key(s)
// ORM::Row = ORM::Table->getById(5, 7); // because PRIMARY KEY is composed by '5' and '7'
//
// // USE CASE :: getAll
// ORM::Column = ORM::Table->getAll();
//
// // USE CASE :: select(FIELD)
// mixed = ORM::Row->select('username');
//
// // USE CASE :: select(FIELD1, FIELD2, ...)
// mixed = ORM::Row->select('id_user', 'username');
?>

78
manager/ORM/Row.php Normal file
View File

@ -0,0 +1,78 @@
<?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){}
}
?>

200
manager/ORM/Rows.php Normal file
View File

@ -0,0 +1,200 @@
<?php
namespace \manager\ORM;
class Rows{
/* Attributs */
private $where; // Tableau associatif contenant les conditions
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){
/* (2) On récupère les informations */
$this->schema = $schema;
}
/* 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){
/* [1] On récupère les clés primaires
=========================================================*/
$keys = [];
foreach($this->schema['columns'] as $k=>$v)
$keys[] = $k;
/* [2] Si clé simple
=========================================================*/
if( count($keys) == 1 ){
/* (1) Si type INT et pas numérique */
if( $this->schema['columns'][$keys]['type'] == 'int' && !is_numeric($primary[0]) )
return $this;
/* (2) Si type STRING et pas string */
if( $this->schema['columns'][$keys]['type'] == 'text' && !is_string($primary[0]) )
return $this;
/* (3) Si type OK, on enregistre la condition */
$this->where[$keys[0]] = $primary[0];
/* [3] Si clé composée
=========================================================*/
}else{
$defaultWhere = $this->where;
/* (1) Pour chaque clé, On vérifie les TYPES */
foreach($key as $i=>$key){
/* (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;
/* (4) Si type OK, on enregistre la condition */
$this->where[$keys[0]] = $a[0];
}
/* 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 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(){}
}
?>

View File

@ -7,7 +7,7 @@
use \manager\ManagerError; use \manager\ManagerError;
use \manager\Repo; use \manager\Repo;
use \manager\Database; use \manager\Database;
use \manager\View; use \manager\ORM\Row;
debug(); debug();
@ -338,5 +338,8 @@
debug(); debug();
$userFetch = new Row('user');
?> ?>

View File

@ -62,7 +62,7 @@
$selected = Database::delNumeric( $selReq->fetchAll() ); $selected = Database::delNumeric( $selReq->fetchAll() );
echo "<article class='inline-row'>"; echo "<article class='inline-row' style='border: 0; box-shadow: none;background: transparent;'>";
echo "<span>Machine</span>"; echo "<span>Machine</span>";
echo "<span>Dernière utilisation</span>"; echo "<span>Dernière utilisation</span>";
echo "<span>Conducteurs</span>"; echo "<span>Conducteurs</span>";
@ -75,13 +75,13 @@
echo "<span class='title'><span>#".$mac['name']."</span></span>"; echo "<span class='title'><span>#".$mac['name']."</span></span>";
echo "<span class='row'>"; echo "<span>";
echo "<span>".date('d/m/Y H:i:s', $mac['last'])."</span>"; echo "<span>".date('d/m/Y H:i:s', $mac['last'])."</span>";
echo "<span style='color:#aaa;'>Il y a xx jours et yy heures</span>"; echo "<span style='color:#aaa;'>Il y a xx jours et yy heures</span>";
echo "</span>"; echo "</span>";
echo "<span class='column'>"; echo "<span>";
echo "<span>".$mac['users']." conducteur(s)</span>"; echo "<span>".$mac['users']." conducteur(s)</span>";
echo "<span>".$mac['users']."</span>"; echo "<span>".$mac['users']."</span>";
echo "</span>"; echo "</span>";