2017-06-15 106 views
2

我將我的應用程序從Symfony 2.8遷移到Symfony 3.3。Symfony 3:無法從控制器內部訪問容器

從我的控制器內我有這樣的:

public function indexAction() 
{ 
    $email = new Email(); 

    $form = $this->createForm(GetStartedType::class, $email, [ 
     'action' => $this->generateUrl('get_started_end'), 
     'method' => 'POST', 
    ]); 

    return [ 
     'form' => $form->createView(), 
    ]; 
} 

但我收到此異常:

調用一個成員函數get()方法在空

我控制器延伸Symfony\Bundle\FrameworkBundle\Controller\Controller

/** 
* {@inheritdoc} 
*/ 
class DefaultController extends Controller 
{ 
... 
} 

所以我有權訪問容器。

把一些堆放在Symfony的代碼的時候,我看到容器是否設置正確:

namespace Symfony\Component\DependencyInjection; 

/** 
* ContainerAware trait. 
* 
* @author Fabien Potencier <[email protected]> 
*/ 
trait ContainerAwareTrait 
{ 
    /** 
    * @var ContainerInterface 
    */ 
    protected $container; 

    /** 
    * Sets the container. 
    * 
    * @param ContainerInterface|null $container A ContainerInterface instance or null 
    */ 
    public function setContainer(ContainerInterface $container = null) 
    { 
     dump('Here in the ContainerAwareTrait'); 
     dump(null === $container); 
     $this->container = $container; 
    } 
} 

這轉儲

Here in the ContainerAwareTrait 
false 

所以自動裝配運作良好,並設置容器。

但在ControllerTrait我有這樣的:

trait ControllerTrait 
{ 
    /** 
    * Generates a URL from the given parameters. 
    * 
    * @param string $route   The name of the route 
    * @param mixed $parameters An array of parameters 
    * @param int $referenceType The type of reference (one of the constants in UrlGeneratorInterface) 
    * 
    * @return string The generated URL 
    * 
    * @see UrlGeneratorInterface 
    */ 
    protected function generateUrl($route, $parameters = array(), $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH) 
    { 
     dump('Here in the ControllerTrait'); 
     die(dump(null === $this->container)); 
     return $this->container->get('router')->generate($route, $parameters, $referenceType); 
    } 

    ... 

這是轉儲:

Here in the ControllerTrait 
true 

所以這裏的containernull,這將導致錯誤。

任何人都可以幫我解決這個問題嗎?

爲什麼container爲空?

如果可能的幫助,這是services.yml配置(與Symfony的卡梅斯默認):

# controllers are imported separately to make sure they're public 
# and have a tag that allows actions to type-hint services 
AppBundle\Controller\: 
    resource: '../../src/AppBundle/Controller' 
    public: true 
    tags: ['controller.service_arguments'] 

這個問題是張貼問題上Symfony's issue tracker

+0

我還沒有機會玩弄新的autowire控制器的東西。只是踢,嘗試添加調用:[[setContainer,['@service_container']]]到services.yml。不應該有必要。 – Cerad

+0

可能的重複:[Symfony控制器無法訪問容器](https://stackoverflow.com/questions/44446763/symfony-controller-unable-to-access-container)? – ccKep

+0

您可能希望將'composer.json'添加到問題中,以防萬一有一箇舊套件覆蓋了symfony 3.3的一部分 – ccKep

回答

0

S3.3自動裝配能力使得將控制器定義爲服務更容易一些。

將控制器定義爲服務的通常動機是避免注入容器。換句話說,您應該明確注入控制器使用的每項服務。 autowire功能允許你使用動作方法注入,所以你不必在構造函數中注入一堆東西。

但是,基礎Symfony控制器類提供了一些輔助函數,它使用了大約12種不同的服務。一次注入這些會很痛苦。我曾認爲自動裝配功能可能會爲您處理這個問題,但我想不是。

因此,您基本上需要在服務定義中添加對setContainer的調用。例如:

AppBundle\Controller\: 
    resource: '../../src/AppBundle/Controller' 
    public: true 
    [[setContainer, ['@service_container']]] 
    tags: ['controller.service_arguments'] 

自動裝配能力是一項非常重要的工作,所以如果3.4/4.0發生變化,我不會感到驚訝。

0

此問題已由PR #23239修復,並在Symfony 3.3.3轉載。

+0

是的,但我還沒有驗證它......當我做的時候,我會把這個標記爲最佳答案......謝謝! – Aerendir