2012-01-11 71 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