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}'