Bonjour à tous,
Je sais que j'ai déjà posté un topic avec le même nom (http://www.grafikart.fr/forum/topics/15240) mais du coup grâce à votre aide je souhaitez vous faire partager la première version de ma classe PHP que j'ai pu faire grâce à votre aide.
https://github.com/babeuloula/DynamicTable
<?php
/**
* Permet de créer dynamiquement des bases de données et de les modifier
*/
class DynamicTable {
private $table;
private $db;
/**
* Permet d'initialiser le module de table dynamique
* @param string $table nom de la table
* @param PDO $pdo instance d'une connexion mysql via PDO
*/
public function __construct($table, $pdo) {
$this->table = $this->replaceChars($table);
$this->db = $pdo;
}
/**
* Permet de créer la table
* @param array $rows contenu de la table array('title' => titre, 'type' => type, 'comment' => commentaire)
*
* @return DynamicTable
*/
public function create($rows) {
if(!is_array($rows)) {
throw new Exception("Vous devez rentrer les colonnes à créer sous forme d'un tableau.");
}
$create_sql = "CREATE TABLE IF NOT EXISTS `" . $this->table . "` ( `id` int(11) NOT NULL AUTO_INCREMENT, ";
foreach($rows as $row) {
if(!isset($row['title']) || !isset($row['type'])) {
throw new Exception("Vous devez spécifier le nom de la colonne et son type.");
} else {
$comment = (isset($row['comment'])) ? " COMMENT '" . addslashes($row['comment']) . "'" : "";
$create_sql.= "`" . $this->replaceChars($row['title']) . "` " . $this->getRowType($row['type']) . " NOT NULL" . $comment . ",";
}
}
$create_sql.= "PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1";
try {
$this->db->exec($create_sql);
return new DynamicTable($this->table, $this->db);
} catch (PDOException $e) {
die($e->getMessage());
}
}
/**
* Permet de récupérer les colonnes de la table
*
* @return DynamicTable
*/
public function getRows() {
try {
$recordset = $this->db->query("SHOW FULL COLUMNS FROM `" . $this->table . "`");
return $recordset->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
die($e->getMessage());
}
}
/**
* Permet d'ajouter une colonne à la table
* @param string $name nom de la colonne
* @param string $type type de la colonne
* @param string $order emplacement de la table (first, after ou end)
* @param string $after après quelle colonne insérer la colonne (uniquement si after)
* @param string $comment commentaire de la colonne
*
* @return DynamicTable
*/
public function addRow($name, $type, $order = 'end', $after = null, $comment = null) {
$comment = ($comment !== null) ? " COMMENT '" . addslashes($comment) . "'" : "";
try {
switch ($order) {
case 'first':
$this->db->exec("ALTER TABLE `" . $this->table . "` ADD `" . $this->replaceChars($name) . "` " . $this->getRowType($type) . " NOT NULL " . $comment . " FIRST");
break;
case 'after':
if($after === null) {
throw new Exception("Vous devez indiquer après quelle colonne insérer " . $this->replaceChars($name));
} else {
$this->db->exec("ALTER TABLE `" . $this->table . "` ADD `" . $this->replaceChars($name) . "` " . $this->getRowType($type) . " NOT NULL " . $comment . " AFTER `" . $this->replaceChars($after) . "`");
}
break;
default:
$this->db->exec("ALTER TABLE `" . $this->table . "` ADD `" . $this->replaceChars($name) . "` " . $this->getRowType($type) . " NOT NULL " . $comment);
break;
}
return new DynamicTable($this->table, $this->db);
} catch (PDOException $e) {
die($e->getMessage());
}
}
/**
* Permet de renomer une colonne
* @param string $oldName ancien nom de la table
* @param string $newName nouveau nom de la table
* @param string $type nouveau type de la table
* @param string $comment commentaire de la colonne
*
* @return DynamicTable
*/
public function renameRow($oldName, $newName, $type = null, $comment = null) {
if($type !== null) {
foreach($this->getRows() as $row) {
if($row['Field'] === $oldName) {
$type = $row['Type'];
}
}
}
$comment = ($comment !== null) ? " COMMENT '" . addslashes($comment) . "'" : "";
$this->db->exec("ALTER TABLE `" . $this->table . "` CHANGE `" . $this->replaceChars($oldName) . "` `" . $this->replaceChars($newName) . "` " . $this->getRowType($type) . " NOT NULL " . $comment);
return new DynamicTable($this->table, $this->db);
}
/**
* Permet de changer l'ordre des colonnes de la table
* @param string $rowName nom de la colonne a deplacer
* @param string $after nom de la colonne apres laquelle il faut deplacer $rowName
*
* @return DynamicTable
*/
public function orderRow($rowName, $after) {
foreach($this->getRows() as $row) {
if($row['Field'] === $rowName) {
$type = $row['Type'];
}
}
$this->db->exec("ALTER TABLE `" . $this->table . "` CHANGE `" . $this->replaceChars($rowName) . "` `" . $this->replaceChars($rowName) . "` " . $this->getRowType($type) . " NOT NULL AFTER `" . $this->replaceChars($after) . "`");
return new DynamicTable($this->table, $this->db);
}
/**
* Permet de supprimer une colonne
* @param string $name nom de la colonne
*
* @return DynamicTable
*/
public function deleteRow($name) {
$this->db->exec("ALTER TABLE `" . $this->table . "` DROP `" . $this->replaceChars($name) . "`");
return new DynamicTable($this->table, $this->db);
}
/**
* Permet de renommer la table
* @param string $newName nouveau nom de la table
*
* @return DynamicTable
*/
public function renameTable($newName) {
$this->db->exec("ALTER TABLE `" . $this->table . "` RENAME `" . $this->replaceChars($newName) . "`");
$this->table = $this->replaceChars($newName);
return new DynamicTable($this->table, $this->db);
}
/**
* Permet de vider la table
*
* @return DynamicTable
*/
public function truncate() {
try {
$this->db->exec("TRUNCATE `" . $this->table . "`");
return new DynamicTable($this->table, $this->db);
} catch (PDOException $e) {
die($e->getMessage());
}
}
/**
* Permet de supprimer la table
*
* @return DynamicTable
*/
public function drop() {
try {
$this->db->exec("DROP TABLE `" . $this->table . "`");
return new DynamicTable($this->table, $this->db);
} catch (PDOException $e) {
die($e->getMessage());
}
}
/**
* Permet de recupérer le type à inscrire dans la requête SQL
* @param string $type type de la colonne
*
* @return string type correct de la colonne
*/
private function getRowType($type) {
switch ($type) {
case 'int' :
case 'integer' :
case 'int(11)':
return "int(11)";
break;
case 'varchar':
case 'varchar(255)':
return "varchar(255)";
break;
case 'text':
return "text";
break;
case 'date':
return "datetime";
break;
default:
throw new Exception("Ce champs n'est pas encore prévu dans la classe.");
break;
}
}
/**
* Permet de prévenir les espaces et les accents dans le nom des colonnes
* @params string $string nom de la colonne
*
* @return string le nom de la colonne sans les caractères spéciaux
*/
private function replaceChars($string) {
$in = array('’',':',';',',',' ',"'",'"','&','~','(',')','{','#','[','|','`','\\','^','@',']','}','¤','%','§','/','À','Á','Â','Ã','Ä','Å','à','á','â','ã','ä','å','Ò','Ó','Ô','Õ','Ö','Ø','ò','ó','ô','õ','ö','ø','È','É','Ê','Ë','è','é','ê','ë','Ç','ç','Ì','Í','Î','Ï','ì','í','î','ï','Ù','Ú','Û','Ü','ù','ú','û','ü','ÿ','Ñ','ñ','À','Á','Â','Ã','Ä','Å','Ç','È','É','Ê','Ë','Ì','Í','Î','Ï','Ò','Ó','Ô','Õ','Ö','Ù','Ú','Û','Ü','Ý','à','á','â','ã','ä','å','ç','è','é','ê','ë','ì','í','î','ï','ð','ò','ó','ô','õ','ö','ù','ú','û','ü','ý','ÿ','+','–','.','€');
$out = array('','','','','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','a','a','a','a','a','a','a','a','a','a','a','a','o','o','o','o','o','o','o','o','o','o','o','o','e','e','e','e','e','e','e','e','c','c','i','i','i','i','i','i','i','i','u','u','u','u','u','u','u','u','y','n','n','A','A','A','A','A','A','C','E','E','E','E','I','I','I','I','O','O','O','O','O','U','U','U','U','Y','a','a','a','a','a','a','c','e','e','e','e','i','i','i','i','o','o','o','o','o','o','u','u','u','u','y','y','-','-','','e');
return strtolower(str_replace($in, $out, $string));
}
}
Et du coup je voudrais votre avis sur son écriture, les choses à améliorer, supprimer ...
J'attends vos retours
Merci et bonne journée
Heu si sans doute mais au début j'ai commencé à faire avec des false pour $after et quand j'ai écris la doc, il arretait pas de me dire que j'ai pas la même chose car je suis dit que c'est un string alors que dans ma fonction j'ai un boolean
Salut,
Vraiment pas mal cette classe ! Bon, j'ai pas encore trouvé d'utilité dans mes projets actuels, mais elle peut s'avérer très utile dans certains cas. Beau boulot !
Je vais quand même regarder le code de plus près, mais à première vue, ton code est très propre !
Je te conseil le tuto de Graf' dans ce cas : http://www.grafikart.fr/tutoriels/php/exception-throw-try-catch-529
J'avais vu merci mais j'ai pas eu le temps de le regarder c'est pour ça que je n'ai pas encore implémenté les Exception perso
J'y pense, c'est pas très propre ça ^^ :
default:
die(htmlentities("Ce champs n'est pas encore prévu dans la classe."));
break;
Avec les exceptions ça sera plus propre, mais ce qui me choque c'est que tu utilise un htmlentities, ce qui est généralement utilisé pour néttoyer un user input. Dans ton cas, il est inutile, car le texte, c'est toi qui l'as hard coder, a moins que tu ne te fasse pas confiance, tu n'est pas obligé de l'utiliser :)
Non c'est juste que j'ai zapé de le retiré car mon serveur local n'est pas en utf8 et du coup j'avais des choses bizarres. Mais dans la v2 avec les Exception je retirerai ça
Je viens de mettre en place une nouvelle version avec beaucoup de modifs :
Dites moi si vous avez des idées de modifs.
Bonne journée
Bonsoir,
C'est devenu vraiment pas mal, bravo ! Pour realiser une interface d'edition de la base de donnée pour le client ça peut etre sympa.
Je n'ai pas beaucoup d'idées à par ajouter les requetes "basiques" tel que les insertions de données et eventuellement des methodes pour l'ajout de triggers (même si pour le dernier cas je n'ai pas vraiment de cas d'application concret).
Encore bravo.
Cordialement Litium
En gros j'ai dev ca car j'ai un client qui a besoin de gerer une base de donnees clients où il pourra changer les colonnes en ajoutant, supprimer, reoganiser
Salut,
en lisant brièvement le code, j'ai vu que tu retournais une nouvelle instance dans ta méthode create().
Je sais bien que tu souhaites utiliser le chainage de méthode, mais un 'return $this' ne suffirait-il pas ?
Pachenko.
Le return $this ne retourne pas la même chose. J'ai justement testé avant de faire ça et ça ne fonctionne pas.
Tu peux regarder le tuto sur le Créer un MVC, Grafikart explique pourquoi.
En réalité, l'idée c'est de créer une copie de l'ancien objet. Il faut toutefois prendre en considération les références. En effet, tu fais return $this, ça retourne une référence de l'objet courant. Autrement dit, ça va créer un pointeur, sur la case mémoire en question. C'est pour ça qu'il est important de faire des clones d'un objet. Pour ce faire, il y a deux possibilités, le « deep copy », ou la copie en profondeur et le « shallow copy, soit la copie superficielle. Dans une copie en profondeur, l'idée sera de copier toutes les données pouvant faire référence à un pointeur, afin que celui-ci soit propre à une référence, et non à deux. Alors que la copie superficielle va uniquement copier la référence du premier objet (pas de ses variables membres par exemple).
// En PHP, il existe des mécanismes nous permettant d'effectuer une copie superficielle (comme dans les autres languages d'ailleurs).
// Une copie superficielle
class MaClasse { /* ... */ } // Peu importe ce qu'il y a dedans.
$maClasse = new MaClasse();
$uneCopieSuperficielle = clone $maClasse; // En Java, il y aurait une méthode dans la classe globale « Object ».
// Un copie en profondeur
class MaClasse
{
private $classeComposée;
public function __construct()
{
// C'est bête, mais c'est juste pour l'exemple... :D
$this->classeComposée = new MaClasse();
}
public function setClasseComposée(MaClasse $classeComposée)
{
$this->classeComposée = $classeComposée;
}
// Heureusement, on peut définir cette méthode magique dans nos classes!
public function __clone()
{
$classeClonée = new MaClasse();
$classeClonée->setClasseComposée(new MaClasse());
return $classeClonée;
}
}
$maClasse = new MaClasse();
$uneCopieEnProfondeur = clone $maClasse;
Je vous encourage à consulter plusieurs documents à ce sujet. Bien souvent, on s'en rend même pas compte! Il y a probablement plusieurs spécificités selon les langages (moi j'ai juste transposé ça de C#), mais il faudrait voir de quel façon les trucs sont passés en PHP, comparativement à C# ou Java.
Ramz.
Alors j'ai compris En réalité, l'idée c'est de créer une copie de l'ancien objet. Il faut toutefois prendre en considération les références. En effet, tu fais return $this, ça retourne une référence de l'objet courant. Autrement dit, ça va créer un pointeur, sur la case mémoire en question mais alors après, j'ai eu l'impression que tu me parlais en chinois ... Il y aurai moyen de faire un article plus étendu et détaillé sur la matière ?