Как получить экземпляр диспетчера служб в контроллере в Zend Framework 3?

Я пытаюсь заставить экземпляр ServiceManager в моем контроллере использовать фабрику для Db\Adapter.

Я добавил в module/Application/config/module.config.php:

'service_manager' => [
    'factories' => [
        Adapter::class => AdapterServiceFactory::class,
    ],
],

В config / autoload / local.php я добавил следующие строки:

'db' => [
    'driver' => 'Mysqli',
    'database' => 'mydb',
    'username' => 'myuser',
    'password' => 'mypassword',
]

Теперь я хочу получить доступ к ServiceManager в моем модуле /Application/src/Controller/IndexController.php. Как я могу это сделать?

Я старался $sm = $this->getPluginManager(); безуспешно. Если я бегу $serviceManager->get(Adapter::class) с PluginManager это дает мне ошибку:

Too few arguments to function Zend\Db\Adapter\Adapter::__construct(), 0 passed in (...)\vendor\zendframework\zend-servicemanager\src\Factory\InvokableFactory.php on line 30 and at least 1 expected

Что я могу сделать, чтобы получить ServiceManager, который получит мой объект Adapter?


Я изменил фабрику контроллеров с

'controllers' => [
    'factories' => [
        Controller\IndexController::class => InvokableFactory::class,
    ],
],

в

'controllers' => [
    'factories' => [
        Controller\IndexController::class => function(ContainerInterface $serviceManager) {
            return new Controller\IndexController($serviceManager);
        },
    ],
],

Я также добавил метод getServiceConfig() в module.config.php и добавил конструктор в IndexController, который получает ServiceManager. Теперь у меня есть доступ внутри контроллера.

Но мой вопрос сейчас: есть ли более приятный, более "зендоподобный" способ добиться этого?

2 ответа

Решение

Благодаря замечательным связанным темам SO я наконец нашел ответ. ServiceManager в ZF3

Кажется, это делается с помощью фабрики контроллеров, почти как я.

У меня есть опыт работы с ZF1, и теперь я изучаю ZF3, я хотел сделать простую вещь: установить конфигурацию DB в файле конфигурации, а затем получить адаптер db на контроллере. Мне потребовалось некоторое время, чтобы понять это, поскольку в официальных документах есть миллионы вариантов различных настроек. Поэтому я публикую свой ответ, чтобы помочь всем, кто ищет.

1- Добавить учетные данные БД в config/autoload/global.php или же config/autoload/local.php, как это:

<?php
return [
    'db' => [
        'driver' => 'Pdo_Mysql',// can be "Mysqli" or "Pdo_Mysql" or other, refer to this link for the full list: https://docs.zendframework.com/zend-db/adapter/
        'hostname' => 'localhost',// optional
        'database' => 'my_test_db',
        'username' => 'root',
        'password' => 'root',
    ],
];

2- В module/YOUR_MODULE_NAME/config/module.config.php, добавьте это в разделе фабрики контроллеров:

return [
    //...
    'controllers' => [
        'factories' => [
            //...
            // Add these lines
            Controller\MycontrollernameController::class => function($container) {// $container is actually the service manager
                return new Controller\MycontrollernameController(
                    $container->get(\Zend\Db\Adapter\Adapter::class)
                );// this will pass the db adapter to the controller's constructor
            },
            //...
        ]
    ]
    //...
];

3- Наконец, в вашем контроллере module/YOUR_MODULE_NAME/src/Controller/MycontrollernameController, вы можете получить и использовать адаптер БД:

<?php
namespace Application\Controller;

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

use Zend\Db\Adapter\Adapter;

class MycontrollernameController extends AbstractActionController
{

    private $db;

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

    public function indexAction()
    {
        $result = $this->db->query('SELECT * FROM `my_table`', Adapter::QUERY_MODE_EXECUTE);
        echo $result->count();// output total result
        return new ViewModel();
    }
}

Есть другой способ добиться того же, создав фабрику для вашего контроллера, и внутри этой фабрики передайте адаптер db контроллеру. Я думаю, что для начинающих, которые пробуют ZF3 на мировом уровне, это слишком.

Другие вопросы по тегам