Consultez la FAQ sur le ZF avant de poster une question
Vous n'êtes pas identifié.
Pages: 1 2
Voici comment on peut configurer les modules d'une appli et les charger via le nouveau loader.
Avant on était obligé d'ajouter tous les paths nécessaires à l'include_path.
Ce n'est plus nécessaire.
// index.php $application = new Zend_Application( APPLICATION_ENV, APPLICATION_PATH.'/config/application.ini' );
;application.ini ... bootstrap.path = APPLICATION_PATH "/Bootstrap.php" bootstrap.class = "Bootstrap" ; chargement des modules resources.modules[] = module1 resources.modules[] = module2 ...
<?php class Bootstrap extends Zend_Application_Bootstrap_Bootstrap { ... protected function _initModules() { $config = new Zend_Config($this->getOptions()); $modules = $config->resources->modules; // On charge chacun des modules configurés $loaders = array(); foreach ($modules->toArray() as $index => $module) { $loaders[$module] = new Zend_Application_Module_Autoloader( array( 'namespace' => ucfirst($module), 'basePath' => APPLICATION_PATH.'/modules/'.$module, ) ); $loaders[$module]->addResourceType('View', 'views/mavue', 'View'); $loaders[$module]->addResourceType('Model', 'models', 'Model'); $loaders[$module]->addResourceType('Form', 'forms', 'Form'); } ... return $loaders; } ... ?>
Par contre, avant on appelait une classe titi située dans le module toto comme cela:
$titi = new titi();
Maintenant, avec les nouveaux namespaces (pour éviter d'avoir 2 classes de même nom dans 2 dossiers différents), on apellera:
$titi = new Toto_Model_Titi(); // si la classe est dans /models
$titi = new Toto_Form_Titi(); // si la classe est dans /forms
Ca fait pas mal de code à changer, mais bon, pas le choix ...
Voila j'espère pouvoir aider, même si cela doit sembler évident à de nombreuses personnes.
Si jamais vous avez d'autres solutions je suis preneur.
Dernière modification par booradley (17-08-2009 02:12:09)
Hors ligne
Sympa l'idée! Merci pour le partage ;-)
Hors ligne
De rien,
J'ai jugé bon de poster ceci car j'avais encore trouvé aucun exemple concret sur internet.
David
Hors ligne
Salut,
En fait il n'est pas vraiment nécessaire d'ajouter tous les modules à l'include_path.
Si chaque module possède un bootstrap, par ex. module "News":
application/ bootstrap.php <--- bootstrap de l'application modules/ News/ controllers/ models/ services/ bootstrap.php <--- boostrap pour le module news
Boostrap du module news:
<?php /** * Module News - Bootstrap */ class News_Bootstrap extends Zend_Application_Module_Bootstrap { protected function _initAutoload() { $autoloader = new Zend_Application_Module_Autoloader(array( 'namespace' => 'News_', 'basePath' => dirname(__FILE__) )); return $autoloader; } }
Zend_Application charge automatiquement le bootstrap des modules au travers de la ressource Zend_Application_Resource_Modules.
L'avantage d'avoir un fichier Bootstrap pour chaque module est de découpler le plus possible les modules de l'application, de conserver un bootstrap "propre" pour l'appli et de laisser chaque module gérer sa propre config. Il peut être également intéressant de récupérer le bootstrap d'un module pour exécuter certaines méthodes propres à ce modules à tout moment.
c.f Doc:
$resource = $bootstrap->getPluginResource('modules'); $moduleBootstraps = $resource->getExecutedBootstraps(); $newsBootstrap = $moduleBootstraps['news'];
Ton code à l'avantage de ne pas avoir à créer de fichier Bootstrap par module. En contre-partie tu perds l'idée de modules indépendants.
Petit détail sinon, ces deux lignes sont inutiles:
$loaders[$module]->addResourceType('Model', 'models', 'Model'); $loaders[$module]->addResourceType('Form', 'forms', 'Form');
Ces deux ressources sont dans les ressources par défaut de Zend_Application_Module_Autoloader.
A+ benjamin.
Hors ligne
Salut,
merci à vous deux, ça m'a bien aidé.
Hors ligne
Bonjour,
Dans l'idée d'un bootstrap unique, il n'y a toutefois pas besoin de déclarer tous les modules dans le fichier de conf, un moyen de les récupérer automatiquement pourrait être :
$this->bootstrap('frontcontroller'); $modules = array_keys( $this->getResource('frontcontroller')->getControllerDirectory() ); // foreach ...
En revanche en ce qui concerne un bootstrap par module, quand on regarde la classe Zend_Application_Resource_Modules il s'avère qu'elle ne semble pas chercher de fichier de bootstrap pour le module déclaré "par défaut".
Cela signifie-t-il que tout traitement que l'on pourrait vouloir placer dans un bootstrap du module par défaut doit être écrit dans celui de l'application ?
Hors ligne
Salut,
Tout dépend de l'arbo que tu décides d'utiliser.
Si ton module par défaut se trouve dans le dossier application, alors ce sera le bootstrap de ton application qui sera celui de ton module par défaut.
Sinon, si tu redéfinis le module par défaut par un module qui se trouve dans le dossiers des modules, il aura un bootstrap comme tous les autres. Tu ne fais qu'indiquer au Front Controller quel est le module à utiliser par défaut.
De base, il s'agit du dossier application.
A+ benjamin.
Hors ligne
Dans le cas où le module par défaut est dans /modules/default/, il faut dès lors faire pointer "bootstrap.path" dans la config vers le bootstrap du module/default, non ?
Car dans la boucle qui parse tous les modules dans Zend_Application_Resource_Modules, le foreach force un continue; dès que le module parsé est celui déclaré par défaut. Cela sous-entends qu'à chaque chargement de l'application, le bootstrap du module par défaut est appelé en premier lieu, et c'est lui qui se charge via le plugin de resources Zend_Application_Resource_Modules de charger les autres bootstraps ?
Hors ligne
Est-ce normal que lors du lancement de l'application, tous les bootstraps soient chargés ?
Je pensais que le bootstrap d'un module donné serait chargé lors du lancement de ce même module ...
Merci pour vos réponses.
Hors ligne
tylerdurd, c'est impossible. Le boostrap est ce qui intervient en premier. Le processus de routage n'a pas encore eut lieu et donc il est impossible de savoir quelle module est appelé.
Pour configurer un module qui sera utilisé, il faut passé par un plugin (c'est fait pour)
Hors ligne
Je ne sais pas si je me suis bien fait comprendre ... et si j'ai suffisamment était précis aussi
Je sais que le bootstrap est ce qui intervient en premier, cependant, dans mon application, j'ai un bootstrap par module (en plus de celui à la racine de 'application'), et je pensais que ces bootstrap là ne seraient pas tous chargés dès le début ... hors après une regard dans le code du ZF, ben tous les bootstraps sont chargés d'entrée ... (ceux situés dans les modules compris, c'est le chargement de ceux là qui m'interrogent)
Du coup, je ne vois plus trop l'utilité de mettre des fichiers de config (par exemple) propre à un module sachant qu'ils seront dans tous les cas chargés à tout moment ...
Hors ligne
L'utilité est la possibilité de le faire C'est tout l'intérêt du ZF.
Tu n'y trouves pt être pas l'utilité dans ton cas personnel (pas encore), mais peut-être que moi ou qqun d'autre y trouve une utilité.
Je suis prêt à parier que le developpeur y trouve une utilité
Par exemple, moi je l'utilise pour initialisé certaines partie de mes menus. J'ai des helpers qui récupères des variables concernant le module courant (je me suis fait un helper getModuleOptions($moduleName = null))
Hors ligne
Ok, merci, toutes mes excuses ... J'avoue avoir pensé dans mon cas ...
Hors ligne
Salut,
@Eureka:
Ce n'est pas le module par défaut qui charge les autres. C'est simplement que s'il s'agit du module par défaut, le bootstrap a logiquement déjà été chargé et donc c'est inutile de repasser dedans. Par contre la boucle continue et charge tous les autres bootstrap des modules.
@tylerdurd:
Tu peux avoir besoin d'accéder à tous tes modules à tout moment dans l'application, c'est donc nécessaire d'initialiser les modules au préalable et donc de systématiquement charger les bootstrap.
A+ benjamin.
Hors ligne
Delprog,
Je vais suivre ton conseil de créer un bootstrap par module.
En effet la doc indique:
$resource = $bootstrap->getPluginResource('modules'); $moduleBootstraps = $resource->getExecutedBootstraps(); $newsBootstrap = $moduleBootstraps['news'];
Mais $bootstrap n'est pas défini dans mon boostrap.
J'ai bien essayé :
$resource = $this->getPluginResource('modules'); ou $resource = $this->bootstrap->getPluginResource('modules');
Mais j'arrive pas a trouver a quel classe appartient cet méthode getPluginResource().
Est ce que c'est lié au getOptions() qui permet de récupérer les infos de application.ini?
Hors ligne
Salut,
$bootstrap = Zend_Controller_Front::getInstance()->getParam('bootstrap');
Tu peux ainsi accéder à toutes les ressources n'importe où.
Edit : sekaijin a mis à disposition des diagrammes bien pratiques, n'hésitez pas à vous en servir. Entre autre:
http://www.z-f.fr/forum/viewtopic.php?id=3608
A+ benjamin.
Dernière modification par Delprog (19-08-2009 14:19:55)
Hors ligne
hello,
Delprog a écrit:
@Eureka:
Ce n'est pas le module par défaut qui charge les autres. C'est simplement que s'il s'agit du module par défaut, le bootstrap a logiquement déjà été chargé et donc c'est inutile de repasser dedans. Par contre la boucle continue et charge tous les autres bootstrap des modules.
Quand je parlais de "module par défaut qui charge les autres" je sous-entendais que c'est le bootstrap du module par défaut qui déclenche le plugin de ressource Z_A_Resource_Modules qui charge les autres bootstraps.
Merci pour ta réponse, ça répond à mon questionnement.
Hors ligne
Delprog,
j'ai ajouté cette ligne dans mon bootstrap par défaut:
$bootstrap = Zend_Controller_Front::getInstance()->getParam('bootstrap');
Ca fait carrément crasher Apache.
De plus je comprends pas comment ca fonctionne.
Tout ce que je veux c'est qu'a partir de mon bootstrap par défault, les bootsraps de mes autres modules soient appelés
protected function _initAutoload() { $config = new Zend_Config($this->getOptions()); $modules = $config->resources->modules; // On charge chacun des modules configurés $loaders = array(); foreach ($modules->toArray() as $index => $module) { $bootstrap = Zend_Controller_Front::getInstance()->getParam('bootstrap'); $resource = $bootstrap->getPluginResource('modules'); $bootstrap = $moduleBootstraps[$module]; /* $loaders[$module] = new Zend_Application_Module_Autoloader( array( 'namespace' => ucfirst($module), //.'_' 'basePath' => APPLICATION_PATH.'/modules/'.$module, ) ); $loaders[$module]->addResourceType('View', 'views/exotica', 'View'); $loaders[$module]->addResourceType('Helper', 'helpers', 'Helper'); */ } ... return $loaders; }
Quelqu'un peut-il me dire ce qui cloche?
Hors ligne
Il me semble qu'ils sont chargés automatiquement, tu n'as pas besoin de ta boucle foreach.
Fais bien hériter les Bootstraps (situés dans les modules) de la classe Zend_Application_Module_Bootstrap
Il faut également que le nom de classe de ton Bootstrap soit de la forme "NomModule_Bootstrap"
Hors ligne
A priori je dirais :
Soit ajouter dans le fichier de configuration la ligne
resources.modules = ''
qui se chargera d'appeler le plugin de ressource Zend_Application_Resouce_Modules qui instanciera les boostraps de chaque module.
Soit dans ton bootstrap par défaut de faire
$this->bootstrap('modules'); // pour instancier la ressource (et les bootstraps de chaque module) $bootstraps = $this->getResource('modules') // au besoin récupére le tableau des bootstrap nés de l'instanciation
Il me semble que les boostraps de modules embarque à leur création une instance de Zend_Application_Module_Autoloader (probablement initialisé avec des chemins par défaut). Du coup il doit être possible de le modifier soit dans ton bootstrap principal en récupérant les bootstraps comme ci-dessus, soit dans les bootsraps eux-même.
Hors ligne
Si je définis moi même dans mon application.ini les modules à charger c'est que je n'utilise que 15 modules sur 30.
En effet j'ai plusieurs applications qui tournent et chacun utilise l'un ou l'autre des modules disponibles.
C'est la raison pour laquelle j'utilise un foreach.
;application.ini resources.modules[] = module24 resources.modules[] = module745 resources.modules[] = module16
En tout cas ca crashe plus,
mes bootstrap de modules étendaient Zend_Application_Bootstrap_Bootstrap et non Zend_Application_Module_Bootstrap.
Par contre si j'ajoute un bootstrap au module 99 (alors que celui ci n'est pas chargé via mon application.ini, il est quand même appelé!
Pas cool!!!
Dernière modification par booradley (19-08-2009 17:06:04)
Hors ligne
Je ne sais pas si l'idée est bonne, mais dans application.ini, tu pourrais (s'il n'y a pas d'effet de bord) :
Ne pas mettre cette ligne (si elle est présente) :
resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
car elle définit le chemin des modules et ZF considères donc chaque sous-dossier comme un module à utiliser.
Mais plutôt utiliser :
resources.frontController.controllerDirectory.<ModuleName> = APPLICATION_PATH "/modules/<ModuleName>/controllers" // mettre les 15 à utiliser
qui ici va forcer le plugin de ressource Z_A_R_Modules à ne considérer comme modules que ceux spécifiés dans la config
Dernière modification par Eureka (19-08-2009 17:21:04)
Hors ligne
Oui c'est une idée mais bon je trouve pas ca tres optimal.
Je pense donc qu'il serait bon dans mon cas d'appeler mes bootstrap explicitement dans mon code et de désactiver l'appel automatique de Zend.
Une idée sur le sujet?
Hors ligne
salut,
Pour que ZF ne charge pas les bootstraps il suffit ne pas charger la ressource Zend_Application_Resource_Modules car c'est elle qui les charge tous dès lors que resources.frontController.moduleDirectory est renseigné en config.
Du coup pour les charger manuellement je pense qu'il faut prendre exemple sur la méthode _init() de la ressource, à priori il suffirait de la copier/coller dans ta méthode d'initialisation à toi, et de faire en sorte que la boucle parsant les modules se base sur ta liste de modules et non sur la liste des modules trouvé dans les répertoires.
// Z_A_Resource_Modules utilise globalement : array_keys($front->getControllerDirectory()); // et toi tu l'adaptes à ton besoin, via $config->resources->modules;
Dernière modification par Eureka (21-08-2009 10:12:03)
Hors ligne
Oui je vois bien mais il faudrait court-circuiter l'appel à Z_A_Resource_Modules.
Et là je vois pas comment faire.
Hors ligne
Pages: 1 2