Model et Model DAO dans une application MVC

Model et Model DAO dans une application MVC - PHP - Programmation

Marsh Posté le 04-12-2007 à 15:54:56    

Bonjour,
je soumet à  votre critique ma réflexion sur le rôle des classes model et modeldao. L'une permet de définir, filtrer et valider des données, tandis que l'autre permet leur ajout/modification/supression et séléction dans la couche d'accès aux données.
 
Le code est assez commenté pour illustrer ma pensée :
 

Code :
  1. <?php
  2. // Classe de base pour tous les modèles.
  3. // Procure les méthodes de définiton/récupération des propriétés.
  4. // Permet de filtrer les données en amont et en aval.
  5. // Permet de valider les données pour leur enregistrement/modification.
  6. // Indépendant de la source des données.
  7. abstract class Model
  8. {
  9.   // Contient la liste des erreures.
  10.   protected $errors = array();
  11.   // Constructeur.
  12.   public function __construct($data)
  13.   {
  14.     foreach ($data as $name => $value)
  15. {
  16.   $this->{$name} = $value;
  17. }
  18.   }
  19.  
  20.   // Définie une propriété.
  21.   public function __set($name, $value)
  22.   {
  23. $this->{'set_'.$name}($value);
  24.   }
  25.  
  26.   // Récupère une propriété.
  27.   public function __get($name)
  28.   {
  29. return $this->{'get_'.$name}();
  30.   }
  31.  
  32.   // Vérifie qu'une propriété existe.
  33.   public function __isset($name)
  34.   {
  35.     return (isset($this->{$name}));
  36.   }
  37.  
  38.   // Supprime une propriété.
  39.   public function __unset($name)
  40.   {
  41.     unset($this->{$name});
  42.   }
  43.  
  44.   // Définie une erreure
  45.   // $name : nom de la propriété
  46.   // $message : message d'erreur
  47.   public function set_error($name, $message)
  48.   {
  49.     $this->errors[$name] = $message;
  50.   }
  51.  
  52.   // Récupère une erreure spécifique
  53.   // $name : nom de la propriété
  54.   public function get_error($name)
  55.   {
  56.     return (isset($this->errors[$name]) ? $this->errors[$name] : NULL);
  57.   }
  58.  
  59.   // Récupère toutes les erreures
  60.   public function get_errors()
  61.   {
  62.     return (!empty($this->errors) ? $this->errors : NULL);
  63.   }
  64.  
  65.   // Méthode abstraite de validation des données
  66.   abstract protected function is_valid();
  67. }
  68. // Classe de modèle d'article.
  69. class Model_Article extends Model
  70. {
  71.   // Identifiant.
  72.   private $id;
  73.   // Titre.
  74.   private $title;
  75.   // Contenu.
  76.   private $content;
  77.  
  78.   // Définie l'identifiant.
  79.   public function set_id($id)
  80.   {
  81.     // Sécurise l'identifiant.
  82.     $this->id = filter_var($id, FILTER_SANITIZE_NUMBER_INT);
  83.   }
  84.  
  85.   // Récupère l'identifiant.
  86.   public function get_id()
  87.   {
  88.     return (isset($this->id) ? $this->id : NULL);
  89.   }
  90.  
  91.   // Définie le titre.
  92.   public function set_title($title)
  93.   {
  94.     // Sécurise le titre.
  95.     $this->title = filter_var($title, FILTER_FLAG_STRIP_HIGH, FILTER_FLAG_ENCODE_HIGH);
  96.   }
  97.  
  98.   // Récupère le titre.
  99.   public function get_title()
  100.   {
  101.     return (isset($this->title) ? $this->title : NULL);
  102.   }
  103.  
  104.   // Définie le contenu.
  105.   public function set_content($content)
  106.   {
  107.     // Sécurise le contenue
  108.     $this->content = filter_var($content, FILTER_FLAG_STRIP_HIGH, FILTER_FLAG_ENCODE_HIGH);
  109.   }
  110.  
  111.   // Récupère le contenu.
  112.   public function get_content()
  113.   {
  114.     return (isset($this->content) ? $this->content : NULL);
  115.   }
  116.  
  117.   // Valide les données
  118.   public function is_valid()
  119.   {
  120.     // Pour le moment on ne va considérer que la validation des données
  121. // pour leur insertion.
  122.     if (empty($this->title))
  123. {
  124.   $this->set_error('title', 'Veuillez entrer un titre.');
  125.   return FALSE;
  126. }
  127.     if (empty($this->content))
  128. {
  129.   $this->set_error('content', 'Veuillez entrer un contenu.');
  130.   return FALSE;
  131. }
  132. return TRUE;
  133.   }
  134. }
  135. // Classe de base du model d'accès aux données.
  136. abstract class Model_DAO
  137. {
  138.   // Nom de la classe de modèle
  139.   protected $model_class;
  140.   // connexion avec la base de données.
  141.   protected $dbh;
  142.   // nom de la table.
  143.   protected $table;
  144.   // structure de la table.
  145.   protected $schema;
  146.  
  147.   // Constructeur.
  148.   // $dbh : connexion avec la base de données.
  149.   public function __construct(PDO $dbh)
  150.   {
  151.     $this->dbh = $dbh;
  152. // Récupère le nom de la table
  153. // Model_DAO_<nom_dela_table>
  154. $this->table = substr(get_class($this), 10);
  155. $this->model_class = 'Model_'.$this->table;
  156. // La structure n'est pas définie ?
  157. // On peut imaginer plus tard la génération de structure,
  158. // puis leur inclusion plutôt qu'une requàªte...
  159. if (!isset($this->schema))
  160. {
  161.       $sql = 'SHOW COLUMNS FROM '.$this->table;
  162.   $stmt = $this->dbh->query($sql);
  163.   // Le serveur de base de données ne réussit pas à  executer de la requàªte ?
  164.   if (!$stmt)
  165.   {
  166.  $error = $this->dbh->errorInfo();
  167.  throw new Exception ($error[2]);
  168.   }
  169.   // Définie la structure de la table afin de pouvoir
  170.   // travailler avec le modèle.
  171.   $this->schema = $stmt->fetchAll(PDO::FETCH_ASSOC);
  172. }   
  173.   }
  174.  
  175.   // Insertion d'un nouvel enregistrement.
  176.   // $model : instance de la classe modèle.
  177.   public function insert(Model $model)
  178.   {
  179.     // Les données à  insérées sont-elles valides ?
  180.     if (!$model->is_valid())
  181. {
  182.   return FALSE;
  183. }
  184.     // Passe en revue la structure de la table.
  185. foreach($this->schema as $columns)
  186. {
  187.   // Récupère le nom des colonnes.
  188.   $names[]  = $columns['Field'];
  189.   // Récupérer les donnés contenues dans la classe modèle.
  190.   // Appel <nom_du_modele>::get_<nom_de_la_colonne> ();
  191.   $values[] = $model->{$columns['Field']};
  192.   // Remplie un tableau de marqueurs pour la préparation de la
  193.   // requàªte avant son execution.
  194.   $binds[]  = '?';
  195. }
  196. // Requàªte SQL
  197.     $sql = 'INSERT INTO `'.$this->table.'` (`'
  198.   . implode ('`, `', $names).'`) VALUES ('
  199.   . implode(', ', $binds).')';
  200. // Prépare la requàªte SQL avec des marqueurs
  201. $stmt = $this->dbh->prepare($sql);
  202. // Le serveur de base de données ne réussit pas à  préparer la requàªte SQL?
  203. if(!$stmt)
  204. {
  205.  $error = $this->dbh->errorInfo();
  206.  throw new Exception ($error[2]);
  207. }
  208. // Le serveur de base de données ne réussit pas à  executer la requàªte SQL préparée ?
  209. if (!$stmt->execute($values))
  210. {
  211.  $error = $stmt->errorInfo();
  212.  throw new Exception ($error[2]);
  213. }
  214. // Déinie l'identifiant du dernier enregistrement inséré dans le modèle.
  215. $model->id = $this->dbh->lastInsertId();
  216. return TRUE;
  217.   }
  218.   // Met à  jour un ou plusieurs enregistrement(s).
  219.   // $model : instance de la classe modèle.
  220.   public function update(Model $model)
  221.   {
  222.     // ...
  223.   }
  224.   // Supprime un ou plusieurs enregistrement(s).
  225.   // $model : instance de la classe modèle.
  226.   // On pourrait supprimer par l'identifiant ou
  227.   // le nom d'une colonne si elle est définie.
  228.   public function delete(Model $model)
  229.   {
  230.     // ...
  231.   }
  232.   // Sélectionne un ou plusieurs enregistrement(s).
  233.   public function select()
  234.   {
  235.     // ...
  236. // On retourne une instance de la classe modèle
  237. // pour chaque enregistrement.
  238. $result = array();
  239. foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $record)
  240. {
  241.   $result = new $this->model_class($record);
  242. }
  243. return $result;
  244.   }
  245.  
  246.   // + implantation de méthode gérant les relations
  247.   // one-to-one, one-to-many et many-to-many
  248. }
  249. // Classe de modèle d'accés au données des articles.
  250. class Model_DAO_Article extends Model_DAO
  251. {
  252.   // Constructeur.
  253.   // Surcharge de la classe parente.
  254.   public function __construct($dbh)
  255.   {
  256.     $this->table = 'article';
  257.     $this->model_class = 'Model_Article';
  258.     parent::__construct($dbh);
  259.   }
  260. }
  261. // Instance de la classe de base de données
  262. $dbh = new PDO('mysql:host=localhost;dbname=tournoi', 'root', 'root');
  263. // Ajout des données au modèle article
  264. $article = new Model_Article (array('id' => NULL, 'title' => 'Article\'s title', 'content' => 'This is the article content'));
  265. // Ajout de l'instance de la classe de base de données au modèle d'accès aux données.
  266. $article_dao = new Model_DAO_Article ($dbh);
  267. // Ajout de l'instance du modèle article pour insérer les données.
  268. if ($article_dao->insert($article))
  269. {
  270.   echo '<p>Article ajouté avec succès.</p>';
  271. }
  272. else
  273. {
  274.   // Récupération des erreures
  275.   $errors = $article->get_errors();
  276.   // 1er choix d'affichage
  277.   // Ou bien une liste :
  278.   echo '<ul>';
  279.   foreach ($errors as $error)
  280.   {
  281.     echo '<li>'.$error.'</li>';
  282.   }
  283.   echo '</ul>';
  284.  
  285.   // 2ème choix d'affichage
  286.   // A l'endroit ou se situe le champs titre du formulaire
  287.   /*if (!empty($errors['title']))
  288.   {
  289.     echo '<p>'.$errors['title'].'</p>';
  290.   }
  291.   // A l'endroit ou se situe la zone de texte content du formulaire
  292.   if (!empty($errors['content']))
  293.   {
  294.     echo '<p>'.$errors['content'].'</p>';*/
  295.   }
  296. }
  297. // Pas implémenter dans l'exemple.
  298. // Uniquement à  titre informatif...
  299. /*
  300. foreach ($article_dao->select() as $article)
  301. {
  302.   echo '<p>id : '.$article->id.'</p><p>titre : '.$article->title.'</p><p>contenu : '.$article->content.'</p>';
  303.        
  304. }
  305. */
  306. ?>



Message édité par hametsu le 05-12-2007 à 14:38:53
Reply

Marsh Posté le 04-12-2007 à 15:54:56   

Reply

Marsh Posté le 04-12-2007 à 17:10:48    

balises code bourdaÿl ! :o

Reply

Marsh Posté le 05-12-2007 à 14:39:51    

Pas d'idée ?

Reply

Marsh Posté le 05-12-2007 à 22:55:43    

Pourquoi reinventer la roue ?
www.phpdoctrine.net => un ORM simple d'emploi et très puissant.

Reply

Marsh Posté le 06-12-2007 à 11:53:48    

Viens dans mon topic MVC [:dawa]

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed