Consultez la FAQ sur le ZF avant de poster une question
Vous n'êtes pas identifié.
Bonjour à tous,
Voilà dans mon intranet j'ai plusieurs fichiers JS qui sont appelés, et ce suivant les actions.
Par souci de performance, et comme je fais bien les choses , mes JS sont appelés juste avant la fermeture de mon body ...
Sauf que si par exemple, j'ai un footer qui lui est commun, ça remet en cause pas mal de choses.
Sans compter en plus que mon code html se retrouve fragmenté entre mon layout et mes vues et c'est moche car j'ai des balises qui s'ouvrent dans mon layout pour se fermer dans ma vue.
J'ai pensé à l'alternative de mettre mes appels js en les injectant dans mon controller ... et du coup je n'ai plus qu'à mettre un echo $this->inlineScript dans mon layout et le tour est joué. Le souci c'est que ça fait des patés d'appel dans mes controlleurs, de plus je dois appeler $this->getServiceLocator()->get('viewhelpermanager')->get($helperName); et les appels au basepath. Le controlleur n'est pas fait pour ça et j'ai peur que ça alourdisse les perfs.
Qu'en pensez-vous ? avez-vous eu à gérer ce genre de problématique ? quelles solutions avez-vous envisagées ?
Danke schön
Dernière modification par amelie (22-07-2015 11:52:41)
Hors ligne
Hello, déjà un truc à bannir c'est d'utiliser le ServiceLocator dans les contrôleurs. A partir du moment où tu t'en sers c'est qu'il y a un problème de conception.
Donc je te suggères d'utiliser des aides de vues avec des paramètres et dans ton aide de vue en fonction du paramètre tu injectes ton fichier JS. Dans le cas où c'est dans ton layout ou ton footer générique c'est un peu galère. Donc tu peux peut être jouer avec une variable globale dans le layout que tu définies dans tous tes contrôleurs mais c'est vrai que c'est un peu lourd.
Tu peux aussi passer par un listener qui va injecter ce dont tu as besoin au moment du rendu en fonction de la page.
Hors ligne
Hello, déjà un truc à bannir c'est d'utiliser le ServiceLocator dans les contrôleurs. A partir du moment où tu t'en sers c'est qu'il y a un problème de conception.
>> Comment ça ? On en a bien besoin pour appeler les BDD par exemple, à travers TableGateway (cf. le tuto ZF2) ... on est bien obligé d'appeler ServiceLocator pour demander les services ...
Là je suis perdue par ta remarque ....
Dernière modification par amelie (09-07-2015 14:18:50)
Hors ligne
http://framework.zend.com/manual/curren … odels.html
Rubrique "Back to the controller" :
[lang=php] // module/Album/src/Album/Controller/AlbumController.php: public function getAlbumTable() { if (!$this->albumTable) { $sm = $this->getServiceLocator(); $this->albumTable = $sm->get('Album\Model\AlbumTable'); } return $this->albumTable; }
J'ai bien lu ?
Hors ligne
Salut
En fait tu as bien lu, et je donnerai des baffes aux mecs qui font des tutos en foutant tout dans les controleurs, et appelant le service locator dedans.
Mais rapporte toi a ce lien :
https://github.com/zendframework/zf2/issues/5168
Le service locator à été enlevé des controleur pour la v3, considéré comme une mauvaise pratique, cela le fait déborder de son role de controleur.
Hors ligne
Hallucinant !!!!!!
J'ai appris à programmer avec ZF2 en suivant ce tutoriel, donc ça fait des années que je programme avec les SL dans mes controleurs !!!!
JE fais COMMENT pour appeler mes BDD en l’occurrence !!!!!!
Dernière modification par amelie (09-07-2015 14:41:29)
Hors ligne
Tu dois avoir une couche modèle, qui se connecte a ta base de donnée, c'est ici que tes appels au service locator peuvent etre fait donc potentiellement toute tes couches modèles(services) doivent donc étendre serviceLocatorAwareInterface (avec le trait correspondant serviceLocatorAwareTrait).
Et bien sur tes controleur peuvent avoir une injection de dépendance aux services correspondant, et tu isole donc bien correctement ta couche modèle de tes contrôleurs.
Tu peux aussi regarder comment est construit l'architecture d'un blog MVC version ZF2 (review par Orkin)
https://github.com/Grafikart/BlogMVC/tr … Framework2
De ce projet tu pourras voir comment s'organise les factory de controleur avec les dependances de services et comment l'accès aux données s'opère.
De manière générale, tu peux aussi te dire que Thick controller = bad architecture.
Hors ligne
De ce projet tu pourras voir comment s'organise les factory de controleur avec les dependances de services et comment l'accès aux données s'opère.
Oui j'en ai fait.
Mais en utilisant TableGateway, il y a moyen où faut tout que je recommence ?
Hors ligne
Je n'ai jamais utilisé TableGateway je suis passé directement sur Doctrine dès mon apprentissage de ZF2.
Mais tu peux utiliser TableGateway depuis les services, de la même manière que tu y accèdes de tes contrôleurs, je ne vois pas de problème la dedans. Après si quelqu'un qui s'y connait mieux que moi peut infirmer cela, j'aurais appris un truc. Mais sinon je pense que tes TableGateway ont tout a faire dans les services.
Hors ligne
Pas que a chaque fois que j'ai eu regardé un tuto ZF2 pour "aller vite" ils mettent tous dans les contrôleurs... c'est franchement un manque de rigueur mais bon..
Hors ligne
Pour leur défense si je peux me permettre, la plupart de ces tutos datent en fait de 2011 et n'ont pas forcément été remis à jour correctement... On peut d'ailleurs proposer des évolutions, si besoin je me ferais un plaisir de faire la traduction en anglais.
Comme pour les patterns utilisés en ZF1 (registry), ZF2 proposait le service locator dans les contrôleurs, ce qui se trouve être une mauvaise idée finalement mais en était une bonne à l'époque... Le fait que cette injection existe toujours et ne sera supprimée que pour la V3 est uniquement dû à la limite que s'impose l'équipe en terme de SemVer : pas de compatibility break dans une version mineur !
Hors ligne
Moi aussi je suis tombé dans le panneau avec ce tutoriel Sinon, dans la suite de celui-ci, il y a le développement d'un autre module, qui cette fois semble utiliser les bonnes pratiques (corrigez-moi si je me trompe).
Hors ligne
amelie a écrit:
De ce projet tu pourras voir comment s'organise les factory de controleur avec les dependances de services et comment l'accès aux données s'opère.
Oui j'en ai fait.
Mais en utilisant TableGateway, il y a moyen où faut tout que je recommence ?
Non c'est exactement pareil j'avais fait un article sur ce forum mais il date un peu en gros si tu veux faire un truc propre ça se passe comme ça :
DAO > Service > Contrôleur
Pour faire simple chaque couche est spécialisée dans sa tâche. La couche DAO s'occupe de récupérer les données (et éventuellement des les formater mais ça peut aussi être le boulot de la couche service), la couche service va s'occuper de tous ce qui est traitement métier (algo, traiter les données etc ...), le contrôleur va se charger de rassembler les donner pour les transmettre à la vue. Là où c'est un important c'est que la couche DAO n'a pas connaissance de la couche service alors que la couche service oui. Même chose la couche service n'a pas connaissance du contrôleur mais le contrôleur oui. Etc ...
Donc dans ton cas tu vas injecter un ou plusieurs services dans ton contrôleur (suivant tes besoins), dans tes services tu peux injecter d'autres services (ça c'est pas gênant) puisque tu peux avoir un service User et un service Rôle et enfin dans ton service tu vas injecter un ou plusieurs TableGateway. Donc au lieu d'utiliser le Service Locator dans le contrôleur pour utiliser tes TableGateway tu vas le faire dans le service (en faisant une factory) et tu feras une fabrique pour ton contrôleur pour y injecter ton/tes service(s).
Alors tu vas me dire "oui mais ça me fait créer plein de classes pour faire la même chose". C'est vrai le code est beaucoup plus découpé mais il est réutilisable. C'est à dire qu'à l'heure actuelle tes traitements sur les données tu les fais dans ton contrôleur donc si t'en a besoin ailleurs tu dois faire du copier coller. Si tu fais juste un "select * from table where id = $id;" effectivement la couche service ne fait que "proxy" entre le contrôleur et la couche DAO. Par contre si tu fais des traitements tu modifies à un seul endroit et c'est mis à jour partout. C'est ça l'avantage en plus d'avoir une classe pour chaque fonction.
amelie a écrit:
Merci.
J'aurais appris quelque chose.
Mais là j'ai la haine contre les mecs du site de ZF2 qui ont validé un tuto de m... , si je comprends bien.
Oui et non il aurait du être écrit que la pratique est mauvaise et que l'exemple ne reprend pas un modèle d'une belle architecture pour aller plus vite. Sinon quand tu lis le tuto faut te farcir la couche DAO, puis service, puis contrôleur, puis les fabriques etc ... Juste pour faire un hello world (j'exagère un peu mais c'est l'idée).
Seryus a écrit:
Moi aussi je suis tombé dans le panneau avec ce tutoriel
Sinon, dans la suite de celui-ci, il y a le développement d'un autre module, qui cette fois semble utiliser les bonnes pratiques (corrigez-moi si je me trompe).
Oui il y a une interface en plus pour la couche service mais ça semble respecter les bonnes pratiques. C'est même plutôt propre je n'avais pas vu ce tuto. Il devrait être mis en avant !
Hors ligne
Hello,
Pour reprendre le principe d'Orkin mais de manière plus générale que le ZF2, tu peu regarder du coté du concept DDD (Domain Driven Design)
C'est une méthode générale pour réaliser une architecture propre de tes applications.
Pour ce qui est du temps de chargement de la méthode d'Orkin, cela ne devrait pas être significatif.
Tout dépend ce que tu entends par pas mal mais si ta page mets 2 fois plus de temps à arriver ce n'est pas normal.
Hors ligne
amelie a écrit:
Du coup mon temps de chargement augmente pas mal, c'est normal ?
Non c'est vraiment minime les temps de réponses liés à ça. C'est quelques classes c'est rien sachant que c'est réutilisé partout via l'injection de dépendance donc au lieu d'avoir 15 briques du même code tu récupères toujours la même instance (sauf si tu demandes explicitement le contraire). Donc sur cet aspect tu peux avoir même un gain de performance sur une grosse application.
Hors ligne
Hola todos,
Une petite question : est-il préconisé d'utiliser des interfaces ?
J'm'e tâte ... ça n’encombrait-il pas le code ou c'est une vraie garantie de sécurité ?
Hors ligne
Disons que le fait de coder contre des interfaces au lieu de coder contre des implementations te permet de changer les implementations au besoin. Honnêtement, je n'en utilise pas partout mais je pense que ça te contraint à avoir un code plus propre et plus testable.
Pour des petits projets ou des projets qui n'évoluerons jamais, ce n'est clairement pas nécessaire, pour les autres, c'est mieux en effet.
Hors ligne
Bonjour à tous,
Orkin, je reviens vite fait sur ton premier message :
Orkin a écrit:
Donc je te suggères d'utiliser des aides de vues avec des paramètres et dans ton aide de vue en fonction du paramètre tu injectes ton fichier JS. Dans le cas où c'est dans ton layout ou ton footer générique c'est un peu galère. Donc tu peux peut être jouer avec une variable globale dans le layout que tu définies dans tous tes contrôleurs mais c'est vrai que c'est un peu lourd.
Tu peux aussi passer par un listener qui va injecter ce dont tu as besoin au moment du rendu en fonction de la page.
J'ai développé une solution similaire donc à ce que tu préconises. Un listener envoie à mon view helper le nom de mon contrôler et de mon action et en fonction de ces éléments il render le bon fichier phtml. Mais j'ai un souci : la modularité. Comment puis-je organiser ça de la façon la plus adéquate, module par module ? Car en effet passer par un view helper directement dans le layout m'oblige à mettre les éléments dans mon "module central" mais il perd de sa généricité.
En fait je pense avoir mal compris ta proposition , peux-tu juste la développer, stp
. Merci ^^.
Dernière modification par amelie (20-07-2015 17:00:06)
Hors ligne
Faudrait que tu développes un peu plus ton besoin en fait .
Hors ligne
Bon en fait je tourne en rond
J'ai mis un appel à un listener dans mon onDispatch (les variables ont toutes été implémentées auparavant donc no soucy) :
[lang=php] $sharedEvent = new SharedEventManager(); $sharedEvent->attach('Foo', 'bar', function($e) { $event = $e->getName(); $target = get_class($e->getTarget()); $params = json_encode($e->getParams()); printf( '%s called on %s, using params %s', $event, $target, $params ); }); $foo = new Foo(); $foo->getEventManager()->setSharedManager($sharedEvent); $foo->bar($myAction, $myController, $basePath, $module);
(premier souci avec le code ci-dessus : je ne vois pas le retour de mon printf )
Pour le moment voici ma class Foo :
[lang=php] class Foo implements EventManagerAwareInterface { protected $events; public function setEventManager(EventManagerInterface $events) { $this->events = $events; return $this; } public function getEventManager() { if (!$this->events) { $this->setEventManager(new EventManager(__CLASS__)); } return $this->events; } public function bar($action, $controller, $basepath, $module) { $params = compact('action', 'controller', 'basepath', 'module'); $this->getEventManager()->trigger(__FUNCTION__, $this, $params); } }
En fait je voudrais que mon listener puisse récupérer mes éléments pour pouvoir appeler un viewhelper qui serait dans chaque module et qui injecterait à inlinescript les javascripts nécessaires, car ils varient selon l'action et le controller. Mais comme je n'ai jamais fait de listener ... ben je pédale un peu dans la choucroute. C'est tout simple en fait car mes js changent tout le temps dans mon site et j'ai pas envie pour des soucis de propreté de les mettre dans la vue (car ça casserait la propreté du code html toussa).
You see what i mean ? Danke Shön ^^
Dernière modification par amelie (21-07-2015 10:57:17)
Hors ligne
Hum, petite mise à jour.
Je pense m'être un peu compliqué la vie.
Du coup dans mon onDispatch j'envoie selon le nom du module le nom d'un service qui va ensuite injecter ce qu'il faut à inlinescript, donc plus de listener à part, ni de view helper. Et là je vois plus clair
Hors ligne
Résolu.
Dans Module.php j'écoute ce qu'il s'y passe puis j'envoie selon là où je me trouve certaines infos vers un service qui va gentiment injecter mes fichiers vers inlineScript ...
Hors ligne