Este foro ya no está activo, así que no puedes publicar nuevas preguntas ni responder a las preguntas existentes.

Controlador como servicio en Symfony más Doctrine

17 de abril de 2016

Hola. Siguiendo el tutorial de cómo definir un controlador como servicio me encuentro con este error:

services:
    fos_user.doctrine_registry:
        alias: doctrine
 
    fichada:
        class: AppBundle\FichadaBundle\Controller\FichadaController

Probé las dos formas de llamar al controlador import desde este controller:

public function importarfichadaAction() {
       // $fichada = $this->get('fichada');
       // $fichada->importAction();
        $this->forward('fichada:importAction');
    }

De las dos formas me da el mismo error al intentar cargar el entity manager en el otro controlador

Error: Call to a member function has() on null

El error sale justo al tratar de correr esta línea:

$em = $this->getDoctrine()->getManager();

Respuestas

#1

Antes de responder a tu pregunta, me gustaría decirte que no se recomienda el uso de los controladores como servicios. El propio creador de Symfony dice que es una muy mala práctica y que nunca habría que usar controladores como servicios.

Respondiendo a tu pregunta, uno de los muchos problemas que te vas a encontrar al usar controladores como servicios es que no tienes acceso preconfigurado a ninguno de los servicios que utilizas dentro del controlador.

Cuando haces $this->getDoctrine() en realidad estás obteniendo el servicio doctrine del contenedor de servicios de Symfony. Antes de obtenerlo se hace un $this->has('doctrine') y esa es la línea que te está fallando. Al usar el controlador como servicio, no tienes acceso ni a Doctrine ni al contenedor de servicios, por lo que el $this->has(...) falla.

La solución consiste en inyectar a mano todos los servicios que vayas a necesitar, como por ejemplo doctrine. Así que en la definición de tu controlador-servicio tendrías que hacer lo siguiente:

services:
    fos_user.doctrine_registry:
        alias: doctrine

    fichada:
        class: AppBundle\FichadaBundle\Controller\FichadaController
        arguments: ['@doctrine']

Después tienes que añadir un __construct() en el controlador para obtener el servicio doctrine que has inyectado. Como ves, los controladores-servicio te hacen trabajar mucho más y sus supuestas ventajas son muy discutibles. Si puedes, olvídate de ellos para siempre.

@javiereguiluz

18 abril 2016, 8:23
#2

Gracias por la respuesta, buscando en google recomendaban usar servicios y otros no...

lo que intentaba hacer era reutilizar un método de un controlador en otro para no duplicar código, lo que puedo hacer es pasar esa lógica al modelo y reutilizarlo de ahí.

Esa seria la forma correcta de reutilizar código para no usar servicios ?

Saludos

@xub

18 abril 2016, 13:53
#3

Como dices, puedes pasar esa lógica al modelo. También podrías hacer un servicio sencillo y específico para esa lógica y que sea independiente del modelo y de los controladores.

@javiereguiluz

18 abril 2016, 14:59
#4

Hola,

En mi opinión, yo recomendaría hacer la lógica específica en una clase independiente y esa clase es la que convertirías en un servicio, ya teniendo eso inyectar ese servicio en los controladores.

Analizándolo bien, creo que es lo mismo que recomienda Javier.

Saludos

@miguelplazasr

21 abril 2016, 7:02