Zend FR

Consultez la FAQ sur le ZF avant de poster une question

Vous n'êtes pas identifié.

#26 10-02-2010 09:38:45

Delprog
Administrateur
Date d'inscription: 29-09-2008
Messages: 670

Re: [Partage/Reflexion]MVC, Services, Mapper et Persistance

Salut,

En fait, les patterns "Tabla Data Gateway" et "Row Data Gateway" ne collent pas vraiment avec le mapper.

Si ton objet étend Zend_Db_Table_Row_Abstract tu le lies étroitement à ta base de données. Un row est le reflet exact d'un enregistrement dans une table, tu perds donc toute la souplesse car les propriétés de ton objet seront les noms de tes champs dans la base et toute évolution de la base de données aura une incidence sur ta couche métier.

Ton objet métier peut-être le résultat de plusieurs enregistrements dans plusieurs tables. Le mapper ne devrait pas étendre non plus un Zend_Db_Table, mais plutôt reçevoir des instances de chaque table dont il a besoin pour construire ton objet métier.

Dans l'exemple que tu donnes, tu considères que la structure de ton objet = ta table et en fait tu ne fais que donner des alias à tes champs. Mais un objet métier c'est pas forcément ça.

Imagine par exemple que sur ton site tu as des articles et que ces articles sont liés à des tags. Dans la base tu vas sans doute vouloir séparer les tags de ton article, tu auras plusieurs tables, alors que dans ta couche métier l'objet Article possèdera une simple propriété "tags" qui recevra un string correspondant à la liste des tags séparés par une virgule par ex.

Si tu mets à jour et que tu veux sauvegarder les états de cet objet tu ne pourras pas utiliser le save du Row car l'update nécessite la mise à jour de plusieurs tables (dépendances). Ton mapper est là pour ça, il sait comment faire, et il doit le faire via un update() pour être optimisé et ne doit pas récupérer un row, le peupler puis le sauvegarder (de toute façon dans ce cas de figure ce n'est pas possible).

Si maintenant tu décides de ne plus séparer les tags des articles dans la BDD et de créer un champ "tags" string dans ta table article, et bien tu mets à jour ton mapper, mais tu n'auras pas à toucher à ton objet, et donc toutes les couches qui l'utilisent en dessous (ou dessus, ça dépend d'où on regarde :p) ne seront pas touchées non plus.

Après ce n'est peut-être pas gênant pour toi, ça dépend de ton application.

Les tables, row et rowset ici ne sont utilisés que pour requêter la BDD et pouvoir itérer sur les résultats pour construire tes objets.


A+ benjamin.


http://www.anonymation.com/ - anonymation - Studio de création.
http://code.anonymation.com/ - anonymation - blog - développement et architecture web

Hors ligne

 

#27 10-02-2010 10:11:37

Delprog
Administrateur
Date d'inscription: 29-09-2008
Messages: 670

Re: [Partage/Reflexion]MVC, Services, Mapper et Persistance

Petit détail, j'ai dit une petite connerie, le mapper ne doit pas recevoir des instances de chaque table, mais il doit recevoir un objet lui permettant de requêter la BDD, par exemple l'objet DB.
Je sais c'est pas ce que donne le Quickstart ZF mais je suis pas d'accord avec eux, donc smile

Quoi que ça peut aussi être une table sur laquelle d'autres sont jointes en virant le integrityCheck.

A+ benjamin.


http://www.anonymation.com/ - anonymation - Studio de création.
http://code.anonymation.com/ - anonymation - blog - développement et architecture web

Hors ligne

 

#28 10-02-2010 14:48:26

Blount
Membre
Date d'inscription: 23-06-2009
Messages: 98
Site web

Re: [Partage/Reflexion]MVC, Services, Mapper et Persistance

Je suis ce sujet depuis son commencement et j'aurai aimé savoir comment gérer un upload de fichier. Pour faire simple, je vais donner un exemple :

J'ai un formulaire contenant un champ d'envoi d'une image pour un utilisateur. À la création d'un utilisateur, aucun souci. Par contre, quand j'édite le profil, il doit pouvoir soit supprimer son avatar, soit le changer.

Donc, j'ai une sorte de classe de formulaire de ce style :

Code:

class Form_User extends JR_Form
{
    
    public function init()
    {
        
        
        $this->addElement('text', 'name', array(
            'label' => 'Nom',
            'order' => 10
        ));
        
        $this->addElement('text', 'firstname', array(
            'label' => 'Prénom',
            'order' => 20
        ));
        
        
        $file = new JR_Form_Element_File('image', array(
            'label' => 'Image',
            'destination' => APPLICATION_PATH.'/../public/images/avatars',
            'required' => false,
            'ignore' => true,
            'validators' => array(
                array('Extension', false, array('jpg', 'gif', 'png', 'jpeg')),
                array('File_Size', false, array('min' => 0, 'max' => 1024000))
            ),
            'description' => 'JPG, Gif, PNG ; 1MB maximum',
            'order' => 30
        ));
        $this->addElement($file);
        
        
        $this->addElement('SubmitOrCancel', 'enregistrer', array(
            'label' => 'Enregistrer',
            'cancelLabel' => 'Annuler',
            'ignore' => true,
            'order' => 230
        ));
    }
    
    
    public function populate(array $values)
    {
        if (isset($values['image'])) {
            $this->addElement('checkbox', 'deleteImage', array(
                'label' => 'Supprimer l\'image',
                'ignore' => true,
                'order' => 201
            ));
            
            $el = $this->getElement('deleteImage');
            $decorators = $el->getDecorators();
            $el->clearDecorators();
            
            foreach ($decorators AS $name => $decorator) {
                if ($name == 'Zend_Form_Decorator_HtmlTag') {
                    $el->addDecorator(
                        new Jr_Form_Decorator_Html(array('html' => '<img src="/images/logements/'.$values['image'].'" class="preview" alt="" />'))
                    );
                }
                $el->addDecorator(array($name => $decorator));
            }
        }
        
        
        parent::populate($values);
    }
    
}

Donc ici, j'ajoute un checkbox si une image est déjà présente. Dans un premier temps, est-ce que cette solution est correcte ? D'après moi oui, ça me semble "logique".

Maintenant, quand on valide le formulaire, une vérification doit être faite. Si la case est cochée ou un nouveau fichier est envoyé, il faut supprimer l'ancien fichier (sinon ça peut devenir lourd ^^).
Actuellement, c'est dans mon controlleur que j'effectue cette vérification.
Qui devrait se charger de ce traitement ? Je pense que ce serait le mapper, certainement pas le formulaire (ce n'est pas son rôle).

Hors ligne

 

#29 10-02-2010 15:20:28

bakura
Administrateur
Date d'inscription: 30-01-2010
Messages: 353

Re: [Partage/Reflexion]MVC, Services, Mapper et Persistance

Petit détail, j'ai dit une petite connerie, le mapper ne doit pas recevoir des instances de chaque table, mais il doit recevoir un objet lui permettant de requêter la BDD, par exemple l'objet DB.

Pourquoi ça ? Dans mon cas mon mapper n'hérite pas de Zend_Db_Table_Abstract (c'est bien mon objet DbTable_Users qui hérite de cette classe). Zend_Db_Table_Abstract a l'avantage de pouvoir gérer extrêmement facilement les relations entre les tables notamment. Pourquoi utiliser Zend_Db plutôt qu'une classe héritant de Zend_Db_Table_Abstract ?

Pour l'uatre problème, effectivement j'avais oublié que Zend_Db_Table_Abstract offrait les fonctions update et insert u_u. Ce que je faisais c'était récupérer chaque fois l'instance (un SELECT) puis un save (un UPDATE) alors que je pouvais faire directement un update. Je retire donc ce que j'ai dit big_smile.

Un row est le reflet exact d'un enregistrement dans une table, tu perds donc toute la souplesse car les propriétés de ton objet seront les noms de tes champs dans la base et toute évolution de la base de données aura une incidence sur ta couche métier.

Je suis effectivement d'accord avec ça : si je décide de changer le nom légèrement d'un champ de ma base, et bien tout est cassé si j'utilise un objet qui dérive de Zend_Db_Table_Row_Abstract. Mais à côté de ça tu préconises de faire quoi ? La fonction __set est vraiment pratique, ça évite, par exemple pour un utilisateur ou je pourrais avoir pas mal de champs, d'écrire des setUsername, getUsername, setPassword, getPassword, setLastLoginDate, getLastLoginDate... Ça fait une liste incroyablement longue de setters et de getters :-/, même si, dans l'esprit, je suis d'accord que c'est mieux.

Mais concrètement, comment créés-tu tes objets métiers ? Ton constructeur prend un Zend_Db_Table_Row, extrait les données et initialise tous les attributs de l'objet métier ? Avec des setters ou avec __set ? De la même façon, lorsque tu vas vouloir enregistrer les données de ton objet métier dans ta base de donnée, tu vas donc devoir récupérer chaque donnée, par exemple comme ceci :

Code:

$data = array ();
$data ['username'] = $this->getUsername ();
$data ['password'] = $this->getPassword ();
... // D'autres données

$this->getTable ()->update ($data);

C'est quelque chose dans cet esprit ?

N'aurais-tu pas par hasard un peu de code "en situation" (cet exemple d'utilisateur par exemple qui est très bien) ?

