Consultez la FAQ sur le ZF avant de poster une question
Vous n'êtes pas identifié.
Pages: 1
/!\ Attention, ceci n'est valable que pour les versions actuellement disponibles et cité dans ce sujet. Il est possible qu'il y ai des différences avec l'évolution des différents modules./!\
Ce tutoriel pourra évoluer en fonction des mises à jour de version. Je ne parlerais pas de l'aspect purement technique dans ce tutoriel tout simplement parce que je ne le maitrise pas encore assez pour être sûr de ne pas dire de bêtises. J'y reviendrais ultérieurement.
Tout d'abord il est nécessaire d'avoir une base propre de son application.
Pré-requis
- Posséder ZF2.0.beta2, la dernière version se trouve ici : https://github.com/zendframework/zf2 ou http://packages.zendframework.com/ pour une version beta2 "stable". Je ne détail pas plus je pense que tout le monde sait ce que c'est .
- Télécharger le squelette d'une application ZendFramework2 : ZendSkeletonApplication disponible ici : https://github.com/zendframework/ZendSk … pplication (il est possible de récupérer la version adéquat du framework à partir du protocole git comme indiqué sur le readme
- Télécharger le squelette d'un module si vous le souhaitez : ZendSkeletonModule disponible ici : https://github.com/zendframework/ZendSkeletonModule
- Posséder DoctrineModule pour ZendFramework 2 (c'est une version mise à jour de SpiffyDoctrine) on peux la trouver à cette adresse : https://github.com/doctrine/DoctrineModule . Ce module est une intégration de Doctrine 2 pour le ZendFramework 2, il va vous permettre d'utiliser très simplement Doctrine 2.
- Posséder DoctrineORMModule disponible ici : https://github.com/doctrine/DoctrineORMModule . C'est la partie la plus importante, c'est ce qui va vous permettre de faire la liaison entre vos "objets PHP" et votre base de données.
La partie framework est très simple à récupérer et tout est expliqué si vous utilisez le protocole git. Une aide est disponible ici pour pouvoir utiliser git sur votre machine : http://help.github.com/win-set-up-git/
Je vais détailler pour la récupération du module DoctrineORMModule. Si vous faites attention vous verrez que celui-ci nécessite comme submodule le framework Doctrine 2. Il y a une solution identique à celle expliqué pour récupérer ZF2 (elle est expliqué de nouveau dans le fichier install) mais si vous ne pouvez pas utiliser le protocole git sur votre machine (proxy ou autre) il est possible de tout télécharger manuellement. Faites attention à bien parcourir les dossiers "lib/vendor" ou "vendor" qui contiennent des liens vers des fichiers à télécharger. Privilégiez les version recommandé (suite de lettre et de chiffre à côté du lien vers le répository github du module/framework/package) pour vous assurer qu'il n'y ai pas d'incohérence de versions.
Une fois tous vos fichiers téléchargés, vos êtes fin prêt pour débuter ce tutoriel.
Installation
Je pars du principe que l'installation de base d'une application ZendFramework 2 est acquise pour tous, je ne vais donc pas détailler plus cette étape.
Le fichier application.config.php est le fichier "finale" une fois tout installé, il est évident que vous n'aurez pas besoin d'avoir tous les modules de déclaré, pour que votre application fonctionne seul "Application" est nécessaire.
Installation du module DoctrineModule
C'est très simple, il vous suffit de copier le dossier "DoctrineModule" dans le dossier "vendor" de votre application
Installation du module DoctrineORMModule
Même chose que pour le module DoctrineModule. Attention tout de même à bien mettre les fichiers et dossiers comme expliqué dans la partie "pré-requis" car il y a des librairies supplémentaire à ajouter à ce module pour qu'il fonctionne. Généralement dans le dossier "vendor" ou "lib/vendor" du module ou du sous-module.
Fin de l'installation
Normalement vous devriez avoir arborescence de fichiers qui ressemble à celle-ci :
ApplicationName \__ config \__ autoload \__ data \__ module \__ Application \__ config \__ autoload \__ src \__ Application \__ Controller \__ View \__ etc ... \__ view \__ public \__ css \__ images \__ js \__ vendor \__ DoctrineModule \__ DoctrineORMModule \__ ZendFramework
Maintenant que vous avez une arborescence classique et correctement installée il est nécessaire de passer à l'étape de configuration.
Configuration
Tout d'abord il faut configurer le fichier application.config.php et y ajouter les nouveaux modules comme si c'était des modules "classiques" de votre application
[lang=php] 'modules' => array( 'Application', 'DoctrineModule', 'DoctrineORMModule', ),
Maintenant vous devez aller dans le module DoctrineORMModule/config et copier le fichier module.doctrine_orm.local.config.php.dist et le coller dans "config/autoload/" à la racine de votre application. Renommer le fichier en module.doctrine_orm.local.config.php
Nous allons maintenant regarder ce qu'il y a dedans :
[lang=php] /** * Doctrine ORM Configuration * * If you have a ./configs/autoload/ directory set up for your project, you can * drop this config file in it and change the values as you wish. This file is intended * to be used with a standard Doctrine ORM setup. If you have something more advanced * you may override the Zend\Di configuration manually (see module.config.php). */ $settings = array( // if disabled will not register annotations 'use_annotations' => true, // if use_annotations (above) is set to true this file will be registered 'annotation_file' => __DIR__ . '/../../vendor/DoctrineORMModule/vendor/doctrine-orm/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php', // chemin vers la classe qui gère les annotation (on y reviendra plus tard). Normalement vous n'avez pas à le changer si vous avez l'architecture cité ci-dessus // enables production mode by disabling generation of proxies 'production' => false, // à passer à true en production // sets the cache to use for metadata: one of 'array', 'apc', or 'memcache' 'cache' => 'array', // only used if cache is set to memcache 'memcache' => array( 'host' => '127.0.0.1', 'port' => '11211' ), // connection parameters 'connection' => array( 'driver' => 'pdo_mysql', // driver, à changer en fonction de la bdd que vous utilisez 'host' => 'localhost', // host de votre bdd 'port' => '3306', // port de connexion à la bdd 'user' => 'username', // utilisateur pour se connecter à la bdd 'password' => 'password', // mot de passe de connexion à la badd 'dbname' => 'database', ), // driver settings 'driver' => array( 'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver', // Classe qui va lire vos annotations 'namespace' => 'Application\Entity', // namespace de vos classe à lire 'paths' => array('module/Application/src/Application/Entity') // chemin de vos classes à lire ), // namespace aliases for annotations 'namespace_aliases' => array( ), ); /** * YOU DO NOT NEED TO EDIT BELOW THIS LINE. /!\ NE PAS TOUCHER A PARTIR D'ICI /!\ */ $cache = array('array', 'memcache', 'apc'); if (!in_array($settings['cache'], $cache)) { throw new InvalidArgumentException(sprintf( 'cache must be one of: %s', implode(', ', $cache) )); } $settings['cache'] = 'doctrine_cache_' . $settings['cache']; return array( 'doctrine_orm_module' => array( 'annotation_file' => $settings['annotation_file'], 'use_annotations' => $settings['use_annotations'], ), 'di' => array( 'instance' => array( 'doctrine_memcache' => array( 'parameters' => $settings['memcache'] ), 'orm_config' => array( 'parameters' => array( 'opts' => array( 'entity_namespaces' => $settings['namespace_aliases'], 'auto_generate_proxies' => !$settings['production'] ), 'metadataCache' => $settings['cache'], 'queryCache' => $settings['cache'], 'resultCache' => $settings['cache'], ) ), 'orm_connection' => array( 'parameters' => array( 'params' => $settings['connection'] ), ), 'orm_driver_chain' => array( 'parameters' => array( 'drivers' => array( 'application_annotation_driver' => $settings['driver'] ), 'cache' => $settings['cache'] ) ), ), ), );
Une fois ce fichier bien rempli, vous avez tout configuré pour utiliser Doctrine 2 avec votre application ZendFramework 2.
Nous arrivons maintenant à l'étape la plus importe c'est la création de nos entités, la génération de la base de données et la création de vos classes proxy.
Utilisation
Vous devez écrire vos classes en fonction des informations saisies dans le fichier de configuration du chapitre précédent.
Prenons l'exemple d'une classe album (tiré du tutoriel ZendFramework 2 d'akrabat : http://akrabat.com/wp-content/uploads/G … work-2.pdf) que nous allons adapter pour utiliser Doctrine 2.
Je vous conseil d'utiliser le système d'annotation qui permet de faire le plus de choses. Je vous renvoi à la documentation Doctrine 2 pour connaitre les différentes annotation disponibles et leurs fonctions.
Voici à quoi ressemble une classe PHP annoté (il est possible d'y ajouter des accesseurs, j'ai mes attributs en public uniquement pour faire mes tests).
[lang=php] namespace Application\Entity; use Doctrine\ORM\Mapping as ORM; // Pour utiliser les annotations /** * @ORM\Entity * @ORM\Table(name="album") */ class Album { /** * @ORM\Id * @ORM\Column(type="integer") * @ORM\GeneratedValue */ public $id; /** @ORM\Column(type="string") */ public $artist; /** @ORM\Column(type="string") */ public $title; }
Nous pouvons maintenant à partir de cette classe là utiliser l'outil de génération de tables et de proxy.
Génération
Nous allons utiliser la commande PHP si vous ne l'avez pas ajouter à votre PATH windows je vous renvoi vers google il y a énormément de tutoriel pour faire ça.
Ouvrir l'invite de commande windows. Placez vous dans le répertoire ".../DoctrineModule/bin/"
tapez ensuite cette commande :
php doctrine.php orm:schema-tool:create
Ceci va créer vos tables en fonction de vos entités et des annotations que vous avez saisi. Lorsque vous souhaiterez mettre à jour en rapport avec vos modifications il faudra utiliser cette commande :
php doctrine.php orm:schema-tool:update
Il ne vous reste plus qu'à générer vos fichier de proxy :
php doctrine.php orm:generate-proxies chemin_vers_le_dossier_où_vous_voulez_mettre_ces_fichiers
Accès aux données
Maintenant que tout est prêt il vous reste à accéder à vos données. Voici un code exemple permettant de récupérer et d'enregistrer des informations dans la table album.
[lang=php] $em = $this->getLocator()->get('doctrine_em'); // Permet de récupérer l'instance de l'entity manager. // Enregistrement de l'album $album = new Application\Entity\Album(); $album->artist = "artiste"; $album->title = "titre"; // Sauvegarde en base de données et enregistre l'id dans l'objet album $em->persist($album); $em->flush(); $album = $em->find("Application\Entity\Album", $album->id);
Voila la première partie de ce tutoriel touche à sa fin, n'hésitez pas à me faire des retours sur la mise en page, fautes, ou erreurs que j'aurai pu faire en l'écrivant. J'espère que ça vous sera utile !
Merci à Bakura pour ses conseils qui m'ont permis d'écrire cet article et de comprendre pas mal de chose dans le but de vous le faire partager. J'espère que tu auras un peu de temps pour aborder la partie "technique" comme nous avons pu en discuter.
Mise à jour du tutoriel pour intégrer de nouvelles informations, la mise en page sera modifiée ultérieurement
Il est possible de demander à l'injecteur de dépendance de récupérer et d'affecter l'Entity Manager à notre contrôleur.
Dans le fichier module.config.php :
[lang=php]return array( 'di' => array( 'instance' => array( 'alias' => array( 'album' => 'Album\Controller\AlbumController', ), 'Album\Controller\AlbumController' => array( 'parameters' => array( 'em' => 'doctrine_em', // configuration de l'Entity Manager ), ),
Dans mon contrôleur voici ce qu'il est nécessaire d'ajouter :
[lang=php] use \Doctrine\ORM\EntityManager; class AlbumController extends ActionController { /** * @var EntityManager */ protected $em; public function setEm(EntityManager $em) { $this->em = $em; return $this; } }
Pour utiliser l'Entity Manager il n'y a plus qu'à faire $this->em->...
Petit piège à faire attention pour ceux qui n'ont jamais utilisé doctrine, via les méthodes disponible depuis l'Entity Manager il y a "find($entityName(namespace), $id)". Il faut savoir que cette méthode est un "raccourcis". Voici l'exemple suivant :
[lang=php] $this->em->find('My\Entity', 1); // équivalent à $this->em->getRepository('My\Entity')->find(1); // Pour récupérer tous les éléments : $this->em->getRepository('My\Entity')->findAll();
Orkin
Mise à jour du 11/04/2012 :
- Un fichier de configuration a été renommé
- Tutoriel valide pour la béta 3
Dernière modification par Orkin (11-04-2012 16:40:57)
Hors ligne
Réservé
Hors ligne
Réservé au cas où
Hors ligne
J'essaye de lire ça plus en détail après mes partiels et je complèterai au besoin ...
Hors ligne
My appologies, I do not speak French at all (hope you can understand English)
I checked the code and with the help of google translate could understand most of it. That was very useful, cannot find anything like that on the web at all.
I'm working on zf2+doctrine2 thing myself now. One problem I cannot solve yet is how to use entities from different modules.
Driver configuration at module.doctrine_orm.config.php can have just one namespace, even though I can use alot of paths for entities. So when using doctrine from command line it does not recognize entities outside of that one single namespace.
Do you have any ideas on how to solve this?
Thanks alot!
Hors ligne
Hello, I'll try to answer in English.
I have not yet had the opportunity to test this kind of configuration. But I think it must operate with a configuration like this:
=================================================================
En français pour ceux qui veulent :
Salut, je vais essayer de te répondre en anglais.
Je n'ai pas utilisé ce genre de configuration. Mais je pense que ça doit fonctionner en utilisant une configuration de ce genre :
[lang=php] // driver settings 'driver' => array( 'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver', // Classe qui va lire vos annotations 'namespace' => array('Application\Entity', 'Module1\Entity', 'Module2\Entity'), // namespace de vos classe à lire 'paths' => array('module/Application/src/Application/Entity', 'module/Module1/src/Module1/Entity', 'module/Module2/src/Module2/Entity') // chemin de vos classes à lire ),
Dernière modification par Orkin (10-02-2012 11:23:17)
Hors ligne
Thanks, but no, that does not work. That was the first thing I tried, namespace cannot be an array.
Hors ligne
I found an answer at this article here http://www.jasongrimes.org/2012/01/usin … ramework-2
Just just need to configure it for each module separate (using module.config.php)
Hors ligne
Ok thanks for your tips
Hors ligne
Bonjour,
Je me permet de faire remonter ce post qui commence à dater un peu.
J'ai un petit soucis, j'ai suivi le tuto ici =http://www.jasongrimes.org/2012/01/using-doctrine-2-in-zend-framework-2/ afin de pouvoir répartir mes entités dans chaque module.
J'ai voulu utiliser les commandes doctrines pour créer les tables de ma base de données, mais j'ai une erreur...
Fatal error: Uncaught exception 'Zend\Loader\Exception\InvalidArgumentException' with message 'Autoloader class "doctrine" not loaded' in /home/CNPR/viallemonteil/TICE/Projets/Zend_Blog/vendor/zendframework/zendframework/library/Zend/Loader/AutoloaderFactory.php on line 92 Zend\Loader\Exception\InvalidArgumentException: Autoloader class "doctrine" not loaded in /home/CNPR/viallemonteil/TICE/Projets/Zend_Blog/vendor/zendframework/zendframework/library/Zend/Loader/AutoloaderFactory.php on line 92 Call Stack: 0.0007 228832 1. {main}() /home/CNPR/viallemonteil/TICE/Projets/Zend_Blog/vendor/doctrine/doctrine-module/bin/doctrine-module.php:0 0.0305 344976 2. Zend\Mvc\Application::init() /home/CNPR/viallemonteil/TICE/Projets/Zend_Blog/vendor/doctrine/doctrine-module/bin/doctrine-module.php:46 0.1250 1394688 3. Zend\ModuleManager\ModuleManager->loadModules() /home/CNPR/viallemonteil/TICE/Projets/Zend_Blog/vendor/zendframework/zendframework/library/Zend/Mvc/Application.php:241 0.1250 1395016 4. Zend\EventManager\EventManager->trigger() /home/CNPR/viallemonteil/TICE/Projets/Zend_Blog/vendor/zendframework/zendframework/library/Zend/ModuleManager/ModuleManager.php:104 0.1250 1395416 5. Zend\EventManager\EventManager->triggerListeners() /home/CNPR/viallemonteil/TICE/Projets/Zend_Blog/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php:208 0.1271 1416840 6. call_user_func() /home/CNPR/viallemonteil/TICE/Projets/Zend_Blog/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php:464 0.1271 1416872 7. Zend\ModuleManager\ModuleManager->onLoadModules() /home/CNPR/viallemonteil/TICE/Projets/Zend_Blog/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php:464 0.1999 1859376 8. Zend\ModuleManager\ModuleManager->loadModule() /home/CNPR/viallemonteil/TICE/Projets/Zend_Blog/vendor/zendframework/zendframework/library/Zend/ModuleManager/ModuleManager.php:85 0.2027 1865312 9. Zend\EventManager\EventManager->trigger() /home/CNPR/viallemonteil/TICE/Projets/Zend_Blog/vendor/zendframework/zendframework/library/Zend/ModuleManager/ModuleManager.php:152 0.2027 1865352 10. Zend\EventManager\EventManager->triggerListeners() /home/CNPR/viallemonteil/TICE/Projets/Zend_Blog/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php:208 0.2028 1867112 11. call_user_func() /home/CNPR/viallemonteil/TICE/Projets/Zend_Blog/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php:464 0.2028 1867144 12. Zend\ModuleManager\Listener\AutoloaderListener->__invoke() /home/CNPR/viallemonteil/TICE/Projets/Zend_Blog/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php:464 0.2028 1870720 13. Zend\Loader\AutoloaderFactory::factory() /home/CNPR/viallemonteil/TICE/Projets/Zend_Blog/vendor/zendframework/zendframework/library/Zend/ModuleManager/Listener/AutoloaderListener.php:40
Voici le code de mon application.config.php
[lang=php] return array( 'modules' => array( 'Application', 'DoctrineModule', 'DoctrineORMModule', 'News', 'User' ), 'module_listener_options' => array( 'config_glob_paths' => array( 'config/autoload/{,*.}{global,local}.php', ), 'module_paths' => array( './module', './vendor', './vendor/doctrine', ), ), 'service_manager'=>array( 'aliases'=>array( 'doctrine.entitymanager.orm_default'=>'doctrine_entity_manager' ) ), );
et mon fichier local
[lang=php] return array( // Whether or not to enable a configuration cache. // If enabled, the merged configuration will be cached and used in // subsequent requests. //'config_cache_enabled' => false, // The key used to create the configuration cache file name. //'config_cache_key' => 'module_config_cache', // The path in which to cache merged configuration. //'cache_dir' => './data/cache', // ... 'doctrine' => array( 'connection' => array( 'orm_default' => array( 'driverClass' => 'Doctrine\DBAL\Driver\PDOMySql\Driver', 'params' => array( 'host' => 'localhost', 'port' => '3306', 'user' => '****', 'password' => '****', 'dbname' => 'zend_test', ) ) ) ) );
Je ne vois pas trop d'où cela peut venir, je commence juste mon apprentissage avec ZF2...
Merci pour vos futures réponses.
Dernière modification par Birssan (14-12-2012 15:41:14)
Hors ligne
Pourquoi tu créés un alias vers l'entity manager ? Ce n'est pas très utile.
DoctrineModule a pas mal bougé depusi la date ou ce tutoriel a été écrit, c'est possible que ça ne soit plus compatible. Le './vendor/doctrine' n'est pas utile non plus.
La solution la plus simple est d'utiliser Composer maintenant. Composer va automatiqueemnt se charger de toute la partie autoloading (ton erreur quoi), c'est beaucoup plus simple à gérer.
Hors ligne
Et bien j'ai utilisé composer pour installer doctrine, j'ai résolu mon problème en me rendant compte que j'avais mi du code en trop au mauvais endroit.
Pour ce qui est des changements, je ne pense pas qu'il y en ait eu tant que ça, je n'ai pas trouvé de tutoriels récents pour Doctrine 2 avec ZF2.
Cependant j'ai encore un problème, étant donné que les Entités sont réparties dans plusieurs modules, j'ai un problème de namespace lorsque je veux faire des relations entre des objets avec annotations de Doctrine.
J'ai par exemple une classe News qui contient un objet User je veux faire une relation avec les annotations et veut donc mettre un targetEntity="User\Model\User" (le namespace de l'entité User), mais j'ai une erreur lorsque je veux vérifier le schéma. Il cherche l'entité User dans le namespace de l'entité News (News\Model\News) j'ai essayé de mettre \User\Model\User mais le problème est le même...
Pour l'alias je voulais juste que se soit plus court à écrire...
Hors ligne
Normalement ça devrait marcher. As-tu bien pensé à indiquer le driver pour tous tes modules ?
Donc par exemple, dans le fichier de config du module User, tu devrais avoir quelque chose comme ça :
'doctrine' => array( 'driver' => array( 'user_driver' => array( 'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver', 'cache' => 'array', 'paths' => array('module/User/src/User/Model') ), 'orm_default' => array( 'drivers' => array( 'User\Model' => 'user_driver' ) ) ), ),
Idem dans le module News :
'doctrine' => array( 'driver' => array( 'news_driver' => array( 'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver', 'cache' => 'array', 'paths' => array('module/News/src/News/Model') ), 'orm_default' => array( 'drivers' => array( 'News\Model' => 'news_driver' ) ) ), ),
(Sinon, ce n'est qu'un détail, mais je te suggère de garder le nommage "officiel", à savoir utiliser "Entity" au lieu de "Model", donc ça donnera User\Entity\Blabla au lieu de User\Model\Blabla.
Hors ligne
Oui j'ai bien fait ça, en utilisant cependant la variable magique __NAMESPACE__ et en déclarant le namespace au début du fichier, comme dans le tuto en fait.
Et pour ce qui est de la notation, j'ai gardé la notation de base de ZF2, même si c'est des Entités, ça reste des classes Modèles, (je doute que ça change grand chose...)
Dernière modification par Birssan (15-12-2012 00:32:49)
Hors ligne
Non non le changement de nom ne changera rien, c'est juste niveau des conventions, comme dans Doctrine ça s'appelle Entité.
Bizarre bizarre ton soucis, car je te confirme que ça marche très bien chez moi. Je comprends pas, j'ai comparé ta config à la mienne elle a l'air correcte !
Hors ligne
Je regarderai lundi vu que c'est un problème que j'ai au bureau, j'ai pas le code chez moi. En espérant que je trouve une solution, je la posterai si je la trouve...
Hors ligne
J'ai finalement trouvé mon problème...
Faute de ma part j'avais une configuration du driver qui était en commentaire pour une de mes entités, tout marche bien à présent !
Merci pour ton aide
Hors ligne
Pages: 1