2012-01-11 20 views
8

Estoy tratando de enviar un correo electrónico desde ContainerAwareCommand en Symfony2. Pero consigo esta excepción cuando la plantilla de correo electrónico es rendir por:Symfony2 Templating sin solicitud

$body = $this->templating->render($template, $data); 

Excepción:

("You cannot create a service ("templating.helper.assets") of an inactive scope ("request").") 

que encontré en github que esta ayuda necesita el objeto de solicitud. ¿Alguien sabe cómo puedo instanciar el objeto Solicitud?

Respuesta

1

Puesto que usted no tiene una solicitud, es necesario llamar al servicio de plantillas directamente como esto:

$this->container->get('templating')->render($template, $data); 
+3

Esto no resuelve el problema. A medida que se utiliza el activo (probablemente no sea directamente visible en sus plantillas), debe tener un servicio RequestContext de alguna manera. – BetaRide

+0

Recibo el mismo error pero esta solución no resuelve el problema.http: //stackoverflow.com/questions/17942738/erro-you-cannot-create-a-service-templating-helper-assets-of-an-inactive -sco – vishal

+0

Esta solución funcionó para mí cuando la publiqué. No discutiré por un minuto que no funciona con las versiones más nuevas de Symfony de las que tenía en ese momento. Cuando se trata de salir del camino trillado, Symfony es un objetivo móvil. No he tenido tiempo para codificar por un tiempo, así que realmente no puedo investigar en este momento, pero puedes probar la solución de BetaRide. – Matthew

19

Es necesario configurar el contenedor en el alcance adecuado y darle una petición (falso). En la mayoría de los casos esto será suficiente:

//before you render template add bellow code 
$this->getContainer()->enterScope('request'); 
$this->getContainer()->set('request', new Request(), 'request'); 

La historia completa es here. Si desea conocer los detalles, lea esto issue on github.

+1

FYI: Esto fue obsoleto y se elimina en Symfony 3, y se reemplazó por "setScope" en el nivel de servicio: https://github.com/symfony/symfony/blob/master/UPGRADE-3.0.md#dependencyinjection – Rvanlaak

4

El problema surge porque utiliza la función asset() en su plantilla.

Por defecto, activo() se basa en Solicitud servicio para generar URLs a sus activos (lo que necesita saber cuál es la ruta de la base a su sitio web o lo que es el nombre de dominio si utiliza las URL de elementos absolutos , por ejemplo).

Pero cuando ejecuta su aplicación desde la línea de comandos no hay Solicitud.

Una forma de solucionar este problema es definir explícitamente URL base a sus activos en config.yml así:

framework: 
    templating: 
    assets_base_urls: { http: ["http://yoursite.com"], ssl: ["http://yoursite.com"] } 

Es importante definir tanto http y ssl, ya que si se omite uno de ellos activo() seguirá dependiendo del servicio de solicitud.

El (posible) inconveniente es que todas las URL de los activos ahora serán absolutas.

+0

Gracias para su explicación clara y su solución, ¡funciona perfectamente! Intenté antes de esta solución http://symfony.com/doc/current/cookbook/console/sending_emails.html pero sin éxito –

+0

Con esta solución, todos los activos usan una url absoluta. A veces puede ser un problema. – ke20

+0

Esta solución solo funciona si http url y ssl url son exactamente iguales. –

1

La respuesta de BetaRide me puso en el camino correcto, pero eso no fue suficiente. Luego se quejaba: "No se puede generar una URL para la ruta especificada" "ya que dicha ruta no existe".

para crear una solicitud válida He modificado para solicitar la raíz del proyecto, así: (? Raíz asegurado)

$request = new Request(); 
$request->create('/'); 
$this->container->enterScope('request'); 
$this->container->set('request', $request, 'request'); 

puede que tenga que llamar a una ruta diferente, raíz trabajó para mí solo multa.

Symfony2 Docs

Bono además:

que tenía que hacer tanto de plantillas/enrutamiento de CLI a través de Symfony2 ordena que he actualizado el método initializeContainer() en AppKernel. Se crea una ruta a la raíz del sitio, establece el contexto router y falsificaciones de un inicio de sesión de usuario:

protected function initializeContainer() 
{ 
    parent::initializeContainer(); 
    if (PHP_SAPI == 'cli') { 

     $container = $this->getContainer(); 

     /** 
     * Fake request to home page for cli router. 
     * Need to set router base url to request uri because when request object 
     * is created it perceives the "/portal" part as path info only, not base 
     * url and thus router will not include it in the generated url's. 
     */ 
     $request = Request::create($container->getParameter('domain')); 
     $container->enterScope('request'); 
     $container->set('request', $request, 'request'); 
     $context = new RequestContext(); 
     $context->fromRequest($request); 
     $container->get('router')->setContext($context); 
     $container->get('router')->getContext()->setBaseUrl($request->getRequestUri()); 

     /** 
     * Fake admin user login for cli. Try database read, 
     * gracefully print error message if failed and continue. 
     * Continue mainly for doctrine:fixture:load when db still empty. 
     */ 
     try { 
      $user = $container->get('fos_user.user_manager')->findUserByUsername('admin'); 
      if ($user !== null) { 
       $token = $token = new UsernamePasswordToken($user, null, 'main', $user->getRoles()); 
       $this->getContainer()->get('security.token_storage')->setToken($token); 
      } 
     } catch (\Exception $e) { 
      echo "Fake Admin user login failed.\n"; 
     } 
    } 
} 

puede que no necesite la última $container->get('router')->getContext()->setBaseUrl($request->getRequestUri()); parte, pero tenía que hacerlo porque mi raíz del sitio estaba en dominio .com/siteroot/y el enrutador fue stripping/siteroot/away para la generación de url.

+0

FYI: Esto fue obsoleto y se elimina en Symfony 3, y se reemplazó por "setScope" en el nivel de servicio: https://github.com/symfony/symfony/blob/master/UPGRADE-3.0.md#dependencyinjection – Rvanlaak

Cuestiones relacionadas