Kar*_*ski 30 email render symfony twig
我正在研究用symfony2编写的应用程序,我希望在一些动作/事件之后发送电子邮件...问题是,用户可以定义类似"电子邮件模板"的东西,它像db一样存储在db中,例如:"这个是来自{{user}}的一些电子邮件,我需要从该模板呈现电子邮件的正文...在此链接的symfony文档中:http://symfony.com/doc/2.0/cookbook/email.html#sending -emails用于渲染的方法是$ this-> renderView,它希望引用文件为"bundle:controller:file.html.twig",但我的模板是数据库作为简单字符串...我该如何渲染它?
Ata*_*tan 31
Twig_Loader_String已弃用,无论如何总是设计用于内部使用.强烈建议不要使用此加载程序.
从API文档:
永远不要使用这个装载机.它仅存在于Twig内部用途.当使用带有缓存机制的加载器时,您应该知道每次模板内容"更改"时生成新的缓存键(缓存键是模板的源代码).如果您不希望看到缓存失去控制,则需要自己清理旧的缓存文件.
另请查看此问题:https://github.com/symfony/symfony/issues/10865
我知道从String源加载模板的最佳方法是:
$template = $this->get('twig')->createTemplate('Hello {{ name }}');
$template->render(array('name'=>'World'));
Run Code Online (Sandbox Code Playgroud)
如下所述:http://twig.sensiolabs.org/doc/recipes.html#loading-a-template-from-a-string
{{ include(template_from_string("Hello {{ name }}", {'name' : 'Peter'})) }}
Run Code Online (Sandbox Code Playgroud)
如下所述:http://twig.sensiolabs.org/doc/functions/template_from_string.html
请注意,'template_from_string' - 函数默认情况下不可用,需要加载.在symfony中,您可以通过添加新服务来完成此操作:
# services.yml
services:
appbundle.twig.extension.string:
class: Twig_Extension_StringLoader
tags:
- { name: 'twig.extension' }
Run Code Online (Sandbox Code Playgroud)
ada*_*vea 20
这应该工作.将"Hello {{name}}"替换为模板文本,并使用您需要的任何变量填充传递给render函数的数组.
$env = new \Twig_Environment(new \Twig_Loader_String());
echo $env->render(
"Hello {{ name }}",
array("name" => "World")
);
Run Code Online (Sandbox Code Playgroud)
Phi*_*ber 10
克隆本机twig
服务并使用本机twig字符串加载器替换文件系统加载器:
<service id="my.twigstring" class="%twig.class%">
<argument type="service" id="my.twigstring.loader" />
<argument>%twig.options%</argument>
</service>
<service id="my.twigstring.loader" class="Twig_Loader_String"></service>
Run Code Online (Sandbox Code Playgroud)
控制器内的用法示例:
$this->get('my.twigstring')->render('Hello {{ name }}', array('name' => 'Fabien'));
Run Code Online (Sandbox Code Playgroud)
这是一个适用于Symfony 4的解决方案(也可能是旧版本,虽然我还没有测试过),并允许您使用存储在数据库中的模板,就像使用文件系统中的模板一样.
这个答案假设您正在使用Doctrine,但如果您正在使用另一个数据库库,则相对容易适应.
这是一个使用注释的示例类,但您可以使用您已经使用的任何配置方法.
SRC /实体/的template.php
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Table(name="templates")
* @ORM\Entity
*/
class Template
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var string
*
* @ORM\Column(type="string", nullable=false)
*/
private $filename;
/**
* @var string
*
* @ORM\Column(type="text", nullable=false)
*/
private $source;
/**
* @var \DateTime
*
* @ORM\Column(type="datetime", nullable=false)
*/
private $last_updated;
}
Run Code Online (Sandbox Code Playgroud)
最基本的字段是filename
和source
,但是包含它是一个非常好的主意,last_updated
否则你将失去缓存的好处.
SRC /枝条/装载机/ DatabaseLoader.php
<?php
namespace App\Twig;
use App\Entity\Template;
use Doctrine\ORM\EntityManagerInterface;
use Twig_Error_Loader;
use Twig_LoaderInterface;
use Twig_Source;
class DatabaseLoader implements Twig_LoaderInterface
{
protected $repo;
public function __construct(EntityManagerInterface $em)
{
$this->repo = $em->getRepository(Template::class);
}
public function getSourceContext($name)
{
if (false === $template = $this->getTemplate($name)) {
throw new Twig_Error_Loader(sprintf('Template "%s" does not exist.', $name));
}
return new Twig_Source($template->getSource(), $name);
}
public function exists($name)
{
return (bool)$this->getTemplate($name);
}
public function getCacheKey($name)
{
return $name;
}
public function isFresh($name, $time)
{
if (false === $template = $this->getTemplate($name)) {
return false;
}
return $template->getLastUpdated()->getTimestamp() <= $time;
}
/**
* @param $name
* @return Template|null
*/
protected function getTemplate($name)
{
return $this->repo->findOneBy(['filename' => $name]);
}
}
Run Code Online (Sandbox Code Playgroud)
这堂课比较简单.getTemplate
从数据库中查找模板文件名,其余方法用于getTemplate
实现Twig所需的接口.
配置/ services.yaml
services:
App\Twig\Loader\DatabaseLoader:
tags:
- { name: twig.loader }
Run Code Online (Sandbox Code Playgroud)
现在,您可以像使用文件系统模板一样使用数据库模板.
从控制器渲染:
return $this->render('home.html.twig');
包括来自另一个Twig模板(可以在数据库或文件系统中):
{{ include('welcome.html.twig') }}
渲染到字符串(其中$twig
是一个实例Twig\Environment
)
$html = $twig->render('email.html.twig')
在每种情况下,Twig将首先检查数据库.如果getTemplate
在你的DatabaseLoader
返回null中,Twig将检查文件系统.如果模板在数据库或文件系统中不可用,Twig将抛出一个Twig_Error_Loader
.
最好的方法是使用template_from_string
树枝功能.
{{ include(template_from_string("Hello {{ name }}")) }}
{{ include(template_from_string(page.template)) }}
Run Code Online (Sandbox Code Playgroud)
看看为什么在stof这个github问题上使用或出于那个目的不是一个好主意.Twig_Loader_Chain
Twig_Loader_String