EDIT : ça n'a rien à voir mais je te pose la question vu que tu sembles relativement calé en design. Pour l'authentification j'utilise actuellement un "service" (pas dans le sens service web), qui me permet de ne pas alourdir le code du contrôleur.

Toutefois penses-tu que l'authentification doit être "transferé" directement dans l'objet métier User (après tout, c'est un utilisateur qui s'authentifie, cette fonction aurait donc sa place en tant que méthode membre de la classe User). Mais une entité a t-elle "le droit" d'interagir comme ça avec d'autres composants ?

EDIT 2 : par rapport à ton système de tags dont tu parles... Justement j'ai un cas un peu similaire. Concrètement, j'ai une classe métier "Cours", chaque classe contenant un ensemble de leçons. Logiquement, j'ai donc un attribut "lessons" dans chaque classe métier "Cours", et une fonction getLessons qui me renvoit un paginator de leçons. Le truc c'est que je n'ai pas systématiquement besoin des leçons, à savoir, certaines pages ou je vais afficher un cours (par exemple sa description), et donc aucun besoin de connaître les leçons. Si j'ai 100 leçons, cela veut dire que mon mapper va charger 100 leçons (donc 100 lignes de ma table leçons) pour les stocker dans mon objet métier Cours, alors que je ne vais pas exploiter ces données ? Et d'ailleurs, qui est-ce qui doit charger ces données ? Est-ce que le mapper de Cours va utiliser un mapper Leçon (et l'utiliser lors du chargement d'un cours), ou est-ce que le mapper Leçon est inutile ?

Désolé pour toutes ces questions... sad

Dernière modification par bakura (10-02-2010 15:53:20)

Hors ligne

 

#30 12-02-2010 09:33:48

Delprog
Administrateur
Date d'inscription: 29-09-2008
Messages: 670

Re: [Partage/Reflexion]MVC, Services, Mapper et Persistance

J'essaie de vous répondre à tous les deux dès que j'ai un peu de temps smile

A+ benjamin.


http://www.anonymation.com/ - anonymation - Studio de création.
http://code.anonymation.com/ - anonymation - blog - développement et architecture web

Hors ligne

 

#31 13-02-2010 21:40:12

bakura
Administrateur
Date d'inscription: 30-01-2010
Messages: 353

Re: [Partage/Reflexion]MVC, Services, Mapper et Persistance

Merci pour ton aide, Benjamin smile.

Hors ligne

 

#32 08-03-2010 10:29:03

Delprog
Administrateur
Date d'inscription: 29-09-2008
Messages: 670

Re: [Partage/Reflexion]MVC, Services, Mapper et Persistance

Salut,

Un peu tard mais une petite réponse quand même :

@Blount:

Je pense qu'il y a plusieurs solutions selon l'application et la charge. J'aurais tendance à écraser l'avatar dans la persistance (via le mapper) et ne pas supprimer immédiatement le fichier. Ensuite, il y aurait un script serveur qui tournerait par ex. toutes les nuits et qui supprimerait tous les fichiers sans référence.

Sinon, si tu veux supprimer le fichier au moment du changement d'avatar, c'est du métier, c'est à dire que c'est ta classe métier (User par ex.) qui va devoir supprimer l'ancien avatar, ou ton service si tu as déporté le métier dans une couche de services. Tu peux par ex. uploader ton nouvel avatar dans un fichier temporaire avec un uuid ( uiniqid() ), passer le chemin de ce fichier à ton métier qui se chargera de le déplacer/renommer, puis d'unlink le fichier temporaire + le fichier de l'ancien avatar.

