2011-09-22 15 views
38

Quiero algunos comandos de terminal para mi aplicación Symfony2. He pasado por el example in the cookbook, pero no he podido averiguar cómo acceder a mi configuración, mi administrador de entidades y mis entidades aquí. En el constructor, consigo el recipiente (que me debe dar acceso a la configuración y entidades) usando¿Cómo usar mis Entidades y Administradores de Entidades en el Comando de Consola Symfony 2?

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

Pero esta llamada genera un error:

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

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

$this->getApplication() 

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

+0

estoy teniendo el mismo error cuando (y yo intento de acceder a 'getContainer() 'dentro de' MyCommand-> execute() 'pero aún recibe el mismo error fatal. my' 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? –

Respuesta

71

Creo que no debería recuperar el contenedor en el constructor directamente. En su lugar, recupérelo en el método configure o en el método execute. En mi caso, obtengo el administrador de mi entidad al comienzo del método execute 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 instanciación del objeto de aplicación aún no ha terminado cuando se está llamando getContainer en su constructor que dan lugar a este error. El error proviene de la getContainer método tyring hacer:

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

Desde getApplication aún no es un objeto, se obtiene un diciendo que el error o se llama a un método getKernel en un no-objeto.

Actualización: En la versión más reciente de Symfony, getEntityManager ha quedado en desuso (y podría haber sido eliminado del todo por ahora). Use $entityManager = $this->getContainer()->get('doctrine')->getManager(); en su lugar. Gracias a Chausser para señalarlo.

Actualización 2: En Symfony 4, el auto-cableado se puede utilizar para reducir la cantidad de código necesario.

Crea un __constructor con una variable EntityManagerInterface. Esta variable estará accesible en el resto de tus comandos. Esto sigue el esquema de Inyección de Dependencia de auto-cableado.

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 para proporcionar el comentario y el código de ejemplo.

+0

Tenía esa idea de o ut ya, pero como nuevo, no pude responder mi propia pregunta. No puede obtener el contenedor en el constructor, ya que aún no existe. Todo funciona muy bien si recuperas el contenedor en el método de ejecución. Después de eso, tiene acceso a sus Entidades de la manera habitual: $ myEntities = $ em-> getRepository ('Acme \ DemoBundle: Myentity') -> findAll(); –

+10

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

+1

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

4

Yo sé que la respuesta de Matt resuelto la cuestión, pero si usted ha más de un gestor de la entidad, se puede utilizar este:

Hacer model.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> 

A continuación, cargue este archivo en su extensión DI

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

Entonces puede usarlo en cualquier lugar.En comando de consola ejecutar:

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

y no se olvide a fin de:

$em->flush(); 

Ahora puede utilizar como un argumento a otro servicio en services.yml:

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

Espero que esto ayude a alguien.

8

extiende su clase de comando desde ContainerAwareCommand en lugar de Comando

class YourCmdCommand extends ContainerAwareCommand 

y obtener gestor de la entidad así:

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