web-dev-qa-db-fra.com

Comment utiliser mes entités et gestionnaires d'entités dans la commande de console Symfony 2?

Je veux quelques commandes de terminal pour mon application Symfony2. J'ai parcouru le exemple dans le livre de cuisine , mais je n'ai pas pu trouver comment accéder à mes paramètres, à mon gestionnaire d'entités et à mes entités ici. Dans le constructeur, j'obtiens le conteneur (qui devrait me donner accès aux paramètres et aux entités) en utilisant

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

Mais cet appel génère une erreur:

Erreur fatale: appel à une fonction membre getKernel () sur un non-objet dans /Users/fester/Sites/thinkblue/admintool/vendor/symfony/src/Symfony/Bundle/FrameworkBundle/Command/ContainerAwareCommand.php sur la ligne 38

Fondamentalement, dans ContainerAwareCommand-> getContainer () l'appel à

$this->getApplication()

renvoie NULL et non un objet comme prévu. Je suppose que j'ai laissé une étape importante, mais laquelle? Et comment vais-je enfin pouvoir utiliser mes paramètres et entités?

42
Fester Bestertester

Je pense que vous ne devriez pas récupérer le conteneur directement dans le constructeur. Au lieu de cela, récupérez-le dans la méthode configure ou dans la méthode execute. Dans mon cas, j'obtiens mon gestionnaire d'entité juste au début de la méthode execute comme ça et tout fonctionne bien (testé avec Symfony 2.1).

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

    // Code here
}

Je pense que l'instanciation de l'objet d'application n'est pas encore effectuée lorsque vous appelez getContainer dans votre constructeur, ce qui entraîne cette erreur. L'erreur vient de la méthode getContainer qui essaie de faire:

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

Puisque getApplication n'est pas encore un objet, vous obtenez une erreur indiquant ou appelez une méthode getKernel sur un non-objet.

Mise à jour : Dans la nouvelle version de Symfony, getEntityManager a été déconseillé (et aurait pu être supprimé complètement maintenant). Utilisez à la place $entityManager = $this->getContainer()->get('doctrine')->getManager();. Merci à Chausser de l'avoir pointé.

Mise à jour 2 : Dans Symfony 4, le câblage automatique peut être utilisé pour réduire la quantité de code nécessaire.

Créez un __constructor Avec une variable EntityManagerInterface. Cette variable sera accessible dans le reste de vos commandes. Cela suit le schéma d'injection de dépendance à câblage automatique.

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();
  }
}

Crédits à @ profm2 pour avoir fourni le commentaire et l'exemple de code.

75
Matt

étend votre classe de commande à partir de ContainerAwareCommand au lieu de Command

class YourCmdCommand extends ContainerAwareCommand

et obtenez le gestionnaire d'entité comme ceci:

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

Je sais que la réponse de Matt a résolu la question, mais si vous avez plus d'un gestionnaire d'entité, vous pouvez utiliser ceci:

Créez model.xml avec:

<?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>

Chargez ensuite ce fichier dans votre extension DI

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

Ensuite, vous pouvez l'utiliser n'importe où. Dans la commande de console, exécutez:

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

et n'oubliez pas à la fin de:

$em->flush();

Vous pouvez maintenant l'utiliser comme argument dans un autre service dans services.yml:

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

J'espère que cela aidera quelqu'un.

4
TheLastTamurai