Pour moi le controller ne devrait qu'uploader le fichier, et ne pas s'occuper du reste. Le formulaire n'est là que pour s'assurer du bon format du fichier, même si cette vérif. devrait aussi être faite dans le métier (Entité ou Service).

Après attention c'est une idée hein, ça mérite peut-être plus de réflexion.


@bakura:

bakura a écrit:

Pourquoi utiliser Zend_Db plutôt qu'une classe héritant de Zend_Db_Table_Abstract ?

Je parle de Zend_Db parce que dans ce cas là je n'ai pas besoin des fonctionnalités d'une Zend_Db_Table, mais tu peux aussi bien les utiliser smile


J'ai des accesseurs pour toutes mes propriétés ça c'est certain, rien de magique, ne serait-ce que pour l'autocompletion. Ça fait beaucoup de code à écrire mais tu peux aussi t'écrire un petit générateur qui chargerait par ex. un fichier xml dans lequel tu as défini toutes tes propriétés avec leur type. Ou sinon, si tu utilises Zend Studio, il a un générateur de getters/setters smile

Tous mes objets métiers héritent d'une classe "Base" qui définit un constructeur et des méthodes magiques tels que dans le quickstart. Je peux passer un tableau d'options à mon constructeur qui se chargera (via la méthode magique __set) de setter les propriétés qui existent dans mon objet. Mais j'utilise très très peu cette fonctionnalité. Dans mes mappers DB je définis mon mapping, c'est à dire les correspondances entre mes propriétés et mes champs dans la persistance, et c'est mon mapper générique qui se charge de peupler ce qu'il faut au bon moment.

Pour des exemples de codes, je n'ai pas de concret, puisque comme je le disais, depuis j'ai abandonné cette solution et je suis passé sur l'ORM Doctrine pour lequel j'attend impatiemment la version 2 qui règlera toutes les questions abordées ici big_smile
Mais regarde en première page du thread, il doit y avoir le mapper générique dont je parle smile


bakura a écrit:

Toutefois penses-tu que l'authentification doit être "transferé" directement dans l'objet métier User (après tout, c'est un utilisateur qui s'authentifie, cette fonction aurait donc sa place en tant que méthode membre de la classe User). Mais une entité a t-elle "le droit" d'interagir comme ça avec d'autres composants ?

Ca dépend. Si par ex. ton métier c'est de gérer des collections comme des albums photos pour tes utilisateurs, la sécurité et la manière d'identifier ton utilisateur ne font pas partie du métier. L'authentification et les ACLs devraient vraiment faire partie d'une couche spécifique qui serait utilisée par plusieurs autres couches (controleurs, services). Dans mon cas j'implémente souvent dans mon appli une simple interface :

Code:

<?php 
/**
 * Security contract
 * @author Benjamin Dulau
 */
interface App_Auth
{
    /**     
     * @param array $data    
     */
    public function storeAuthentification(array $data, $rememberMe = false);
    
    /**
     * @return boolean     
     */
    public function clearAuthentification();
    
    /**
     * @return boolean
     */
    public function isAuthentified();
        
    /**     
     * @return Tight_DataTransferObject
     */
    public function getCurrentUser($defaultRole = 'guest');
    
    /**     
     * @param Zend_Acl_Role_Interface|string     $role
     * @param Zend_Acl_Resource_Interface|string $resource
     * @param string                             $privilege
     * @return boolean
     */
    public function isAllowed($role = null, $resource = null, $privilege = null);
    
    /**     
     * @return App_Acl
     */
    public function getAcl();
}

Qui gère à la fois l'authentification et les acls. Une implémentation de cette classe est ensuite injectée où je veux, soit dans un contrôleur, soit dans un service. Mais aujourd'hui je ne sais toujours pas si c'est une bonne pratique smile


Pour la pagination, c'est une chose qui devrait être gérée par le front. Par ex. dans un Repository (qui pourrait être un mapper hein) je vais avoir :

Code:

<?php
interface Repository_Album
{    
    /**
     * Finds an album using given id.
     * 
     * @param  mixed $albumId
     * @return Model_Album if found, else null
     */
    function find($albumId);
    
    /**
     * Finds an album with its
     * photos (populated)
     * 
     * @param int $albumId
     * @return Model_Album
     */
    function findWithPhotos($albumId);
    
    /**
     * Finds albums
     * 
     * @return ArrayObject|Model_Album
     */
    function findWithFilters($filter = null, $pageSize = 20, $page = 1, &$totalItemCount);
    
    /**
     * Saves given album.
     * 
     * @param Model_Album $album
     */
    function save(Model_Album $album);
    
    /**     
     * @param Model_Album $album
     * @return bool
     */
    function delete(Model_Album $album);
    
    /**     
     * @param array $photoIds
     * @return bool
     */
    function removePhotos(array $photoIds = array());
}

La méthode "findWithFilters" ne va retourner que les éléments nécessaires et ne peuplera donc que ceux là dans mon objet. Je crée ensuite un paginateur avec l'adapteur Null dans mon front (contrôleur) et je le passe à la vue. Je ne ballade pas de paginateur entre mes couches.

Pour ce qui est des relations entre les entités, tu n'es pas obligé de peupler les enfants mais le faire que quand c'est nécessaire. Ton mapper ne renvoie que le strict minimum et peuple les entités avec ce qu'il a.


A+ benjamin.


http://www.anonymation.com/ - anonymation - Studio de création.
http://code.anonymation.com/ - anonymation - blog - développement et architecture web

Hors ligne

 

#33 16-03-2010 14:04:46

armetiz
Membre
Lieu: Lyon
Date d'inscription: 26-02-2010
Messages: 53
Site web

Re: [Partage/Reflexion]MVC, Services, Mapper et Persistance

Bonjour,
Merci pour ton partage de réflexion.

Ce qu'il manque à Zend au niveau des Mapper, c'est en effet une class générique qui s'occupe de faire le sale boulot.
Delprog, tu viens du monde J2EE. Les mappers/models s'apparente à Entity Bean n'est-ce pas ?

La où je bloque avec les mappers/models pour la gestion des héritages et la gestion des champs relationnels; EJB propose une solution au niveau des Entity Bean.

L'utilisation des annotations @OneToOne et @Inheritance sont des solutions du problème ci-dessus.

Ce que tu propose en début de post est une solution à peut près similaire !? Où en es-tu ?

Car comme tu le dis, DbTable permet de gère un système d'héritage et de relation entre table. Mais cela ne fait que du travail coté Row_Abstract ou Rowset_Abstract, rien au niveau des Models et donc des DAO.

Boudiou, Qu'est-ce que cela peut manquer !!


