我遵循了Fabien Potiencier的教程,关于how to create your own Framework on top of the Symfony Components。现在我需要一种方法。我想将Dependency Container注入我的所有控制器,而不是将每个Controller都定义为服务。
在原始的Symfony2 Framework中,所有控制器都扩展了位于Controller
的{{1}}类:
Symfony\Bundle\FrameworkBundle\Controller\Controller.php
namespace Symfony\Bundle\FrameworkBundle\Controller;
class Controller extends ContainerAware
{
// ...
}
类扩展了Controller
类,因此您可以在Controller中执行以下操作:
ControllerAware
所以我的问题是:如何在我的框架中完成相同的工作?
答案 0 :(得分:3)
我花了一段时间,但我终于弄清楚了Symfony2 Framework是如何做到的。 在SymfonyFrameworkBundle中是一个自定义的ControllerResolver,它在已解析的控制器上调用setContainer方法。控制器必须是ContainerAwareInterface的实例。
简化版:
class ContainerAwareControllerResolver extends ControllerResolver
{
private $container;
public __construct(ContainerInterface $container)
{
$this->container = $container;
parent::__construct();
}
public function getController(Request $request)
{
$controller = parent::getController($request);
if($controller instanceof ContainerAware ){
$controller->setContainer($this->container);
}
}
}
来源:
答案 1 :(得分:0)
太简单了。下一个代码将帮助您
namespace Symfony\Bundle\FrameworkBundle\Controller;
use Symfony\Component\DependencyInjection\ContainerInterface as Container;
use Symfony\Component\DependencyInjection\ContainerAware as ContainerAware;
class TestService extends ContainerAware
{
public function __construct(Container $container) {
// in your example from official doc 'dependencie_xyz' is a name of service
$this->setContainer($container); // call parent setContainer() method, for identifying container variable, from now you can access to ServiceContainer using $this->container variable
$test_param = $this->container->getParameter('test_param'); // get test_param from config.yml
}
}
in service.yml
写这样的东西
services:
test_service:
class: Symfony\Bundle\FrameworkBundle\TestService
arguments: ['@service_container']
并将服务容器作为参数发布
答案 2 :(得分:0)
如果你没有在控制器上实现任何接口,你可以添加这种方式,它将工作。这是对c4pone实现的一个小修改。
/**
* Description of ContainerAwareControllerResolver
*
* @author sbc
*/
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Controller\ControllerResolver;
class ContainerAwareControllerResolver extends ControllerResolver {
private $container;
public function __construct(LoggerInterface $logger = null, ContainerInterface $container = null) {
parent::__construct($logger);
$this->container = $container;
}
protected function instantiateController($class) {
$new_class = new $class();
$new_class->setContainer($this->container);
return $new_class;
}
答案 3 :(得分:-1)
Controller类扩展了ControllerAware类,因此您可以在Controller中执行以下操作:
嗯,事实并非如此。如果我们查看the signature of the ContainerAware
class,我们会看到这添加了setContainer
方法,因此我们可以设置容器。 Symfony2创建了Controller::get
方法,使一些人更容易生活。
我们可以看到他们是如何做到的in the source code:
/**
* Gets a service by id.
*
* @param string $id The service id
*
* @return object The service
*/
public function get($id)
{
return $this->container->get($id);
}
您可以将它放在您自己的Controller
类中,让所有控制器扩展该控制器类。