2011-01-30 6 views
22

Question étendue: Pourquoi utiliser data mapper/Db_Table_Row, où DbTable est capable de gérer la plupart des tâches de base pour la manipulation des données.Zend framework - Pourquoi utiliser data mapper/Db_Table_Row?

Je suis en train d'apprendre ZF v1.11

Pour la manipulation de base de données, j'ai créé DbTable pour chaque table. Par exemple, la table "users" est représentée par Application_Model_DbTable_Users sans codes supplémentaires.

Lorsque la manipulation de données, je peux utiliser:

<?php 
$uTable = new Application_Model_DbTable_Users(); 
$newUid = $uTable->insert(array('name'=>'Old Name', 'email'=>'')); 
$user = $uTable->find($newUid)->current(); 

// Then I can use $user which is instance of Table_Row 
$user->name = "New Name"; 
$user->email = "[email protected]"; 
$user->save(); 

Ma question est, quand aurais-je besoin de définir une classe de ligne (en supposant Table_Row est désigné comme DataMapper dans ZF-Tutoriels)

// By, adding this to the DbTable class 
protected $_rowClass = 'Application_Model_User'; 

Quels sont les avantages d'avoir une classe Row pour chaque entité? Quelqu'un peut-il me signaler les meilleures pratiques pour cela.

+0

http://stackoverflow.com/questions/373054/ - donne une idée que l'envoi de courrier électronique ou la modification d'une logique de mot de passe peut être implémentée dans la classe Table Row, qui est spécifique à l'utilisateur. –

Répondre

41

Vous n'avez pas besoin de définir votre propre Table_Row. Cependant, il peut être utile dans de nombreux cas, en particulier si vous souhaitez définir des méthodes ou des propriétés spécifiques pour une ligne d'utilisateur donnée. Ils peuvent également améliorer la lisibilité de votre code.

Par exemple dans votre cas de table des utilisateurs, vous pouvez définir une méthode appelée getFullName() dans une rangée utilisateur personnalisée comme:

public function getFullName() { 
    return $this->firstName . ' ' . $this->lastName; 
} 

Ensuite, lorsque vous obtenez objet ligne de l'utilisateur, pour obtenir le nom complet de l'utilisateur, vous venez de faire:

$user = $uTable->find($newUid)->current(); 
$fullName = $user->getFullName(); 

Second exemple est quand vous avez une table parent à la table des utilisateurs, telles que les adresses. Dans ce cas, vous pouvez définir une méthode appelée getAddress dans une ligne d'utilisateur:

public function getAddress() { 
    return $this->findParentRow('Application_Model_DbTable_Addresses'); 
} 

Dans ce scénario, vous obtiendrez un objet de la ligne d'adresse pour un utilisateur actuel comme suit:

$user = $uTable->find($newUid)->current(); 
$addressRow = $user->getAddress(); 

Un autre exemple, serait lorsque vous voulez créer des méthodes personnalisées de suppression ou instert. Supposons que vous voulez vous assurer que vous ne voulez pas supprimer un utilisateur admin en utilisant la méthode delete(). Ensuite, vous pouvez surcharger la méthode de suppression de Zend_Db_Table_Row comme suit:

public function delete() { 
     if ('admin' === $this->userRole) { 
       return 0; 
     } 
     return parent::delete(); 
} 

De cette façon, vous ne seriez pas en mesure de supprimer un administrateur simplement en appelant delete() sur un objet de ligne de l'utilisateur:

$user = $uTable->find($newUid)->current(); 
$rowsDeleted = $user->delete(); // would be 0 if $user is admin 

Ce ne sont que trois exemples de base montrant l'utilité de définir vos propres classes de lignes. Mais bien sûr, ils ne sont pas nécessaires. Cependant, d'après ma propre expérience, ils sont très pratiques.

+0

Génial !!! Merci pour les exemples réels de la vie avec l'explication: -] –

+0

+1 En effet, très agréable. –

+0

Dans la réponse à la question # 373054, il y a une fonction sendMailTo for User, est-ce une bonne habitude de garder les fonctions non liées à la base de données dans la classe Db_Row? Où devrait rester ce type de logique métier spécifique à l'utilisateur? –

20

En un mot: il s'agit de l'isolation.

Zend_Db_Table est une implémentation de la passerelle de données de table. Il canalise l'accès CRUD à une vue de table spécifique à travers une classe.Il est généralement utilisé avec un Table Module, par ex. une classe qui contient la logique métier pour les enregistrements gérés par une passerelle.

Zend_Db_Table_Row est une implémentation du Row Data Gateway Pattern. Ici, les objets retournés ressemblent exactement à un enregistrement de base de données et contiennent la logique métier pour fonctionner avec ces données, mais ils ne contiennent pas la logique de CRUD avec la table d'où ils proviennent (mais ActiveRecord) mais les regroupent.

Les passerelles de données en ligne sont correctes tant que vous n'en avez pas trop object relational impedance mismatch. La manière dont un objet est conservé dans une base de données relationnelle et son apparence dans un monde objet sont souvent des choses très différentes. Lorsque vous utilisez un Domain Model, vos objets métier sont généralement structurés différemment de ceux stockés dans la base de données. Ainsi, vous ne pouvez pas facilement les CRUD à partir de la base de données. C'est là que DataMapper entre en jeu. Un DataMapper prend la responsabilité de mapper les objets de domaine sur les jeux d'enregistrements et vice versa. Cela rend votre application plus maintenable car elle découpe les objets de votre domaine à partir de la structure de la base de données. Il les garde séparés et vous donne plus de flexibilité dans la façon de modéliser les deux couches (persistance et domaine).

Questions connexes