Sylius:如何使用自定义控制器创建我自己的自定义资源而不会出现 "can not autowire"-exception?

Sylius: how to create my own Custom Resource with custom controller without getting "can not autowire"-exception?

我想按照 here. After many pitfalls and errors as described blow I looked also at some Sylius plugins and found this one 所述在 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 .....
    }
}

但是,它会导致以下错误:

Cannot autowire service "AppBundle\Controller\Shop\CustodyController": argument "$metadata" of method "Sylius\Bundle\ResourceBundle\Controller\ResourceController::__construct()" references interface "Sylius\Component\Resource\Metadata\MetadataInterface" but no such service exists. Did you create a class that implements this interface?

搜索此错误将我带到这个 GitHub 问题,人们建议将此特定控制器的 autowire 设置为 false。所以我做了:

services.yml:

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

但是这样调用构造函数时没有任何参数:

Too few arguments to function Sylius\Bundle\ResourceBundle\Controller\ResourceController::__construct(), 0 passed in /var/www/var/cache/dev/Container1MQRWcB/getCustodyControllerService.php on line 16 and exactly 17 expected

我很好奇为什么类似的配置在我上面提到的 CmsPlugin 中有效,但在我的情况下却没有。

我怎样才能做到这一点?

基于此配置

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

Sylius 将根据 resource bundle documentation

生成一些服务,包括资源控制器

只需定义控制器 class,它将定义服务并连接正确的构造函数参数。

在这种情况下,它会生成一个id为app.controller.custody的服务,这个定义可以通过运行 php bin/console debug:container app.controller.custody.

看到

然后,在services.yaml中有这个配置

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

它定义了另一个未被 Sylius 处理的 ID 为 AppBundle\Controller\Shop\CustodyController 的服务。

即使删除该配置,错误仍然存​​在,因为在同一页面上有一个 automatic service loading configured, here's another example

解决方案很简单:从该导入中排除资源控制器:

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

如果有很多资源控制器 and/or 可能会添加更多,那么将它们放在一个公共文件夹中并将其添加到 exlude glob 模式可能会更容易,例如:

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