A plugin by the name “getServiceLocator” was not f

2019-07-25 07:05发布

Recently started learning AngularJS and Zend Framework 2 through a course. Given the year of the course, which if I remember is 2013, some things have changed in both frameworks. Soon, I came across a problem using the following code snippet to test the connection to the database and list the records using Doctrine 2:

namespace Application\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;

class IndexController extends AbstractActionController {
    public function indexAction() {
        $em = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
        $repo = $em->getRepository('Entity\Categoria');

        $categorias = $repo->findAll();

        return new ViewModel(['categories'=>$categorias]);
    }
}

When I run, it returns the following error::

A plugin by the name "getServiceLocator" was not found in the plugin manager Zend\Mvc\Controller\PluginManager

Furthermore, an additional information:

Zend\ServiceManager\Exception\ServiceNotFoundException

File:

C:\xampp\htdocs\Curso de ZF2\vendor\zendframework\zend-servicemanager\src\AbstractPluginManager.php:133

As far as I know, the problem stems from the fact that the getServiceLocator() had been removed from the latest version of Zend Framework 2. However, I have no idea how to solve this so that I can continue testing . Someone can help me?

1条回答
叛逆
2楼-- · 2019-07-25 08:04

If you have updated or checked out Zend Framework 3 from composer, and if it's just for making your course material work, you could downgrade to an earlier (2.x) version, where getServiceLocator() is available, yet deprecated. It was removed from 3.0 onwards.

A better approach would be to understand how to work around it, since you will have to do it in the future, anyway. Basically, you shouldn't inject dependencies in the middle of runtime, but actually register a factory for your controller and then pass dependencies in through a constructor. Possible fixes are explained well in the accepted answer for the following question:

PHP Deprecated: You are retrieving the service locator from within the class ZFTool\Controller\ModuleController

In the example above, $db = $this->getServiceLocator()->get('Db\ApplicationAdapter'); is passed as a constructor argument, so it will be immediately available to the Controller. So in a similar fashion, you should create a Factory for your IndexController, which should return it with Doctrine\ORM\EntityManager already injected through a constructor (remember to replace "yourModule" with your real module name):

namespace yourModule\Controller\Factory;

use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
use yourModule\Controller\IndexController;

class IndexControllerFactory implements FactoryInterface {
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null) {
        return new IndexController($container->get('Doctrine\ORM\EntityManager'));
    }
}

You could place your Factory class anywhere, as long as everything is configured accordingly. In this example, I've put it in /Module/yourModule/src/yourModule/Controller/Factory/IndexControllerFactory.php.

With the class above being called, your $em variable would then be populated and could be called from anywhere in the controller (note the new property $em and its usage: $this->em):

class IndexController extends AbstractActionController {

    protected $em;

    public function __construct(EntityManager $em) {
        $this->em = $em;
    }

    public function indexAction() {
        $repo = $this->em->getRepository('Entity\Categoria');
        $categorias = $repo->findAll();
        return new ViewModel(['categories'=>$categorias]);
    }

    ...

}

Now, register you new factory in yourModule's module.config.php and we're done:

<?php
return [
    // ... other stuff
    // ...
    'controllers' => [
        'factories' => [  
            'yourModule\Controller\Index' => 'yourModule\Controller\Factory\IndexControllerFactory',
            ],
    ],
    // etc...
]; 
// end of file

Very important: your file will probably have similar contents, but using "invokes" as array key. Notice that you will use factories as key name (because you are declaring a controller factory), instead of "invokes", which is for classes without dependencies or regular controllers.

I also recommend studying this Migration guide for Zend Framework 3, it has a lot of important information that might help.

As for that course you are following, again, I suggest you downgrade PHP to a compatible version (very easy if you're using composer), or try to find another up-to-date course or tutorial on the web. ZF2 changed significantly between versions and chances are this is not the only error you will find and you'll get very confused instead of learning. Let me know if this works for you.

查看更多
登录 后发表回答