2012-01-11 82 views
8

我试图从Symfony2中的ContainerAwareCommand发送电子邮件。但是,我得到这个例外,当电子邮件模板呈现由:Symfony2无需请求的模板

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

异常

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

我在github上发现,这个辅助需要请求对象。任何人都知道我怎样才能实例化Request对象?

回答

1

既然你没有要求,你需要直接调用模板服务是这样的:

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

这并不能解决问题。由于使用logn作为资产(可能不能直接在您的模板中可见),它需要以某种方式提供RequestContext服务。 – BetaRide 2013-01-11 11:08:05

+0

我得到同样的错误,但此解决方案不能解决问题.http://stackoverflow.com/questions/17942738/erro-you-cannot-create-a-service-templating-helper-assets-of-an-inactive -sco – vishal 2013-07-30 09:22:32

+0

当我发布它时,此解决方案适用于我。我不会争辩一下,它不适用于当时比较新版本的Symfony。谈到摆脱困境时,Symfony是一个动人的目标。我暂时没有时间编写代码,因此目前我无法调查,但是您可以尝试使用BetaRide的解决方案。 – Matthew 2013-08-05 00:24:24

19

您需要将容器设置到正确的范围,并给它一个(假的)请求。在大多数情况下,这将是不够的:

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

完整的故事是here。如果您想知道详情,请阅读issue on github

+1

供参考:这已被弃用,并在Symfony 3中被删除,并在服务级别上被替换为“setScope”:https://github.com/symfony/symfony/blob/master/UPGRADE-3.0.md#dependencyinjection – Rvanlaak 2016-12-13 14:06:14

4

问题出现是因为您在模板中使用了asset()函数。

默认情况下,资产()依靠请求服务生成URL到您的资产(它需要知道什么是基本路径到您的网站或什么是域名,如果你使用绝对资源网址, 例如)。

但是,当您从命令行运行应用程序时,没有请求

一种方式来解决这个问题它明确地定义基本URL到你的资产在config.yml这样的:

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

同时定义HTTPSSL这是非常重要的,因为如果你忽略其中一个资产()仍将依赖于请求服务。

(可能的)缺点是所有资产的URL现在都是绝对的。

+0

谢谢为了您的明确解释和您的解决方案,它完美的工作!我在此解决方案之前尝试过http://symfony.com/doc/current/cookbook/console/sending_emails.html但没有成功 – 2014-07-31 10:42:56

+0

使用此解决方案,所有资产都使用绝对网址。有时候这可能是一个问题。 – ke20 2015-03-17 14:28:06

+0

这个解决方案只在http url和ssl url完全相同时才起作用。 – 2017-03-28 10:42:21

1

正在关注BetaRide的回答让我走上了正轨,但那还不够。然后它抱怨说:“无法为指定的路由生成一个URL”,因为这样的路由不存在。“

要创建我已经修改了它要求项目的根像这样一个有效的请求:(?确保根)

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

您可能需要调用不同的路线,根工作对我来说只是精细。

Symfony2 Docs

奖金此外:

我不得不通过Symfony2中做了这么多的模板/路由中的CLI命令,我已经更新AppKernel的initializeContainer()方法。它创建到网站根目录的路径,设置路由器环境和假货用户登录:

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"; 
     } 
    } 
} 

你可能并不需要最后$container->get('router')->getContext()->setBaseUrl($request->getRequestUri());一部分,但我不得不这样做,因为我的网站根目录是在域.com/siteroot /和路由器正在剥离/ siteroot /为了生成网址。

+0

仅供参考:这已被弃用,并在Symfony 3中被删除,并在服务级别替换为“setScope”:https://github.com/symfony/symfony/blob/master/UPGRADE-3.0.md#dependencyinjection – Rvanlaak 2016-12-13 14:06:17