Tu dis être passer à Doctrine 1.2, qu'est-ce que cela à changer ? Selon le principe de couche, Doctrine ce situe au niveau de Zend_DbTable non ? Donc le problème reste normalement le même ?

J'essaie de développer moi même un Mapper générique, mais étant malgré tout débutant, ca me prend un temps fou, et je réinvente la roue.. Pour au final faire un truc qui n'est ni robuste ni générique.

Hors ligne

 

#34 17-03-2010 14:00:25

Delprog
Administrateur
Date d'inscription: 29-09-2008
Messages: 670

Re: [Partage/Reflexion]MVC, Services, Mapper et Persistance

Je ne viens pas spécialement du monde JAVA, c'est simplement que leur implémentation des patterns, que je trouve robuste, m'inspire beaucoup (mais ce n'est pas la seule source d'inspiration).

Je suis passé à Doctrine car une équipe de dév. + une communauté sera toujours plus performante que moi tout seul avec mon petit ORM maison (et le peu de temps que je peux y consacrer). Ce que j'ai proposé, Doctrine le fait en mieux.
La version 1.2 permet, à partir d'un fichier de config, de générer les entités. Ensuite Doctrine est blindé de fonctionnalités plus ou moins intéressantes (la plupart très utiles). Ils ont implémentés des proxy pour "gérer" la magie (attention quand même) du lazy load, save() & Co, bref, pas la peine que j'épuise de l'énergie pour rien, le but était surtout de mettre la main dedans pour comprendre les rouages d'un tel système smile

Le cli de Doctrine est aussi très pratique.

