Symfony 2 Controller依赖项,扩展了ContainerAware [英] Symfony 2 Controller dependencies, extending ContainerAware

查看:113
本文介绍了Symfony 2 Controller依赖项,扩展了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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