0

我有一个带有两个自定义可重用包的 Symfony 5.3 项目。

我在bundle1中创建了一个实体,我希望能够从bundle2中读取和写入它

但是,我无法成功地将 Doctrine 包含在我的任何捆绑控制器中。

我已经尝试了一切:扩展控制器,扩展AbstractController,添加构造函数来传递教义,将控制器定义为服务,但我无法得到任何工作。

项目/bundle1/src/Controller/testController.php:

namespace Bundle1\TestController;

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Doctrine\ORM\EntityManagerInterface;
use Bundle1\Entity;


class TestController 
{

private $entityManager;

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

     /**
     * @Route("/list", name="list")
     */
    public function listingsAction(): Response
    {


    //$this->em = $this->getDoctrine()->getManager();

    return new Response(
            '<html><body><h1>List from DB</h1> 
            
            </body></html>'
        );
    }
}

错误:

URI "/list" 的控制器不可调用:控制器 "Bundle1\TestController\TestController" 具有必需的构造函数参数并且在容器中不存在。您是否忘记将控制器定义为服务?

编辑** 以下内容已根据@Cerad 的帮助进行了修改,但不幸的是相同的错误消息仍然存在。

我正在使用自动装配,并且通过依赖注入加载了以下 services.xml:

项目/bundle1/Resources/config/services.xml:

        <?xml version="1.0" encoding="UTF-8" ?>
        <container xmlns="http://symfony.com/schema/dic/services"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://symfony.com/schema/dic/services
                https://symfony.com/schema/dic/services/services-1.0.xsd">
 <services>
             <service 
                id="Bundle1\Controller\TestController\TestController" 
               public="true">
     <call method="setContainer">
                <argument type="service" id="doctrine.orm.entity_manager"/>
     </call>
                <tag name="controller.service_arguments"/>
            </service>
</services>
        </container>

我已经使用注释进行路由

项目/config/routes/annotations.yaml 文件:

controllers-bundle1:
    resource: ../../bundle1/src/Controller/
    type: annotation

当我php bin/console debug:container 'bundle1.controller.test_controller'在控制台中运行时,我得到:

未找到与“bundle1.controller.test_controller”匹配的服务。

项目/bundle1/src/Bundle1.php

namespace Bundle1;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class Bundle1 extends Bundle
{
    public function getPath(): string
    {
        return \dirname(__DIR__);
    }
}

项目/配置/bundles.php

return [
    Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
    Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
    Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
    Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
    Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
    Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
    Bundle1\Bundle1::class => ['all' => true],
];

似乎我没有正确地将我的控制器定义为服务,但在文档中找不到有关如何执行此操作的明确信息。

**更新:


刚刚在错误堆栈中找到了这个**

ArgumentCountError 函数 Bundle1\TestController\TestController::__construct() 的参数太少,在第 147 行的 /home/Project/vendor/symfony/http-kernel/Controller/ControllerResolver.php 中传递了 0,而预期的正好是 1

在 bundle1/src/Controller/TestController.php(第 17 行)类 TestController { private $entityManager; 公共函数 __construct(EntityManagerInterface $entityManager) { $this->em = $entityManager;

4

1 回答 1

0

让我们从一个符合“最佳实践”的实际答案开始,然后讨论一下。

class TestController // Should not extend anything for bundle controllers
{
    // All services should be injected
    public function __construct(private EntityManagerInterface $em)
...
# Resources/config/services.xml
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services
        https://symfony.com/schema/dic/services/services-1.0.xsd">

    <services>
        <service 
            id="my_bundle.controller.test_controller" 
            class="MyBundle\Controller\TestController" 
            public="true">
            <argument type="service" id="doctrine.orm.entity_manager"/>
            <tag name="controller.service_arguments"/>
        </service>
    </services>
</container>

# and since snake case service ids are recommended
# config/routes.yaml

bundle_test:
    path: /
    controller: my_bundle.controller.test_controller::index

这应该会给你一个注入了实体管理器的工作页面。

我们在这里使用 xml 是因为它在问题中使用过,但 php 可能会更好。web-profiler-bundle 就是一个很好的例子。

我们不使用控制器类名作为服务 id,而是按照推荐的做法拼出一个。您的路线将需要使用它。

public=true 非常重要。Symfony 使用容器感知控制器解析器并最终从容器中提取控制器服务。所以控制器服务必须是公开的。

如果您需要将服务注入到操作方法中,则需要该标记。不确定您是否应该使用捆绑包来执行此操作。如果您不需要它,请删除它。

当然,您需要手动注入任何服务或参数。容器文档有更多示例。

这里讨论了一些替代方法。

于 2021-08-18T13:05:59.720 回答