Par contre, actuellement Doctrine 1.2 ne permet pas d'avoir une vraie couche métier riche (sauf surcouche), mais ça fonctionne plutôt à l'envers, on définit ses entités en fonction de la conception de la BDD. C'est aussi la version 2 de doctrine qui m'a fait réagir, puisque c'est ni plus ni moins qu'un Hibernate-Like pour PHP (entity manger et unit of work) , et dans lequel tu retrouveras d'ailleurs un système d'annotations (que je n'affectionne pas particulièrement) similaire à l'exemple que tu me donnes. Tu devrais parcourir un peu la doc (de la 2.0) pour te faire une idée. Dans cette version, plus de problèmes, les entités ne sont pas générées par l'ORM.

En attendant, avec la 1.2 j'essaie d'utiliser les "alias" pour éviter trop de casse le jour où je détache "pour de vrai" mon métier de la persistance.


A+ benjamin.

Dernière modification par Delprog (17-03-2010 14:01:23)


http://www.anonymation.com/ - anonymation - Studio de création.
http://code.anonymation.com/ - anonymation - blog - développement et architecture web

Hors ligne

 

#35 17-03-2010 20:37:17

citronbleu-v
Membre
Lieu: Béziers ou Arles
Date d'inscription: 03-02-2009
Messages: 79
Site web

Re: [Partage/Reflexion]MVC, Services, Mapper et Persistance

Il y a quelque chose qui m'intrigue avec Doctrine. Peut on changer la classe Doctrine_Collection ou l'étendre pour chaque ModelTable si on le souhaite ? car j'aimerais faire quelques chose du genre :

Code:

$serviceFamille = Service_Famille::getInstance();
$serviceFamille->getTable()->findAll()->toKeyNamePrenomArray(); // getTable() fait un simple return Doctrine_Core::getTable('Model_Famille');

car pour le moment je fais comme ça :

Code:

$familles = $serviceFamille->getTable()->findAll();
$familles = Service_Famille::toKeyNamePrenomArray($familles);

Aussi-non pour parler du couplage de Zend et Doctrine et Réflexion smile :
Pour mes formulaires j'ai couplé les Validateurs de mes Modèles (Doctrine) + les Validateurs des éléments du formulaire.

Je pense qu'il vaut mieux mettre les validations importantes qui ne changerons jamais au plus au niveau. Exemple un champs email dans une base de données ne pourra contenir que des emails donc validation sur le modèle. Si par contre on veut que sur certains formulaires le domaine du mail ne soit que @free.fr alors là j'utilise les Validateur au niveau du formulaire.

Au final j'ai donc quelque chose du genre :

Code:

$form   = new Form_User();   // étend Zend_Form
$model = new Model_User();  // étend Model_Entity_User (Doctrine_Record)

$formAdvanced     = new Form_Advanced($form, $model); // mal nommé au final (Model_Validator plutôt ou My_Validator)
$formAdvanced->setMessageTemplates(array('email' => $this->view->translate('ce nest pas un email'))); // Message personnalisé suivant les clé des erreurs de Zend_Form et Doctrine.

if ($_POST && $formAdvanced->isValid($this->_getAllParams())) { // isValid du formulaire + du modele
      $model->save();
}

Du coup il me semble que je fais le contraire de Delprog. Enfin du moins j'ai décider d'utiliser Zend_Form pour la création des champs et leurs gestions des erreurs qui me reste pratique.

Hors ligne

 

#36 18-03-2010 08:42:20

nORKy
Membre
Date d'inscription: 06-03-2008
Messages: 1098

Re: [Partage/Reflexion]MVC, Services, Mapper et Persistance

1/ oui tu peux à partir de Doctrine 1.2. Tu définis ta classe et tu l'affecte "au core" qui l'utilisera alors pour créé les collections lorsque nécessaire. N'oublie pas qu'il existe des mots clé tel que "INDEX BY" si nécessaire

2/ Il faut savoir que Doctrine 2 n'embarque(ra) pas de validation. Justement parce que l'équipe de Doctrine pense que les framework sont largement équipé de composant fiables. (souvent, les personnes qui utilises doctrine utilise aussi un framework php)

Perso, c'est ma classe de service qui instancie ma classe de formulaire.
C'est mon service qui va aussi rajouté des options ou placé des valeurs dans mon formulaire (et pas le classe de formulaire elle même)
Ensuite, mon controlleur se charge d'appelé la méthode de validation (car c'est lui qui accède aux variables post) et passe à mon service $form->getValues().  ($userService->create($form->getValues())
Ainsi, mon controlleur n'accède pas aux propriétés du formulaire et si je change qqchose dans mon formulaire, je n'aurai qu'a intervenir dans mon service ou la classe de mon formulaire.


----
Gruiiik !

Hors ligne

 

#37 22-03-2010 10:48:46

armetiz
Membre
Lieu: Lyon
Date d'inscription: 26-02-2010
Messages: 53
Site web

Re: [Partage/Reflexion]MVC, Services, Mapper et Persistance

Merci pour ces réponses,
J'ai parcourus la documentation de Doctrine 2 en diagonale, et regardé les parties qui m'intéressent (forcement).
Mais sachant que Doctrine 2 est toujours en Alpha, et que ce n'est pas dans Zend Framework pour tout de suite... J'ai lâché l'affaire...

Mais je pense que je vais revoir Doctrine 1.2 qui pourrai m'apporter des solutions.

C'est assez horrible, car j'ai identifié mes problèmes, et je ne trouve pas de solution. Je ne cherche pas de solution clé en main, mais simplement une direction à prendre.

Puis-je reprendre mes problèmes et voir si vous pouvez y apporter un début de solution ?
D'ailleurs, cela peut se résumer à de simples questions; Comment réalisez-vous le chargement des données au niveau de vos Models, pour que l'application communique à l'aide Entité et non de DbTable_Row ?, ou encore Comment utilisez-vous les Models, Mappers et DbTable/Doctrine pour gérer l'héritage de données située au niveau de la persistance ?

Fonctionner en utilisant DbTable_Row c'est super facile pour la gestion des dépendances, l'héritage de table aussi avec findByParent, même si l'écriture un peu moins user-friendly.

Si j'utilise Doctrine, j'aurai les mêmes soucis non ? Car Doctrine ne fera que remplacer DbTable ? Tout les problèmes concernant la gestion des chargement des dépendances ou encore la gestion des héritages de Table resteront les mêmes ? Et surtout, il n'y aura pas de solution à la liaison des Models ?

A ces deux problèmes, j'ai l'impression - après 1 mois et demi de recherche - que la solution consiste en du bidouillage chez tout le monde. Qu'il n'y a pas une manière de faire qui solutionne 90% des problèmes.
Car pour l'instant, mon application fonctionne, j'ai réussi à faire fonctionner le cahier des charges; mais bon dieu que c'est lourd à maintenir et à implémenter pour de nouvelles fonctions.

PS : C'est une bouteille à la mer, un appel à l'aide, enfin, tout ces trucs de SOS quoi.
PS2 : Avez-vous de la documentation sur l'utilisation de Doctrine 1.2 avec Zend Framework 1.10 ?
Merci à vous.

Dernière modification par armetiz (22-03-2010 10:49:49)

Hors ligne

 

#38 24-03-2010 00:39:31

probitaille
Membre
Lieu: Montréal
Date d'inscription: 20-04-2009
Messages: 336
Site web

Re: [Partage/Reflexion]MVC, Services, Mapper et Persistance

Salut armetiz,

Grâce à ce sujet très éducatifs (Merci Delprog), je suis en plein apprentissage pour faire l'intégration de Doctrine 1.2 dans mes futures projets Zend. J'ai recherché de la documentation sur l'utilisation de Doctrine avec le Zend Framework. Il y a beaucoups de documentation concernant l'implantation de Doctrine dans Zend mais je crois la documentation de Doctrine relié avec celle des modèle dans Zend va t'aider à faire fonctionner un application pas trop complexe.

Malheureusement, je ne parle pas d'application complexe avec les couches métiers, proxy, des notions dont je dois faire l'étude théorique pour comprendre le fonctionnement de tout cela. Je ne peux pas t'aider grandement pour ton problème.

Je dois dire que Delprog m'a ouvert une grande porte vers la notion du ORM, je suis donc la suite de l'histoire avec intérêt. J'ai hâte de voir ce que ZF2 va nous permettre de faire.

Dernière modification par probitaille (24-03-2010 00:39:44)

Hors ligne

 

#39 25-03-2010 08:41:44

nORKy
Membre
Date d'inscription: 06-03-2008
Messages: 1098

Re: [Partage/Reflexion]MVC, Services, Mapper et Persistance

Allez, je crois que je l'avais déjà posté, mais je le remets.
Voici déjà une bonne base pour l'integration de doctrine.

application.ini

Code:

doctrine.dsn                           = "mondsn"
doctrine.data_fixtures_path     = APPLICATION_PATH "/configs/data/fixtures"
doctrine.sql_path                   = APPLICATION_PATH "/configs/data/sql"
doctrine.migrations_path        = APPLICATION_PATH "/configs/migrations"
doctrine.yaml_schema_path   = APPLICATION_PATH "/configs/schema.yml"
doctrine.models_path             = APPLICATION_PATH "/models"

doctrine.generate_models_options.pearStyle            = true
doctrine.generate_models_options.baseClassesDirectory = 
doctrine.generate_models_options.baseClassPrefix      = Base_
doctrine.generate_models_options.classPrefix          = Model_
doctrine.generate_models_options.classPrefixFiles     = false
doctrine.generate_models_options.phpDocPackage        = "Model"
doctrine.generate_models_options.phpDocSubpackage     = "Doctrine"
doctrine.generate_models_options.phpDocName           = "norky"
doctrine.generate_models_options.phpDocEmail          = "monemail@dom.fr"

La resource :

Code:

protected function _initDoctrine()
{
        $this->bootstrap('autoload');
    
        // obligatoire pour sfYaml
        $this->getApplication()->getAutoloader()->pushAutoloader(array('Doctrine_Core', 'autoload'));
    
        $doctrineConfig = $this->getOption('doctrine');
    
        $manager = Doctrine_Manager::getInstance();

        $manager->setAttribute(Doctrine_Core::ATTR_AUTO_ACCESSOR_OVERRIDE, true);
        $manager->setAttribute(Doctrine_Core::ATTR_MODEL_LOADING, Doctrine_Core::MODEL_LOADING_PEAR);
        $manager->setAttribute(Doctrine_Core::ATTR_AUTOLOAD_TABLE_CLASSES, true);
        $manager->setAttribute(Doctrine_Core::ATTR_MODEL_CLASS_PREFIX, 'Model_');
        $manager->setAttribute(Doctrine_Core::ATTR_QUERY_LIMIT, Doctrine_Core::LIMIT_ROWS);
        
        $conn = Doctrine_Manager::connection($doctrineConfig['dsn'], 'db');

        // return $conn;
        return $manager; 
    }

Le script doctrine.php (pour l'exécution ligne de commande)

Code:

<?php

// Define path to application directory
defined('APPLICATION_PATH')
    || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));

// Define application environment
defined('APPLICATION_ENV')
    || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production'));

// Ensure library/ is on include_path
set_include_path(implode(PATH_SEPARATOR, array(
    realpath(APPLICATION_PATH . '/../library'),
    get_include_path(),
)));


