¿Cómo usar mis Entidades y Administradores de Entidades en Symfony 2 Console Command?

4 minutos de lectura

avatar de usuario
Fester Bestertester

Quiero algunos comandos de terminal para mi aplicación Symfony2. he pasado por el ejemplo en el libro de cocina, pero no pude averiguar cómo acceder a mi configuración, mi administrador de entidades y mis entidades aquí. En el constructor, obtengo el contenedor (que debería darme acceso a configuraciones y entidades) usando

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

Pero esta llamada genera un error:

Error fatal: llamada a una función miembro getKernel() en un no objeto en /Users/fester/Sites/thinkblue/admintool/vendor/symfony/src/Symfony/Bundle/FrameworkBundle/Command/ContainerAwareCommand.php en la línea 38

Básicamente, en ContainerAwareCommand->getContainer() la llamada a

$this->getApplication()

devuelve NULL y no un objeto como se esperaba. Supongo que dejé algún paso importante por fuera, pero ¿cuál? ¿Y cómo finalmente podré usar mis configuraciones y entidades?

  • tengo el mismo error cuando (e intento acceder getContainer() dentro de MyCommand->execute() pero aún obtengo el mismo error fatal. mi CommandTest extends \PHPUnit_Framework_Testcase y lo ejecuto a través de phpunit -c app src/CompanyName/MyBundle/Tests/Commands/MyCommandTest.php ¿Alguna idea de lo que puede estar mal?

    – Dimitri K.

    25 de julio de 2014 a las 8:28

avatar de usuario
Mate

Creo que no debería recuperar el contenedor en el constructor directamente. En su lugar, recupérelo en el configure método o en el execute método. En mi caso, obtengo mi administrador de entidad justo al comienzo de la execute método como este y todo funciona bien (probado con Symfony 2.1).

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

    // Code here
}

Creo que la creación de instancias del objeto de la aplicación aún no se ha realizado cuando está llamando getContainer en su constructor que da como resultado este error. El error viene del getContainer método que intenta hacer:

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

Ya que getApplication aún no es un objeto, obtiene un error que dice o está llamando a un método getKernel en un no-objeto.

Actualizar: En la versión más nueva de Symfony, getEntityManager ha quedado en desuso (y podría haberse eliminado por completo ahora). Usar $entityManager = $this->getContainer()->get('doctrine')->getManager(); en cambio. Gracias a Chausser por señalarlo.

Actualización 2: En Symfony 4, se puede usar el cableado automático para reducir la cantidad de código necesario.

Crear un __constructor con un EntityManagerInterface variable. Esta variable será accesible en el resto de sus comandos. Esto sigue el esquema de inyección de dependencia de cableado automático.

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éditos a @profm2 por proporcionar el comentario y el código de muestra.

  • Con la última versión ->getEntityManager(); ahora está en desuso a favor de ->getManager();

    – Perseguir

    27 de junio de 2013 a las 5:21

  • Recuerde extender ContainerAwareCommand en lugar de Command para acceder al método getContainer()

    – esmoquin

    18 de marzo de 2014 a las 12:28

  • En Symfony 4, crea un __constructor con una variable EntityManagerInterface. Esta variable será accesible en el resto de sus comandos. Esto sigue el esquema de autowiring/dependencyInjection.

    – profem2

    16 de enero de 2018 a las 19:59

  • Un pequeño apéndice: no te olvides de poner el use Doctrine\ORM\EntityManagerInterface; en la cima

    – muc

    29 ago 2018 a las 18:50

  • ContainerAwareCommand está en desuso desde 4.2. ¿Alguna solución para usar más adelante?

    – Isengo

    13 de diciembre de 2018 a las 13:51

extiende su clase de comando desde ContainerAwareCommand en lugar de Command

class YourCmdCommand extends ContainerAwareCommand

y obtenga un administrador de entidades como este:

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

  • ContainerAwareCommand está en desuso desde 4.2. ¿Alguna solución para usar más adelante?

    – Isengo

    13 de diciembre de 2018 a las 13:52

  • @Isengo muestra otras respuestas más recientes porque mi sugerencia es demasiado antigua

    – stloc

    14 de diciembre de 2018 a las 19:54

  • @Isengo A partir de Symfony 4.2, puede inyectar Doctrine\ORM\EntityManagerInterface en Command.

    – vim

    31 de enero de 2019 a las 11:54

Sé que la respuesta de Matt resolvió la pregunta, pero si tiene más de un administrador de entidades, puede usar esto:

Hacer modelo.xml con:

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

Luego cargue este archivo en su extensión DI

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

Entonces puedes usarlo en cualquier lugar. En el comando de la consola, ejecute:

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

y no olvides al final de:

$em->flush();

Ahora puede usarlo como argumento en otro servicio en services.yml:

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

Espero que esto ayude a alguien.

¿Ha sido útil esta solución?