Symfony 2 Controller依赖项,扩展了ContainerAware [英] Symfony 2 Controller dependencies, extending ContainerAware
问题描述
在深入研究了symfony代码之后,尤其是ControllerResolver,除非我自己子类化/实现ControllerResolverInterface,否则看来我尝试做的事情实际上是不可能的.
after digging into the symfony code, particularly the ControllerResolver, it seems what im trying to do actually isnt possible unless i subclass/implement ControllerResolverInterface myself.
下面的代码实例化了从路由传递过来的控制器:
this is the following code which instantiates the controller passed from the route:
protected function createController($controller)
{
if (false === strpos($controller, '::')) {
throw new \InvalidArgumentException(sprintf('Unable to find controller "%s".', $controller));
}
list($class, $method) = explode('::', $controller, 2);
if (!class_exists($class)) {
throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
}
return array(new $class(), $method);
}
正如您在最后一行看到的那样,
总是在没有传递任何参数的情况下实例化,因此我将不得不重写此方法以这种方式注入某些东西.感觉很hacky.
as you can see on the last line, this is always instantiated with no arguments passed, so i will have to override this method to inject something in that way. feels very hacky.
我试图弄清楚如何使用Symfony组件(例如 not 完整堆栈框架)将服务注入动态路由中定义的自定义控制器中.
I'm trying to figure out how I can inject services into a custom controller defined in dynamic routes using Symfony components (e.g. not the full stack framework).
请注意,我不使用完整的堆栈框架,也不使用其DemoBundle src代码.我有一个需要组件的composer.json
文件,所以我有一个自定义index.php
文件,该文件与此处详细介绍的文件大致相同:
Please note, I am not using the full stack framework and am not using their DemoBundle src code. I have a composer.json
file that requires components, so I have a custom index.php
file which is more or less the same as that detailed here:
$routes = new RouteCollection();
$routes->add(
'some route name',
new Route(
'a route path',
array(
'_controller' => 'App\MyBundle\Controller\MyController::handle'
)
)
);
然后我在App/MyBundle/DependencyInjection/MyExtension.php
中包含以下内容:
Then I have the following within App/MyBundle/DependencyInjection/MyExtension.php
:
public function load(array $configs, ContainerBuilder $container) {
$loader = new XmlFileLoader(
$container,
new FileLocator(__DIR__.'/../Resource/config')
);
$loader->load('services.xml');
}
App/MyBundle/Resources/config/services.xml
:
<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
http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="templating" class="Symfony\Component\Templating\EngineInterface" />
<service id="navigation" class="App\MyBundle\Controller\MyController">
<argument type="service" id="templating" />
</service>
</services>
</container>
我基本上是想将模板服务注入到MyController
构造函数中,我的理解是MyExtension
文件应该自动加载.我以为我没有使用完整的堆栈框架,这就是原因,但是我如何才能使它正常工作?
I'm basically trying to get the templating service injected into the MyController
constructor, and my understanding is the MyExtension
file should be loaded automatically. I assume as I'm not using the full stack framework, this is the reason why, but how can I get this working?
推荐答案
重写ControllerResolver没错.全栈框架也可以做到这一点.否则,控制器就不能成为ContainerAware.
Nothing wrong with overriding ControllerResolver. The full stack framework does that too. Otherwise the Controllers couldn't be ContainerAware.
我还使用了没有完整堆栈框架的Symfony组件,并且部分复制了完整堆栈框架,最终我将其注入到控制器中
I also use Symfony Components without the full stack framework and, partly copying the full stack framework, I ended up with this in order to inject the container in my controllers
class ControllerResolver extends SymfonyControllerResolver
{
protected $container;
public function __construct(ContainerInterface $container, LoggerInterface $logger = null)
{
$this->container = $container;
parent::__construct($logger);
}
protected function createController($controller)
{
if (false === strpos($controller, '::')) {
throw new \InvalidArgumentException(sprintf('Unable to find controller "%s".', $controller));
}
list($class, $method) = explode('::', $controller, 2);
$class = "Namespace\\Controllers\\" . $class;
if (!class_exists($class)) {
throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
}
$controller = new $class();
if ($controller instanceof ContainerAwareInterface) {
$controller->setContainer($this->container);
}
return array($controller, $method);
}
}
如果您想增加将控制器定义为服务的可能性,可以替换
If you wanted to add possibility to define controllers as services you can replace
if (!class_exists($class)) {
throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
}
$controller = new $class();
if ($controller instanceof ContainerAwareInterface) {
$controller->setContainer($this->container);
}
类似
if (!class_exists($class)) {
if (!$this->container->has($class)) {
throw new \Exception( ... );
}
$controller = $this->container->get($class);
return array($controller, $method);
}
$controller = new $class();
if ($controller instanceof ContainerAwareInterface) {
$controller->setContainer($this->container);
}
return array($controller, $method);
这篇关于Symfony 2 Controller依赖项,扩展了ContainerAware的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!