/** Zend_Application */
require_once 'Zend/Application.php';

// Create application, bootstrap, and run
$application = new Zend_Application(
    APPLICATION_ENV,
    APPLICATION_PATH . '/configs/application.ini'
);

$application->getBootstrap()->bootstrap('doctrine');

$cli = new Doctrine_Cli($application->getOption('doctrine'));
$cli->run($_SERVER['argv']);

Ainsi donc, le scripts génère dans application/models les models qui sont respectent la norme PEAR et donc supporté par l'autoload générer par Zend_Application_Module_Autoloader

Alors, on peut poussé encore plus loin, par exemple inclure les clé des setAttribute dans application.ini, intégrer doctrine.php dans zh.sh, mais la, c'est déjà bien intégrer. L'important pour moi était de générer mes models correctement et pouvoir les utilises dans Zend via un autoloader et également que mon script doctrine.php dépends de la même ressource que mon applicatif Zend


----
Gruiiik !

Hors ligne

 

#40 25-03-2010 09:32:14

Delprog
Administrateur
Date d'inscription: 29-09-2008
Messages: 670

Re: [Partage/Reflexion]MVC, Services, Mapper et Persistance

Hello,

Il est aussi possible de créer une ressource doctrine pour Zend_Application à partir de la 1.8 (pour ceux qui préfèrent).

Peut-être à améliorer, mais ça fonctionne smile

Code:

<?php
/**
 * Doctrine resource
 *
 * @category   Tight
 * @package    Tight_Application
 * @subpackage Resource
 * @author     Benjamin Dulau
 */
class Tight_Application_Resource_Doctrine extends Zend_Application_Resource_ResourceAbstract
{
    /**
     * @var Doctrine_Manager
     */
    protected $_manager;
    
    protected $_options = array();

    /**
     * Initialize Doctrine
     * 
     * @return Doctrine_Manager
     */
    public function init()
    {                           
        $this->_options = $this->getOptions();
                                
        $autoloader = $this->getBootstrap()->getApplication()->getAutoloader();
        $autoloader->pushAutoloader(array('Doctrine', 'autoload'));
        //Doctrine_Core::setModelsDirectory($this->_options['models_path']);       
        spl_autoload_register(array('Doctrine', 'modelsAutoload'));          

        $manager = Doctrine_Manager::getInstance();
        $manager->setAttribute(Doctrine_Core::ATTR_AUTO_ACCESSOR_OVERRIDE, true);
        $manager->setAttribute(
            Doctrine_Core::ATTR_MODEL_LOADING,
            Doctrine_Core::MODEL_LOADING_CONSERVATIVE                     
        );
        $manager->setAttribute(Doctrine_Core::ATTR_AUTOLOAD_TABLE_CLASSES, true);
        // Attention au quote identifier, c'est pas forcément conseillé
        $manager->setAttribute(Doctrine_Core::ATTR_QUOTE_IDENTIFIER, true);

        // connection
        $dsn = $this->_options['dsn'];
        
        $conn = Doctrine_Manager::connection($dsn, 'doctrine');
        $conn->setAttribute(Doctrine_Core::ATTR_USE_NATIVE_ENUM, true);
        $conn->setCharset('utf8');
            
        return $conn;
    }
}

Ensuite dans le ini, il faut penser à bien préciser le chemin vers le dossier de ressources perso et simplement ajouter "resources." devant la config que donne nORKy.

Code:

pluginPaths.Tight_Application_Resource = APPLICATION_PATH "/../lib/Tight/Application/Resource"

;.... plus loin
resources.doctrine.dsn = "mysql://utilisateur:password@127.0.0.1/test"
resources.doctrine.data_fixtures_path = APPLICATION_PATH "/../etc/db/data/fixtures-preprod"
;....etc.

Le fait d'ajouter un paramètrage sur la ressource doctrine dans le fichier ini fera que la ressource sera automatiquement chargée, donc rien à faire.


A+ benjamin.


http://www.anonymation.com/ - anonymation - Studio de création.
http://code.anonymation.com/ - anonymation - blog - développement et architecture web

Hors ligne

 

#41 29-03-2010 10:28:24

armetiz
Membre
Lieu: Lyon
Date d'inscription: 26-02-2010
Messages: 53
Site web

Re: [Partage/Reflexion]MVC, Services, Mapper et Persistance

Bon,
Je vais m'y mettre le plus rapidement possible, il semblerai que se soit une solution très intéressante.

Si j'ai bien compris en lisant les blogs et documentations en diagonales, la notion de Mapper va disparaitre avec l'utilisation de Doctrine.
J'espère pouvoir prendre du temps cette semaine pour essayer une migration.

Merci à vous.

Thomas.

Hors ligne

 

#42 30-03-2010 16:43:12

armetiz
Membre
Lieu: Lyon
Date d'inscription: 26-02-2010
Messages: 53
Site web

Re: [Partage/Reflexion]MVC, Services, Mapper et Persistance

Bonjour tout le monde,
Je reviens d'une riche journée avec Zend 1.10 & Doctrine 1.2.

Très intéressant, tout fonctionne nickel. Simplification du code, et l'utilisation du pattern Service Layer rends les choses encore plus élégantes.

Jusqu'à 16h30, toutes les raisons qu'on fait regarder Doctrine de près ont été un franc succès.
Sauf au moment crucial ! (Tada !) Où j'ai voulu mettre en place l'héritage... Et là, quel déception pour la version 1.2 de Doctrine...

Petit exemple avec Yaml

Code:

Shows:
  tableName: shows
  columns:
    title:
      type: string (20)

Videos:
  inheritance:
    type: column_aggregation
    extends: Shows
  tableName: videos
  columns:
    duration:
      type: string (20)

C'est ce code que l'on voit dans la documentation, sur les forums et autre groupe de discutions.
Lorsque l'on génère les Models à partir de ce code YAML, voici à quoi ressemble le code généré

Code:

class Model_Base_Shows extends Doctrine_Record
{
    public function setTableDefinition()
    {
        $this->setTableName('shows');
        $this->hasColumn('title', 'string', 20, array(
             'type' => 'string',
             'fixed' => 0
             ));
        $this->hasColumn('duration', 'string', 20, array(
             'type' => 'string',
             'fixed' => 0
             ));

        $this->setSubClasses(array(
             'Model_Videos' => 
             array(
              'type' => 'Videos',
             )
             ));
    }

//.... d'autre code...
}

