【发布时间】:2019-01-21 20:39:47
【问题描述】:
Symfony 版本:4.1.3
我有一个应用程序,它通过路由加载器服务根据配置加载动态路由,但 Symfony 4 似乎没有自动装配动态路由控制器。
我使用的是标准 Symfony 4 应用程序 services.yaml 文件:
/config/services.yaml
parameters:
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
public: false # Allows optimizing the container by removing unused services; this also means
# fetching services directly from the container via $container->get() won't work.
# The best practice is to be explicit about your dependencies anyway.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
Application\Web\:
resource: '../src/*'
exclude: '../src/{Search/Model,Entity,Migrations,Tests,Kernel.php}'
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
Application\Web\Controller\:
resource: '../src/Controller'
tags: ['controller.service_arguments']
路由加载器: src/Component/RouteLoader.php
<?php
namespace Application\Web\Component;
use Application\Symfony\Bundle\ConfigBundle\ReaderInterface;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
/**
* Class RouteLoader
* @package Application\Web\Component
*/
class RouteLoader
{
/**
* @var ReaderInterface
*/
private $configurationReader;
public function __construct(ReaderInterface $configurationReader)
{
$this->configurationReader = $configurationReader;
}
public function load(): RouteCollection
{
$routes = new RouteCollection();
foreach ($this->configurationReader->find('category_navigation') as $label => $configuration) {
$slug = strtolower($label);
$route = new Route(
$configuration['url'],
[
'_controller' => [$configuration['controller'], 'dispatch'],
'categories_slug' => $slug,
'category_label' => $label,
'page_title' => $configuration['page_title'] ?? null,
'page_description' => $configuration['page_description'] ?? null,
],
[],
[],
'',
[],
['GET']
);
$routes->add($slug . '.home', $route);
}
return $routes;
}
}
控制器构造函数: src/Controller/Page.php
<?php
namespace Application\Web\Controller;
//.... other class code
public function __construct(
ClientInterface $client,
ReaderInterface $configurationReader,
\Twig_Environment $twigEnvironment,
ContentSearcher $contentSearcher,
Environment $environment,
TokenStorageInterface $tokenStorage,
UrlGeneratorInterface $urlGenerator
)
当我尝试加载页面时,Symfony 发出以下错误:
Controller "\Application\Web\Controller\Page" has required constructor arguments and does not exist in the container. Did you forget to define such a service?
但是,当我直接在 config/routes.yaml 文件中定义路由时,控制器会自动装配样式,没有任何问题!
我的问题是:
- 这是 Symfony 自动装配功能的限制吗,即不支持动态路由控制器?
- 在定义使自动装配工作的路线时,我是否遗漏了什么?
- 我是否发现了潜在的错误?
有什么想法吗?
编辑:堆栈跟踪
InvalidArgumentException:
Controller "\Application\Web\Controller\Page" has required constructor arguments and does not exist in the container. Did you forget to define such a service?
at vendor/symfony/http-kernel/Controller/ContainerControllerResolver.php:62
at Symfony\Component\HttpKernel\Controller\ContainerControllerResolver->instantiateController('\\Application\\Web\\Controller\\Page')
(vendor/symfony/framework-bundle/Controller/ControllerResolver.php:54)
at Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver->instantiateController('\\Application\\Web\\Controller\\Page')
(vendor/symfony/http-kernel/Controller/ControllerResolver.php:49)
at Symfony\Component\HttpKernel\Controller\ControllerResolver->getController(object(Request))
(vendor/symfony/http-kernel/Controller/TraceableControllerResolver.php:38)
at Symfony\Component\HttpKernel\Controller\TraceableControllerResolver->getController(object(Request))
(vendor/symfony/http-kernel/HttpKernel.php:132)
at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), 1)
(vendor/symfony/http-kernel/HttpKernel.php:66)
at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), 1, true)
(vendor/symfony/http-kernel/Kernel.php:188)
at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
(public/index.php:37)
ArgumentCountError:
Too few arguments to function Application\Web\Controller\Base::__construct(), 0 passed in /var/www/html/vendor/symfony/http-kernel/Controller/ControllerResolver.php on line 133 and exactly 7 expected
at src/Controller/Base.php:55
at Application\Web\Controller\Base->__construct()
(vendor/symfony/http-kernel/Controller/ControllerResolver.php:133)
at Symfony\Component\HttpKernel\Controller\ControllerResolver->instantiateController('\\Application\\Web\\Controller\\Page')
(vendor/symfony/http-kernel/Controller/ContainerControllerResolver.php:55)
at Symfony\Component\HttpKernel\Controller\ContainerControllerResolver->instantiateController('\\Application\\Web\\Controller\\Page')
(vendor/symfony/framework-bundle/Controller/ControllerResolver.php:54)
at Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver->instantiateController('\\Application\\Web\\Controller\\Page')
(vendor/symfony/http-kernel/Controller/ControllerResolver.php:49)
at Symfony\Component\HttpKernel\Controller\ControllerResolver->getController(object(Request))
(vendor/symfony/http-kernel/Controller/TraceableControllerResolver.php:38)
at Symfony\Component\HttpKernel\Controller\TraceableControllerResolver->getController(object(Request))
(vendor/symfony/http-kernel/HttpKernel.php:132)
at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), 1)
(vendor/symfony/http-kernel/HttpKernel.php:66)
at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), 1, true)
(vendor/symfony/http-kernel/Kernel.php:188)
at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
(public/index.php:37)
【问题讨论】:
-
加载路由时,
$configuration['url']是否包含用于类名的前导斜杠? -
@xabbuh
$configuration['url']包含一个 URL,例如/health。你的意思是我的班级名称是否有前导斜杠?如果是这样,是的。 -
@xabbuh 你真是个天才!当我从动态指定的类名中删除前导斜杠时,它起作用了! :)
标签: php symfony routing autowired symfony4