如何在自定义捆绑包控制器中使用学说 - "Controller has required constructor arguments and does not exist in the container. "
How to use doctrine in custom bundle controllers - "Controller has required constructor arguments and does not exist in the container. "
我有一个带有两个自定义可重用包的 Symfony 5.3 项目。
我在 bundle1 中创建了一个实体,我希望能够从 bundle2[=21 中读取和写入它=]
但是,我无法将 Doctrine 成功地包含在我的任何捆绑包控制器中。
我什么都试过了:扩展控制器,扩展AbstractController
,添加一个构造函数来传递原则,将控制器定义为服务,但我什么都做不了。
project/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>'
);
}
}
错误:
The controller for URI "/list" is not callable: Controller
"Bundle1\TestController\TestController" has required constructor
arguments and does not exist in the container. Did you forget to
define the controller as a service?
编辑**
根据@Cerad 的帮助对以下内容进行了修改,但不幸的是,相同的错误消息仍然存在。
我正在使用自动装配,我有以下 services.xml 通过依赖注入加载:
project/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>
我使用了路由注释
project/config/routes/annotations.yaml文件:
controllers-bundle1:
resource: ../../bundle1/src/Controller/
type: annotation
当我在控制台中 运行 php bin/console debug:container 'bundle1.controller.test_controller'
时,我得到:
No services found that match
"bundle1.controller.test_controller".
project/bundle1/src/Bundle1.php
namespace Bundle1;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class Bundle1 extends Bundle
{
public function getPath(): string
{
return \dirname(__DIR__);
}
}
project/config/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 Too few arguments to function
Bundle1\TestController\TestController::__construct(), 0 passed in
/home/Project/vendor/symfony/http-kernel/Controller/ControllerResolver.php
on line 147 and exactly 1 expected
in bundle1/src/Controller/TestController.php (line 17) class
TestController { private $entityManager; public function
__construct( EntityManagerInterface $entityManager) { $this->em = $entityManager;
让我们从符合 'best practices' 的实际答案开始,然后讨论一下。
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 就是一个很好的例子。
我们没有使用控制器 class 名称作为服务 ID,而是根据推荐做法拼写了一个。您的路线将需要使用它。
public=true 非常重要。 Symfony 使用容器感知控制器解析器并最终从容器中提取控制器服务。所以控制器服务必须是public.
如果您需要将服务注入到操作方法中,则需要该标签。不确定您是否应该使用捆绑包来执行此操作。如果您不需要它,请将其删除。
当然,您需要手动注入任何服务或参数。容器文档有更多示例。
讨论了一些替代方法 here。
我有一个带有两个自定义可重用包的 Symfony 5.3 项目。
我在 bundle1 中创建了一个实体,我希望能够从 bundle2[=21 中读取和写入它=]
但是,我无法将 Doctrine 成功地包含在我的任何捆绑包控制器中。
我什么都试过了:扩展控制器,扩展AbstractController
,添加一个构造函数来传递原则,将控制器定义为服务,但我什么都做不了。
project/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>'
);
}
}
错误:
The controller for URI "/list" is not callable: Controller "Bundle1\TestController\TestController" has required constructor arguments and does not exist in the container. Did you forget to define the controller as a service?
编辑** 根据@Cerad 的帮助对以下内容进行了修改,但不幸的是,相同的错误消息仍然存在。
我正在使用自动装配,我有以下 services.xml 通过依赖注入加载:
project/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>
我使用了路由注释
project/config/routes/annotations.yaml文件:
controllers-bundle1:
resource: ../../bundle1/src/Controller/
type: annotation
当我在控制台中 运行 php bin/console debug:container 'bundle1.controller.test_controller'
时,我得到:
No services found that match "bundle1.controller.test_controller".
project/bundle1/src/Bundle1.php
namespace Bundle1;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class Bundle1 extends Bundle
{
public function getPath(): string
{
return \dirname(__DIR__);
}
}
project/config/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 Too few arguments to function Bundle1\TestController\TestController::__construct(), 0 passed in /home/Project/vendor/symfony/http-kernel/Controller/ControllerResolver.php on line 147 and exactly 1 expected
in bundle1/src/Controller/TestController.php (line 17) class TestController { private $entityManager; public function __construct( EntityManagerInterface $entityManager) { $this->em = $entityManager;
让我们从符合 'best practices' 的实际答案开始,然后讨论一下。
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 就是一个很好的例子。
我们没有使用控制器 class 名称作为服务 ID,而是根据推荐做法拼写了一个。您的路线将需要使用它。
public=true 非常重要。 Symfony 使用容器感知控制器解析器并最终从容器中提取控制器服务。所以控制器服务必须是public.
如果您需要将服务注入到操作方法中,则需要该标签。不确定您是否应该使用捆绑包来执行此操作。如果您不需要它,请将其删除。
当然,您需要手动注入任何服务或参数。容器文档有更多示例。
讨论了一些替代方法 here。