42 votes

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

Je veux ajouter quelques commandes de terminal à mon application Symfony2. J'ai parcouru le exemple dans le livre de cuisine mais je n'ai pas trouvé 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 on line 38

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

$this->getApplication()

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

0 votes

J'ai la même erreur lorsque (et je tente d'accéder à getContainer() à l'intérieur de MyCommand->execute() mais je reçois toujours la même erreur fatale. CommandTest extends \PHPUnit_Framework_Testcase et je l'exécute via phpunit -c app src/CompanyName/MyBundle/Tests/Commands/MyCommandTest.php Une idée de ce qui peut être mauvais ?

79voto

Matt Points 5550

Je pense que vous ne devriez pas récupérer le conteneur dans le constructeur directement. Au lieu de cela, récupérez-le dans la méthode configure ou dans la méthode execute méthode. Dans mon cas, j'obtiens mon gestionnaire d'entités juste au début de la méthode execute comme ceci 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 faite quand vous appelez getContainer dans votre constructeur, ce qui entraîne cette erreur. L'erreur provient du getContainer méthode à faire :

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

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

Mise à jour : Dans une version plus récente de Symfony, getEntityManager a été déprécié (et aurait pu être supprimé complètement à l'heure actuelle). Utilisez $entityManager = $this->getContainer()->get('doctrine')->getManager(); à la place. Grâce à Chausser pour l'avoir signalé.

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

Créer un __constructor avec un EntityManagerInterface variable. Cette variable sera accessible dans le reste de vos commandes. Ceci suit le schéma d'injection de dépendances à 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.

0 votes

J'avais déjà compris cela, mais en tant que novice, je ne pouvais pas répondre à ma propre question. Vous ne pouvez pas obtenir le conteneur dans le constructeur, car il n'existe pas encore. Tout fonctionne parfaitement si vous récupérez le conteneur dans la méthode execute. Après cela, vous avez accès à vos Entités de la manière habituelle : $myEntities = $em->getRepository('Acme \DemoBundle :Myentity')->findAll() ;

10 votes

Avec la dernière version, ->getEntityManager() ; est maintenant déprécié en faveur de ->getManager() ;

1 votes

N'oubliez pas d'étendre ContainerAwareCommand au lieu de Command afin d'accéder à la méthode getContainer().

10voto

stloc Points 123

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

class YourCmdCommand extends ContainerAwareCommand

et obtenir un gestionnaire d'entités comme celui-ci :

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

0 votes

ContainerAwareCommand est déprécié depuis la version 4.2 - une solution pour son utilisation ultérieure ?

0 votes

@Isengo montrer d'autres réponses plus récentes parce que ma suggestion est trop ancienne.

0 votes

@Isengo A partir de Symfony 4.2, vous pouvez injecter l'outil Doctrine. \ORM\EntityManagerInterface dans la commande.

4voto

TheLastTamurai Points 76

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

Faites 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');

Vous pouvez ensuite l'utiliser n'importe où. Dans la commande 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.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X