2013-02-18 69 views
3

我遵循了Fabien Potiencier的教程,約爲how to create your own Framework on top of the Symfony Components。現在我需要一種方法。我想將Dependency Container注入到我的所有控制器中,而無需將每個Controller都定義爲服務。創建一個實現ContainerAwareInterface的基類控制器類

在原單的Symfony2框架的所有控制器擴展了Controller類位於Symfony\Bundle\FrameworkBundle\Controller\Controller.php

namespace Symfony\Bundle\FrameworkBundle\Controller; 

class Controller extends ContainerAware 
{ 
    // ... 
} 

Controller類擴展ControllerAware類,所以你可以做這樣的事情在你的控制器:

use Symfony\Bundle\FrameworkBundle\Controller\Controller; 

class MyController extends Controller 
{ 
    public function someAction() 
    { 
     $this->container->get('dependencie_xyz); 
    } 
} 

所以我的問題是:我怎樣才能在我的框架中完成相同的?

回答

3

我花了一段時間,但我終於想出了Symfony2框架是如何做到的。 在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); 
     } 
    } 
} 

來源:

https://github.com/symfony/symfony/blob/master/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php

+0

你是如何註冊這個自定義控制器解析器的?嘗試註冊時出現參數錯誤。 – 2016-11-09 19:27:22

-1

控制器類擴展了ControllerAware類,所以你可以做這樣的事情在你的控制器:

好了,這是不正確的。如果我們看看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類,並讓所有的控制器擴展該控制器類。

+0

問題不是get方法,問題是如何讓容器注入到我的控制器中。我不知道Symfony框架如何解決這個問題,沒有將每個Controller都聲明爲服務。除此之外,我沒有寫$ this-> get(「」),但$ this-> container-> get(「」) – c4pone 2013-02-22 09:33:07

+0

我想知道爲什麼有人低估了這個問題? – 2013-02-26 13:07:33

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 
    } 

} 

在service.yml

寫smthing等作爲參數,這種

services: 
    test_service: 
     class: Symfony\Bundle\FrameworkBundle\TestService 
     arguments: ['@service_container'] 

和後期服務容器

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; 
} 
相關問題