Consultez la FAQ sur le ZF avant de poster une question
Vous n'êtes pas identifié.
Salut a tous,
J'ai besoin d'utiliser le service manager pour accéder a des services a partir des modeles de table. Il y a une methode qui est tres repandu sur le net y compris le manuel de ZF2 mais bizzarement la methode ne marche pas.
Pour etre plus concret, j'ai un mode ArticleTable et un deuxieme modele CategoriesTable. A partir de ArticleTable, je veut acceder a CategoriesTable pour exploiter certaines de ses methodes.
Sur le net, la methode qui est preconisee est la suivante:
1) Referencer CategoriesTable dans Module.php ou dans Module.config.php. Pour mon cas, j'ai utiliser le referencement dans le fichier Module.php. En voici le code:
--------Extrait du Code Module.php -------------
public function getServiceConfig() {
return array(
// Le service CategoriesTable
'Site\Model\CategoriesTable' => function($sm) {
$tableGateway = $sm->get('CategoriesTableGateway');
$table = new Model\CategoriesTable($tableGateway);
return $table;
},
'CategoriesTableGateway'=>function ($sm) {
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Categories());
return new TableGateway('categories', $dbAdapter, null, $resultSetPrototype);
},
[. . .]
2) Par la suite on demande que ArticleTable implemente l'interface ServiceLocatorAwareInterface. C'est ce que j'ai fait. En voici un extrait du code.
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\Db\TableGateway\TableGateway;
/**
* Description of Article
*
* @author kouame
*/
class ArticleTable implements ServiceLocatorAwareInterface{
// Table name in database
protected $table ='Article';
// Le service manager
protected $sm;
public function __construct(TableGateway $tableGateway)
{
$this->tableGateway = $tableGateway;
}
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
$this->sm = $serviceLocator;
}
public function getServiceLocator()
{
return $this->sm;
}
3) Par la suite, on me dit que je peut ainsi acceder a CategoriesTable a partir de ArticleTable en saisiant simplement ce code dans n'importe quel methode de ArticleTable:
$this->art=$This->getServiceLocator()->get('Site\Model\CategoriesTable');
Le problème est que quand j’exécute ce code, on me met le message d'erreur suivant:
Fatal error: Call to a member function get() on a non-object ...
Quelqu'un aurait une solution a ce probleme et surtout comment la generaliser (comment acceder a un service a partir de n'importe ou dans le code)?
Hors ligne
Salut, comment récupères tu une instance de ArticleTable ?
Hors ligne
Hello
tu devrais peut être passer par une factorie.
ah oui, je sais pas si c'est le copier collé, mais tu a un $This, on sait jamais
Hors ligne
Non ça vient pas du $This l'erreur est sur le get
Hors ligne
Arf dommage ^^
(we je sais y avais peu de chance mais au moins c'est propre X_X)
Il aurait pas plus de chance avec ça?
[lang=php] public function getServiceConfig() { return array( 'factories' => array( // Le service CategoriesTable 'Site\Model\CategoriesTable' => function($sm) { $tableGateway = $sm->get('CategoriesTableGateway'); $table = new Model\CategoriesTable($tableGateway); return $table; }, 'CategoriesTableGateway'=>function ($sm) { $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter'); $resultSetPrototype = new ResultSet(); $resultSetPrototype->setArrayObjectPrototype(new Categories()); return new TableGateway('categories', $dbAdapter, null, $resultSetPrototype); }, ...
Hors ligne
Si mais le problème ne vient probablement pas de là.
Hors ligne
Salut a tous, merci de vos questions. particulierement pour la question d'orkin, je veut simplement dire que jusqu'a present, je n'ai eu besoin de Modeles qu'a partir des Controllers. Hors le controleur implemente deja une interface qui rend disponible le serviceManager.
Donc a partir du controleur, pour avoir acces a ArticlaTable, je fais le code suivant:
$this->art=$This->getServiceLocator()->get('Site\Model\ArticleTable');
Quand je fait ce code ailleurs que dans le controleur j'obtiens le message
Fatal error: Call to a member function get() on a non-object ...
Hors, au fur et a mesure que j'avance dans mon projet, ce probleme se generalise: J'ai besoin de certains services (notamment l'adapter, les modeles, ...) hors du controleur.
Hors ligne
Bonsoir,
C'est une mauvaise pratique d'appeler le serviceLocator dans le controller et ce sera enlevé dans la v3. Libre a toi de faire ce que tu veux toutefois a ce niveau là mais si ton application appelle le serviceLocator dans le controller ton controller assure une partie de la couche service et ce n'est son but ni ce pourquoi il existe. Dans le cadre d'une application maintenable dans le temps et évolutive et a plus forte raison si tu n'est pas seul a maintenir le projet il y a tout intérêt à créer une couche service.
Pour ton problème de "get on a non object" je te renvoie a mon ancien post sur ce forum http://www.z-f.fr/forum/viewtopic.php?id=9032
Tu risques d'apprendre beaucoup
Et si tu veux plus d'infos ou d'exemple de code je te renvoie ici :
https://github.com/jonathangreco/zf2-doctrine-tutorial
en espérant t'avoir aidé à comprendre plus a fond à partir de mes propres problèmes passés.
Dernière modification par JGreco (27-05-2014 21:37:52)
Hors ligne
Salut, que ça plante ailleurs c'est normal pour que l'interface ServiceLocatorAwareInterface ai un sens il faut que la classe qui l'implémente soit instanciée par le service manager (ou locator c'est la même chose). Ce qu'il se passe c'est que lorsque le service manager va instancier un nouvel objet il va faire bêtement un $class = new Class(). Mais ensuite il va faire un test supplémentaire : if ($class instanceof ServiceLocatorAwareInterface) { $class->setServiceLocator($serviceLocator) }.
Donc les contrôleurs le service locator est automatiquement injecté. Il sera probablement retiré dans le ZF3 (ça a été proposé) car il était mal utilisé et trop peu de développeurs utilisaient les fabriques.
Pour ton soucis j'ai répondu un peu trop vite ce matin, ça vient probablement du $This normalement c'est $this. Le message dit que tu appelles la fonction get sur quelque chose qui n'est pas un objet, ce quelque chose c'est getServiceLocator() et il ne peut pas être null dans un contrôleur.
Ensuite pour utiliser le service locator ailleurs que dans un contrôleur il suffit d'implémenter l'interface ServiceLocatorAwareInterface et d'utiliser le trait ServiceLocatorAwareTrait et tout se fait tout seul. La seule chose que tu dois faire c'est appeler tes services via le service locator
Hors ligne