class Model_Base_Videos extends Model_Shows
{
    public function setUp()
    {
        parent::setUp();
        $this->hasOne('Model_Shows as Shows', array(
             'local' => 'id_video',
             'foreign' => 'id_show'));
    }
}

AHHHH, mais qu'est-ce que c'est que ce bordel boudediou !
Les propriétés de Vidéos sont déportées vers Shows... Mais où est l'héritage ? Ba y'en a pas ...

Voici donc la grosse déception de ma journée.
La documentation de Doctrine 1.2 utilise des exemples où les sous-classes n'ont jamais de propriétés.. Pourquoi.. ?!

J'ai pu voir que Doctrine 2 gèrerai correctement l'héritage par agrégation de table. Je vais de ce pas tester..
En espérant pour cette fois, que l'on ne m'a pas vendu du rêve.

PS: Pour ceux qui commence avec Zend & Doctrine.. La documentation existe, mais faut s'accrocher pour trouver tout les éléments nécessaires. Quid d'un quickstart ?

Edit : Pour passer vers Doctrine 2, il faut plus d'une heure... On vera ca une autre fois.. Pour le coups, l
Les ressources sur le net sont pauvres.

Edit 2 : Peut-être que j'ai mal fait un truc, si vous avez la solution.. Je suis preneur.

Dernière modification par armetiz (30-03-2010 16:57:12)

Hors ligne

 

#43 30-03-2010 17:44:16

Blount
Membre
Date d'inscription: 23-06-2009
Messages: 98
Site web

Re: [Partage/Reflexion]MVC, Services, Mapper et Persistance

PS: Pour ceux qui commence avec Zend & Doctrine.. La documentation existe, mais faut s'accrocher pour trouver tout les éléments nécessaires. Quid d'un quickstart ?

Ça m'intéresserai d'avoir tes liens.
J'ai l'intention d'utiliser Doctrine, mais j'ai pas encore commencé à chercher des tutos, si tu peux m'épargner cette tâche wink

Hors ligne

 

#44 30-03-2010 23:51:15

mikaelkael
Administrateur
Lieu: Donges
Date d'inscription: 18-06-2007
Messages: 1176
Site web

Re: [Partage/Reflexion]MVC, Services, Mapper et Persistance

Hello,

Concernant Doctine 2, la version beta pourrait sortir dans les prochains jours et la version finale demandera encore au moins 4-5 mois.

@+


Less code = less bugs
Contributeur ZF - ZCE - ZFCE - Doc ZF (CHM & PDF) - Vice-trésorier AFUP 2011
Ubuntu 11.04 - ZendServer

Hors ligne

 

#45 31-03-2010 09:46:16

nORKy
Membre
Date d'inscription: 06-03-2008
Messages: 1098

Re: [Partage/Reflexion]MVC, Services, Mapper et Persistance

Oui, pour l'instant vaux mieux éviter Doctrine 2 à mon avis.

