2011-09-22 47 views
38

我想要一些終端命令到我的Symfony2應用程序。我已經通過example in the cookbook,但我無法找到如何訪問我的設置,我的實體經理和我的實體在這裏。在構造函數中,我得到的容器使用如何在Symfony 2控制檯命令中使用我的實體和實體管理器?

$this->container = $this->getContainer(); 

(其應產生我訪問設置和實體),但該調用生成錯誤:

Fatal error: Call to a member function getKernel() on a non-object in /Users/fester/Sites/thinkblue/admintool/vendor/symfony/src/Symfony/Bundle/FrameworkBundle/Command/ContainerAwareCommand.php on line 38

基本上,在ContainerAwareCommand-> getContainer()撥打電話

$this->getApplication() 

返回NULL並且不是預期的對象。我想我離開了一些重要的步驟,但哪一個?我將如何最終能夠使用我的設置和實體?

+0

我有同樣的錯誤時,(我試圖訪問'getContainer() 'MyCommand-> execute()'裏面,但仍然得到相同的致命錯誤。我的'CommandTest擴展\ PHPUnit_Framework_Testcase',我通過'phpunit -c app src/CompanyName/MyBundle/Tests/Commands/MyCommandTest.php'運行它。任何想法可能是錯誤的? –

回答

71

我想你不應該直接在構造函數中檢索容器。相反,請在configure方法或execute方法中檢索它。在我的情況下,我的實體管理器就在這樣的execute方法的開頭,並且一切工作正常(用Symfony 2.1進行測試)。

protected function execute(InputInterface $input, OutputInterface $output) 
{ 
    $entityManager = $this->getContainer()->get('doctrine')->getEntityManager(); 

    // Code here 
} 

我認爲,當你在你的構造函數,導致此錯誤調用getContainer應用程序對象的實例化沒有完成呢。錯誤來自getContainer方法tyring做:

$this->container = $this->getApplication()->getKernel()->getContainer(); 

由於getApplication是不是一個對象呢,你會得到一個錯誤說或呼籲非對象的方法getKernel

更新:在較新版本的Symfony中,getEntityManager已被棄用(現在可能已被完全刪除)。改爲使用$entityManager = $this->getContainer()->get('doctrine')->getManager();。感謝Chausser指向它。

更新2:在Symfony 4中,可以使用自動佈線來減少所需的代碼量。使用EntityManagerInterface變量創建__constructor。這個變量將在其餘的命令中被訪問。這遵循自動佈線依賴注入方案。

class UserCommand extends ContainerAwareCommand { 
    private $em; 

    public function __construct(?string $name = null, EntityManagerInterface $em) { 
    parent::__construct($name); 

    $this->em = $em; 
    } 

    protected function configure() { 
    **name, desc, help code here** 
    } 

    protected function execute(InputInterface $input, OutputInterface $output) { 
    $this->em->getRepository('App:Table')->findAll(); 
    } 
} 

積分@ profm2提供評論和代碼示例。

+0

我有那一個想法o但是作爲一個新手,我無法回答我自己的問題。你不能在構造函數中獲取容器,因爲它還不存在。如果您使用execute方法檢索容器,這一切都可以很好地工作。之後,您可以通過以下常用方式訪問您的實體: $ myEntities = $ em-> getRepository('Acme \ DemoBundle:Myentity') - > findAll(); –

+10

使用最新版本 - > getEntityManager();現在棄用 - > getManager(); – Chausser

+1

請記住擴展ContainerAwareCommand而不是命令以訪問getContainer()方法 – tuxone

4

我知道馬特的答案來解決問題,但如果你已經不止一個實體管理器,您可以使用此:

製作model.xml有:

<?xml version="1.0" encoding="UTF-8" ?> 

<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="EM_NAME.entity_manager" alias="doctrine.orm.entity_manager" /> 
</services> 
</container> 

然後加載該文件在你的DI擴展中

$loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); 
$loader->load('model.xml'); 

然後你可以在任何地方使用它。 在控制檯命令執行:

$em = $this->getContainer()->get('EM_NAME.entity_manager'); 

,並在結束不要忘了:

$em->flush(); 

您現在可以使用它作爲另一個服務services.yml一個論點:

services: 
    SOME_SERVICE: 
     class: %parameter.class% 
     arguments: 
      - @EM_NAME.entity_manager 

希望這可以幫助別人。

8

從ContainerAwareCommand而不是命令

class YourCmdCommand extends ContainerAwareCommand 

擴展您的命令類,並得到這樣的實體管理器:

$em = $this->getContainer()->get('doctrine.orm.entity_manager');