web-dev-qa-db-ja.com

Symfony 2コンソールコマンドでエンティティとエンティティマネージャーを使用する方法

Symfony2アプリケーションにいくつかのターミナルコマンドを追加します。 クックブックの例 を試しましたが、ここで自分の設定、エンティティマネージャ、およびエンティティにアクセスする方法を見つけることができませんでした。コンストラクターで、コンテナーを取得します(これにより、設定とエンティティーにアクセスできるようになります)。

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

しかし、この呼び出しはエラーを生成します:

致命的なエラー:38行目の/Users/fester/Sites/thinkblue/admintool/vendor/symfony/src/Symfony/Bundle/FrameworkBundle/Command/ContainerAwareCommand.phpの非オブジェクトでメンバー関数getKernel()を呼び出す

基本的に、ContainerAwareCommand-> getContainer()での呼び出し

$this->getApplication()

期待どおりのオブジェクトではなくNULLを返します。重要な一歩を省いたと思いますが、どれですか?そして、最終的に設定とエンティティをどのように使用できるようになりますか?

42

コンストラクタでコンテナを直接取得しないでください。代わりに、configureメソッドまたはexecuteメソッドで取得してください。私の場合、このようなexecuteメソッドの開始時にエンティティマネージャーを取得し、すべてが正常に動作しています(Symfony 2.1でテスト済み)。

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

    // Code here
}
_

このエラーが発生するコンストラクタでgetContainerを呼び出しているとき、アプリケーションオブジェクトのインスタンス化はまだ行われていないと思います。エラーはgetContainerメソッドの実行が原因です。

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

getApplicationはまだオブジェクトではないため、非オブジェクトに対してgetKernelメソッドを呼び出すか呼び出しているというエラーが表示されます。

Update:Symfonyの新しいバージョンでは、getEntityManagerは非推奨になりました(そして今では完全に削除できました)。代わりに$entityManager = $this->getContainer()->get('doctrine')->getManager();を使用してください。 Chausser に感謝します。

Update 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の功績。

75
Matt

commandではなくContainerAwareCommandからコマンドクラスを拡張します

class YourCmdCommand extends ContainerAwareCommand

そして、このようなエンティティマネージャを取得します:

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

マットの答えが問題を解決したことは知っていますが、エンティティマネージャーが複数いる場合は、これを使用できます。

次を使用して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

これが誰かを助けることを願っています。

4
TheLastTamurai