@armetiz:
L'héritage de type "column aggregation" ne créé qu'une seule table et Doctrine mets toutes les propriétés dans la table "de base" qui va généré la table.
Sinon, lors de la génération de table, il y aurait plusieurs table. (ou alors, il faudrait qu'il exécute des alter_tables, ..)

Tu peux faire $model = new_Video(); $model->duration = 12;

Je ne vois pas quel est le propblème.


----
Gruiiik !

Hors ligne

 

#46 31-03-2010 10:14:07

armetiz
Membre
Lieu: Lyon
Date d'inscription: 26-02-2010
Messages: 53
Site web

Re: [Partage/Reflexion]MVC, Services, Mapper et Persistance

Merci pour vos réponses,
Concernant mon problème, je dois être à coté de la plaque, car tout le monde (IRC / Forum) trouve une solution; sauf quelles ne me conviennent pas.
Explication :
Voici le schéma de ma DB, celui-ci existe déjà en version grandeur nature, et contient des données.
http://armetiz.info/inheritance.png
Nous pouvons remarquer que B et C sont des tables reliés à A par une Foreign Key. Cette technique permet de réaliser un héritage de table, en minimisant la duplication de donnée, et en conservant les contraintes d'intégrités sur les tables (principalement UNIQUE).
A est une table contenant un code, qui se veux unique. Au niveau logique, B et C on donc un code, qui est unique pour les deux.
A est liés à une table Program. B et C ont donc aussi une relation one-to-one.

J'ai du lire la documentation de Doctrine une dizaine de fois pour la partie sur l'héritage. Manque de bol, je suis passé à coté de cette phrase à chaque fois : "With column aggregation inheritance all classes share the same table, and all columns must exist in the parent.".
C'est balo me direz-vous...

Là où j'ai un soucis, c'est pour pluger Zend / Doctrine (ou ZendDbTable il y a 1 semaine).
En effet, au niveau POO, j'aimerai que mon Entité A soit une classe parent, et que B et C hérite de A.
Que le code propre à A, soit uniquement dans la définition de classe A.

Le but du jeu étant au final de faire :

Code:

$objB = new B ();
$objB->code = "a_unique_code";
$objB->user = "léopole";
$objB->save ();

Et mon soucis, c'est pour les méthodes CRUD.
Car un B::create () doit d'abord créer l'objet A, en utilisant une transaction SQL en cas de problème (exemple, unique key duplicate), et ensuite créer l'objet B.
La méthode B::update () doit mettre à jours A et ensuite B (ou inversement !?.)
La méthode B::delete () doit supprimer B et ensuite A (question d'intégrité). Maintenant, si j'utilise ON DELETE CASCADE, le soucis n'est pas réellement présent... Supprime un objet revient à supprimer l'autre. Mais bon.
La méthode B::read () qui sera la plus utilisée, doit charger A et ensuite B. Selon Doctrine Hydrater mon objet B, ou selon notre langage, fournir les attributs de A et B dans l'objet final. Le tout bien évidement, avec une seul requête SQL si c'est possible. Car les A/R, c'est sympa, c'est mignon... Mais sa bouffe 2x plus de ressource au final.

Doctrine 2 intègrera @Join, qui règlera complètement mon problème. Si je m'en réfère à la documentation de Doctrine 2, ou même à celle des EJB dont Doctrine 2 s'inspire fortement.

Le soucis, Doctrine 2, c'est de l'alpha.. Et c'est en PHP 5.3. Même mon Eclipse fait la gueule quand j'ouvre Doctrine 2 et qu'il voit les namespace.

Sur IRC de Doctrine, comme sur ce Forum, j'ai l'impression que mon problème n'existe pas, car il y a une solution.. Mais je ne la trouve pas...
D'ici peu de temps je vais devoir passer à une solution que je n'aime pas, car il va falloir produire.

Et vous, vous en pensez quoi ?

PS : Vous avez trouver la différence entre héritage Simple et column_aggregation sous Doctrine, car chez moi, car produit les mêmes Models.

PS 2 : Mes liens pour Doctrine :
http://www.danceric.net/2009/06/06/doct … framework/
http://giorgiosironi.blogspot.com/2009/ … ework.html
http://www.z-f.fr/forum/viewtopic.php?id=4027&p=2 (post #39 de nOrky)
http://www.itanea.com/blog/2008/11/27/z … red-blanc/
http://www.doctrine-project.org/documen … t-overview
http://www.zendcasts.com/ ( Plusieurs podcast sur Doctrine... A voir si tu as un peu de temps, sa repose le cerveau).
http://www.z-f.fr/forum/viewtopic.php?id=4063

Ensuite, faut faire un jolie merge dans ton cerveau big_smile Et tu adapte sur ZF 1.10 car 80% des tutos sont pour ZF 1.8.

En tout cas, merci à vous, et bonne anniversaire au forum et forumiste wink

Dernière modification par armetiz (31-03-2010 11:13:02)

Hors ligne

 

#47 31-03-2010 14:09:02

nORKy
Membre
Date d'inscription: 06-03-2008
Messages: 1098

Re: [Partage/Reflexion]MVC, Services, Mapper et Persistance

Dire que lorsque une table a une clé étrangère sur un autre, c'est de l'héritage, est totalement faux pour moi.
Dire que ca crée une relation, OK, mais surement pas de l'héritage.
De ce fait, pour moi, ce que tu veux faire ne m'arrivera jamais (choix personnel de conception)
Mais...

Ce que tu veux faire est impossible dans doctrine 1.2.
Si tu veux 2 tables, tu fais de l'héritage "concret"
Si tu veux qu'une table, tu fais de du "column_agregation" ou bien du simple.

La différence entre "simple" et "column_agregation".

Simple :
Doctrine ne sera absolument pas faire la différence entre l'objet B et A.
Tu fais un "select A", tu auras le même résultat que "select B", et l'hydration se créera dans tous les cas une table A.

Column_agregation
Doctrine sait faire la différnece entre A et B.
Ainsi "select A", renverras les lignes concernant l'object A et l'hydration se fera avec des objet A, de même que "select B", renverras les lignes concernant l'object B et l'hydration se fera avec des objet B

PS : N'oublie pas que Doctrine te génère des models "de base" et que tu peux créés tes tables et Record qui en hérite pour ainsi surchargé le comportement des fonctions de base


----
Gruiiik !

Hors ligne

 

#48 31-03-2010 14:47:24

armetiz
Membre
Lieu: Lyon
Date d'inscription: 26-02-2010
Messages: 53
Site web

Re: [Partage/Reflexion]MVC, Services, Mapper et Persistance

nORKy a écrit:

Dire que lorsque une table a une clé étrangère sur un autre, c'est de l'héritage, est totalement faux pour moi.

Faire une FK ne signifie pas créer un héritage, je suis d'accord.
C'est une alternative aux lacunes des SGBDR qui ne supportent pas l'héritage de table (Je parle ici de MySQL).

C'est aussi le choix technique que fera Doctrine 2, et c'est actuellement le choix technique de J2EE / EJB.


Dans ce cas nORKy, sous quel forme est-ce que tu sauvegarde tes données issues d'une POO avec héritage ?
Tu choisis "colmnun_aggregation" ou "concrete" ? Sachant que les deux ont un problème de taille : La perte des contraintes d'intégrité de type unique (cf, mon exemple avec les code), ou alors l'utilisation d'espace inutile.

Car dans le cas de column_aggregation, si on a une super-classes A dont hérite 50 sous-classes, apportant chacune 10 propriétés supplémentaires... La table A va contenir 500 colonnes + les attributs de bases de A... C'est pas super optimisé ? Vous en avez conscience ? (Ne pas le prendre au 1° degré... c'est pour appuyer dessus, pas pour enfoncer.. ).

Mon application est assez petite, je vais me permettre l'héritage sur une seul table pour conserver mes contraintes d'intégrité. Mais.. C'est dommage..

Hors ligne

 

#49 06-07-2010 18:03:18

ant1j
Nouveau membre
Date d'inscription: 06-07-2010
Messages: 1

Re: [Partage/Reflexion]MVC, Services, Mapper et Persistance

Bonjour à tous,

Je vois que le dernier message date un peu mais qu'importe ...

Après de longue recherche infructueuses je tombe enfin sur ce sujet abordant des questions que je me pose depuis pas mal de temps ...

Je voulais simplement avoir un "état des lieux"  de l'utilisation du couple ZF / Doctrine dans leurs dernières versions stables respectives (1.10 / 1.2), et surtout préciser le rôle de Doctrine : "Jusqu'où" va Doctrine dans notre architecture en couche ???

Parce qu'entre mapper, DAO, Gateway, Entity, Model, etc. on s'y perd un peut quand on a pas l'habitude. La discussion aborde l'utilisation de cette ORM, mais avec l'historique, difficile de voir ce que cela remplace, améliore, ... ?

Je suis en train de mettre en place une application ; j'opte à priori pour l'utilisation des couches de Services et Modèles, ... et Doctrine, mais je ne sais donc justement pas ce qu'il faut déléguer à Doctrine.

J'ai créé des modèles qui utiliseront les classes créées par Doctrine, et non directement ces dernières (qui si j'ai bien compris, gère la persistance - et le mapping (?) mais là je suis moins sûr).


Bref, pour résumer, parmi toutes les couches théoriques (DAO, mapper, Entity, Model) quelles sont celles que Doctrine peut remplir ?


Je vous remercie par avance de vos réponses, et surtout merci encore pour tous ces éclaircissements !!

Hors ligne

 

#50 22-07-2010 14:44:32

Moimeme
Membre
Date d'inscription: 19-04-2007
Messages: 120

Re: [Partage/Reflexion]MVC, Services, Mapper et Persistance

Concernant Doctrine 2 (qui est maintenant en beta) quelqu'un a commencé a regarder pour créer une ressource doctrine2 pour Zend_Application ?

Hors ligne

 

Pied de page des forums

Propulsé par PunBB
© Copyright 2002–2005 Rickard Andersson
Traduction par punbb.fr

Graphisme réalisé par l'agence Rodolphe Eveilleau
Développement par Kitpages