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

Я хотел бы создать свой собственный ресурс в приложении Sylius, как описано здесь. После многих ловушек и ошибок, как описано выше, я посмотрел также некоторые плагины Sylius и нашел этот, где все работает нормально.

Однако следование Документам и подобным примерам в моих случаях не сработает.

Я определил ресурс так:

resources.yml:

    app.custody:
        driver: doctrine/orm
        classes:
            model: AppBundle\Entity\CustodyWallet
            form: AppBundle\Form\Type\CustodyType
            controller: AppBundle\Controller\Shop\CustodyController

routing.yml:

account_token_custody:
    path: /account/custody
    methods: [GET, POST]
    defaults:
        _controller: app.controller.custody:custodyAction
        _sylius:
            template: "@AppBundle/custody.html.twig"
            redirect: sylius_shop_account_dashboard

CustodyController выглядит так:

use AppBundle\Entity\CustodyWallet;
use AppBundle\Form\Type\CustodyType;
use Sylius\Bundle\ResourceBundle\Controller\ResourceController;
use Symfony\Component\Form\Form;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class CustodyController extends ResourceController
{
    public function custodyAction(Request $request): Response
    {
        // .... code .....
    }
}

Однако это приводит к следующей ошибке:

Не удается выполнить автоматическое подключение службы "AppBundle\Controller\Shop\CustodyController": аргумент "$metadata" метода "Sylius\Bundle\ResourceBundle\Controller\ResourceController::__construct()" ссылается на интерфейс "Sylius\Component\Resource\Metadata\MetadataInterface", но такой услуги не существует. Вы создали класс, реализующий этот интерфейс?

Поиск этой ошибки привел меня к этой проблеме GitHub, где люди рекомендуют установить autowire на false для этого конкретного контроллера. Так я и сделал:

services.yml:

AppBundle\Controller\Shop\CustodyController:
    autowire: false
    public: true

Но так конструктор вызывается без аргументов:

Слишком мало аргументов для функции Sylius\Bundle\ResourceBundle\Controller\ResourceController::__construct(), 0 передано в /var/www/var/cache/dev/Container1MQRWcB/getCustodyControllerService.php в строке 16 и ожидается ровно 17

Мне любопытно, почему аналогичная конфигурация работает в CmsPlugin, о котором я упоминал выше, но не в моем случае.

Как я могу этого добиться?

1 ответ

Решение

На основе этой конфигурации

sylius_resource:
    resources:
        app.custody:
            driver: doctrine/orm
            classes:
                model: AppBundle\Entity\CustodyWallet
                controller: AppBundle\Controller\Shop\CustodyController

Sylius сгенерирует несколько сервисов, включая контроллер ресурсов, в соответствии с документацией пакета ресурсов.

Просто определите класс контроллера, и он определит службу и подключит правильные аргументы конструктора.

В этом случае он сгенерирует сервис с идентификатором app.controller.custody, определение которого можно увидеть, запустив php bin/console debug:container app.controller.custody.

Затем в services.yaml вот эта конфигурация

AppBundle\Controller\Shop\CustodyController:
    autowire: false
    public: true

который определяет другую службу с идентификатором AppBundle\Controller\Shop\CustodyController это не обрабатывается Силиусом.

Даже если эта конфигурация будет удалена, ошибка все равно будет, потому что настроена автоматическая загрузка службы, вот еще один пример на той же странице.

Решение простое: исключить контроллеры ресурсов из этого импорта:

# config/services.yaml
services:
    # makes classes in src/ available to be used as services
    # this creates a service per class whose id is the fully-qualified class name
    App\:
        resource: '../src/*'
        exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php,CustodyController.php}'

Если есть много контроллеров ресурсов и / или потенциально больше, которые нужно добавить, тогда может быть проще поместить их в общую папку и добавить в шаблон исключения глобуса, например:

# config/services.yaml
services:
    # makes classes in src/ available to be used as services
    # this creates a service per class whose id is the fully-qualified class name
    App\:
        resource: '../src/*'
        exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php,ResourceController}'
Другие вопросы по тегам