Quelles sont certaines des manières dont vous avez implémenté des modèles dans le Zend Framework?
J'ai vu le class User extends Zend_Db_Table_Abstract
De base, puis j'appelle cela dans vos contrôleurs:
$foo = new User;
$foo->fetchAll()
mais qu'en est-il des utilisations plus sophistiquées? La section Quickstart de la documentation offre un tel exemple mais j'ai toujours l'impression de ne pas obtenir d'exemple de "meilleure utilisation" pour les modèles dans Zend Framework. Des implémentations intéressantes là-bas?
EDIT: Je devrais clarifier (en réponse au commentaire de CMS) ... Je sais faire des sélections plus compliquées. Je m'intéressais aux approches globales du concept du modèle et aux exemples concrets de la façon dont les autres les ont mis en œuvre (en gros, les trucs que le manuel laisse de côté et les trucs sur lesquels se glissent les procédures de base)
Je sous-classe personnellement les deux Zend_Db_Table_Abstract
et Zend_Db_Table_Row_Abstract
. La principale différence entre mon code et le vôtre est qu'il traite explicitement la sous-classe de Zend_Db_Table_Abstract
en tant que "table" et Zend_Db_Table_Row_Abstract
comme "ligne". Très rarement, je vois des appels directs pour sélectionner des objets, SQL ou les méthodes de base de données ZF intégrées dans mes contrôleurs. J'essaie de cacher la logique de demander des enregistrements spécifiques aux appels pour derrière Zend_Db_Table_Abstract
ainsi:
class Users extends Zend_Db_Table_Abstract {
protected $_name = 'users';
protected $_rowClass = 'User'; // <== THIS IS REALLY HELPFUL
public function getById($id) {
// RETURNS ONE INSTANCE OF 'User'
}
public function getActiveUsers() {
// RETURNS MULTIPLE 'User' OBJECTS
}
}
class User extends Zend_Db_Table_Row_Abstract {
public function setPassword() {
// SET THE PASSWORD FOR A SINGLE ROW
}
}
/* CONTROLLER */
public function setPasswordAction() {
/* GET YOUR PARAMS */
$users = new Users();
$user = $users->getById($id);
$user->setPassword($password);
$user->save();
}
Il existe de nombreuses façons d'aborder cela. Ne pensez pas que ce soit le seul, mais j'essaie de suivre l'intention du design du ZF. (Voici plus de mes pensées et liens sur le sujet .) Cette approche devient un peu lourde de classe, mais je pense qu'elle garde les contrôleurs concentrés sur la gestion des entrées et la coordination avec la vue; quitter le modèle pour effectuer le travail spécifique à l'application.
J'ai travaillé pour Zend et j'ai fait pas mal de travail sur le composant Zend_Db_Table.
Zend Framework ne donne pas beaucoup de conseils sur le concept d'un "modèle" par rapport au modèle de modèle de domaine. Il n'y a pas de classe de base pour un modèle car le modèle encapsule une partie de la logique métier spécifique à votre application. J'ai écrit un blog sur ce sujet plus en détail.
La persistance dans une base de données doit être un détail d'implémentation interne d'un modèle. Le modèle utilise généralement une ou plusieurs tables. C'est une conception orientée objet courante mais incorrecte de considérer un modèle comme une extension d'une table. En d'autres termes, nous devrions dire le modèle HAS-A Table - pas le modèle IS-A Table.
Voici un exemple d'IS-A:
class MyModel extends Zend_Db_Table_Abstract
{
}
Voici un exemple de HAS-A:
class MyModel // extends nothing
{
protected $some_table;
}
Dans un modèle de domaine réel, vous utiliseriez $ some_table dans les méthodes de MyModel.
Vous pouvez également lire le point de vue de Martin Fowler sur le modèle de conception Modèle de domaine , et sa description de l'anti-modèle Modèle de domaine anémique , qui est le nombre de développeurs qui approchent malheureusement OO programmation.
N'utilisez jamais Zend_Db_Table comme modèle. Cela vous met juste en difficulté. Soit vous écrivez vos propres classes de modèles qui utilisent Zend_Db_Table pour parler à votre base de données, soit vous pouvez lire mon article de blog ici pour un hack qui vous permet de combiner quelque peu la classe "Model" et Zend_Db_Table.
La chose principale à ne pas faire est que lorsque vous utilisez Zend_Db_Table directement dans vos contrôleurs, vous finissez par faire les mêmes choses à plusieurs endroits. Si vous devez modifier une partie de cette logique, vous devez effectuer un changement à plusieurs endroits. Pas bon. Mon premier projet professionnel a été fait comme ça parce que j'étais celui de l'entreprise qui devait apprendre à utiliser ZF et c'est un vrai bordel maintenant.
J'ai également tendance à écrire des fonctions d'aide dans mes classes pour des récupérations sophistiquées. Quelque chose comme $ table-> doNameFetchAll () ou $ table-> doOrderFetchAll ().
J'ai fait quelques recherches sur les modèles pour ZF et suis tombé sur une intéressante série d'articles de Matthew Weier O'Phinney qui valent la peine d'être vérifiés:
Ce n'est pas du "code de production" et beaucoup est laissé à l'imagination, mais c'est une bonne lecture et cela m'a beaucoup aidé.
Un modèle a rien à voir avec la base de données. Que se passe-t-il si je récupère des données à partir d'un flux RSS ou d'un service SOAP ou que je lis des fichiers à partir du FS?
J'ai mis toutes ces sortes de choses dans des modèles. Dans ce cas, ma classe de modèle pourrait ne pas étendre quoi que ce soit. Je suis sur le point d'écrire un modèle qui utilise des méthodes d'autres modèles.
Ignorez ZF pour la partie modèles, il existe de bien meilleures solutions. Le "M" dans "MVC" de ZF est quasiment absent. En lisant leurs documents, ils ne mentionnent pas vraiment les modèles - ce qui est une bonne chose, cela signifie que vous pouvez utiliser à peu près tout ce que vous voulez sans écrire beaucoup de code d'adaptateur.
Jetez un oeil à Doctrine pour les modèles à la place. Il devient rapidement l'ORM de facto pour PHP.
vous pouvez étendre la classe Zend_Db_Table_Abstract et y ajouter quelques méthodes utiles. par exemple, vous pouvez ajouter une méthode changePassword () à votre classe d'utilisateurs et manipuler ses données. ou vous pouvez changer la méthode __toString () par défaut de votre classe, vous aurez donc une méthode __toString () personnalisée qui, disons, renvoie toutes les informations de contact de l'utilisateur (nom, adresse, numéro de téléphone) dans une chaîne bien formatée . dans votre constructeur, vous pouvez remplir vos données dans les propriétés de votre objet. puis utilisez-les comme:
public function __toString() {
$data = $this->_name . ', ' . $this->_adderss . ', call: ' . $this->_phone;
return $data;
}
votre modèle étend le Zend_Db_Table_Abstract juste pour faciliter le processus d'accès à ses données, mais les fonctionnalités que vous pourriez avoir sur ces données dépendent de votre créativité et de vos besoins. Je vous recommande le livre "php | guide de l'architecte pour la programmation avec le framework zend" de Cal Evans. le livre est très instructif et facile à lire. les chapitres 4 et 6 seront utiles à cet égard.
http://zfsite.andreinikolov.com/2008/08/zend_db_table-time-overhead-about-25-percents/
Bit of a catch 22, Zend_Table est Nice en principe, mais génère des frais généraux de performance (sans mise en cache) ...
J'utilise Propel 1.3 au lieu de Zend_Db_Table. C'est difficile à configurer, mais génial. Il peut examiner votre base de données et générer automatiquement tous vos modèles. Il génère en réalité 2 niveaux et 2 types de modèle.
Exemples de table "utilisateur":
Niveau 1: BaseModel & BasePeer: ceux-ci sont remplacés à chaque fois que vous régénérez votre ORM. c'est-à-dire BaseUser.php & BaseUserPeer.php
Niveau 2: StubModel & StubPeer: ceux-ci ne sont pas écrasés. Ce sont eux que vous personnalisez. c'est-à-dire User.php & UserPeer.php
Type 1: modèle - pour les opérations CRUD de base, pas les requêtes, c'est-à-dire User.php Type 2: homologue - pour les requêtes. Ce sont des objets statiques. c'est-à-dire UserPeer.php
Donc pour créer un utilisateur:
$derek = new User();
$derek->setFirstName('Derek');
$derek->save();
Pour trouver tous les dereks:
$c = new Criteria();
$c->add(UserPeer::FIRST_NAME, 'Derek');
$dereks = UserPeer::doSelect($c);
Une entité de base de données n'est pas le seul type de composant de modèle. En tant que tel, cela n'a pas vraiment de sens de parler de modèles (au pluriel) - Votre application a un modèle, qui contient une multitude de composants. Certains de ces composants pourraient être des passerelles de table (et donc s'étendre de Zend_Db
), contrairement à d'autres.
Je vous recommande de vous procurer le livre Domain Driven Design par Eric Evans, qui fait un excellent travail pour expliquer comment construire un modèle d'objet.
Vous pouvez faire des requêtes plus compliquées, consultez la section tilisation avancée dans Zend_Db_Table
page de manuel.
$select = $table->select();
$select->from($table,
array('COUNT(reported_by) as `count`', 'reported_by'))
->where('bug_status = ?', 'NEW')
->group('reported_by');