我正在开发用 symfony2 编写的应用程序,我想在某些操作/事件后发送电子邮件...问题是,用户可以定义类似“电子邮件模板”之类的内容,这些模板像简单的字符串一样存储在数据库中,例如: “这是来自 {{ user }} 的一些电子邮件”,我需要渲染该电子邮件的正文,该电子邮件应使用该模板...
在 symfony 文档中,此链接: https://symfony.com/doc/2.0/cookbook/email/email .html#sending-emails 渲染视图的方法是 $this->renderView 并且它需要文件的路径,例如“bundle:controller:file.html.twig”,但我的模板是来自数据库的简单字符串...
我该如何渲染它?
I'm working on application written in symfony2 and I want to send email after some action/event... the problem is, that the users can define something like "email templates" which are stores in db like simple string, for example: "This is some email from {{ user }}" and I need to render body for that email which should use that template...
In symfony documentation from this link: https://symfony.com/doc/2.0/cookbook/email/email.html#sending-emails the method for render view is $this->renderView and it expects the path to file such as "bundle:controller:file.html.twig", but my template is simple string from database...
How can I render it?
发布评论
评论(11)
Twig_Loader_String 已被弃用,并且始终设计为供内部使用。强烈建议不要使用此加载程序。
来自 API 文档:
另请查看此问题:https://github.com/symfony/symfony/issues/10865
我知道从字符串源加载模板的最佳方法是:
从控制器:
如此处所述:http://twig.sensiolabs.org/doc/recipes .html#loading-a-template-from-a-string
来自树枝模板:
如下所述:http://twig.sensiolabs.org/doc/functions/template_from_string.html
请注意,“template_from_string”函数默认不可用,需要加载。在 symfony 中,您可以通过添加新服务来做到这一点:
Twig_Loader_String is deprecated and was always designed for internal use anyway. The usage of this loader is strongly discouraged.
From the API doc:
Also check out this issue: https://github.com/symfony/symfony/issues/10865
The best way I know to load a template from a String source are:
From a controller:
as described here: http://twig.sensiolabs.org/doc/recipes.html#loading-a-template-from-a-string
From a twig template:
as described here: http://twig.sensiolabs.org/doc/functions/template_from_string.html
Note, that the 'template_from_string' - function is not available by default and needs to be loaded. In symfony you would do this by adding a new service:
这应该有效。将“Hello {{ name }}”替换为模板文本,并使用您需要的任何变量填充传递到渲染函数的数组。
This should work. Replace "Hello {{ name }}" with your template text, and fill the array that is passed into the render function with any variables that you need.
这是一个适用于 Symfony 4(也可能适用于旧版本,尽管我还没有测试过)的解决方案,并允许您使用存储在数据库中的模板,就像使用文件系统中的模板一样。
这个答案假设您使用的是 Doctrine,但如果您使用的是其他数据库,则相对容易适应。
创建模板实体
这是一个使用注释的示例类,但您可以使用已经使用的任何配置方法。
src/Entity/Template.php
最低限度的字段是
filename
和source
,但包含last_updated< 是一个非常好的主意/code> 否则你将失去缓存的好处。
创建DatabaseLoader类
src/Twig/Loader/DatabaseLoader.php
该类比较简单。
getTemplate
从数据库中查找模板文件名,其余方法使用getTemplate
来实现 Twig 需要的接口。将 DatabaseLoader 添加到您的服务配置
config/services.yaml
现在您可以像使用文件系统模板一样使用数据库模板。
从控制器渲染:
return $this->render('home.html.twig');
包括来自另一个 Twig 模板(其中可以在数据库或文件系统中):
{{ include('welcome.html.twig') }}
渲染为字符串(其中
$twig 是一个实例
Twig\Environment
)$html = $twig->render('email.html.twig')
在每种情况下,Twig 都会首先检查数据库。如果
DatabaseLoader
中的getTemplate
返回 null,Twig 将检查文件系统。如果模板在数据库或文件系统中不可用,Twig 将抛出Twig_Error_Loader
。Here's a solution that works with Symfony 4 (and possibly older versions as well, although I haven't tested it) and allows you to work with templates stored in the database the same way you would work with templates in the filesystem.
This answer assumes you're using Doctrine, but is relatively easy to adapt if you're using another database library.
Create the Template entity
This is an example class that uses annotations, but you can use whatever configuration method you're already using.
src/Entity/Template.php
The bare minimum fields are
filename
andsource
, but it's a very good idea to includelast_updated
or you'll lose the benefits of caching.Create a DatabaseLoader class
src/Twig/Loader/DatabaseLoader.php
The class is relatively simple.
getTemplate
looks up the template filename from the database, and the rest of the methods usegetTemplate
to implement the interface that Twig needs.Add the DatabaseLoader to your service config
config/services.yaml
Now you can use your database templates in the same way as filesystem templates.
Rendering from a controller:
return $this->render('home.html.twig');
Including from another Twig template (which can be in the database or filesystem):
{{ include('welcome.html.twig') }}
Rendering to a string (where
$twig
is an instance ofTwig\Environment
)$html = $twig->render('email.html.twig')
In each of these cases, Twig will check the database first. If
getTemplate
in yourDatabaseLoader
returns null, Twig will then check the filesystem. If the template isn't available in the database or the filesystem, Twig will throw aTwig_Error_Loader
.克隆本机
twig
服务并用本机 twig 字符串加载器替换文件系统加载器:控制器内的使用示例:
Clone the native
twig
service and replace the filesystem loader with the native twig string loader:Usage example from within a controller:
最好的方法是使用 template_from_string twig 函数。
请参阅
template_from_string
的文档了解为什么它不 最好在 Twig_Loader_Chain 或
Twig_Loader_String
来实现此目的href="https://github.com/symfony/symfony/issues/10865">stof 的这个 github 问题。The best way to do it is to use
template_from_string
twig function.See documentation of
template_from_string
See why it is not a good idea to use
Twig_Loader_Chain
orTwig_Loader_String
for that purpose on this github issue by stof.从 Twig 1.10 开始,Twig 引擎不支持渲染字符串。但是有一个可用的捆绑包添加了此行为,称为 TwigstringBundle。
它添加了
$this->get('twigstring')
服务,您可以使用它来渲染字符串。(截至 2019 年 9 月,Twig 的当前版本为 2.X,版本 3 即将推出;因此这仅适用于非常旧的 Twig 版本)。
As of Twig 1.10, the Twig Engine doesn't support rendering strings. But there is a bundle available which adds this behavior called TwigstringBundle.
It adds the
$this->get('twigstring')
service wich you can use to render your strings.(As September '19, the current version of Twig is 2.X, and version 3 is around the corner; so this is only applies to very old versions of Twig).
这对我有用:
https://twig.symfony.com/doc/2 .x/api.html
This work for me:
https://twig.symfony.com/doc/2.x/api.html
仅供参考,此功能建议为建议。 com/fabpot/Twig/commit/bf3802bc6e5199b4d065b383caf3fe81203b713d" rel="nofollow">添加从 1.11.0 开始,Twig 的核心,但需要激活由开发商。
FYI, This feature was suggested to be added in the core of Twig as of 1.11.0, but will be needed to be activated by the developper.
在 Symfony 2.2 中,您可以使用 Twig_Chain_Loader
如何注册另一个(自定义)Twig Symfony2 环境中的加载器?
With Symfony 2.2 you can use the Twig_Chain_Loader
How to register another (custom) Twig loader in Symfony2 environment?
我最近必须实现一个由多方使用的 CMS,其中每一方都可以完全自定义他们的模板。为了实现这一点,我实现了一个自定义的 Twig Loader。
最困难的部分是为模板制定一个命名约定,保证不与任何现有模板重叠,例如
!AppBundle:template.html.twig
。如果模板未自定义,则必须加载模板
AppBundle:template.html.twig
作为后备模板。然而,这对于 Chain Loader (AFAIK) 来说是不可能的,因为模板名称无法修改。因此,我必须将默认加载器(即加载器链)注入到我的加载器中,并使用它来加载后备模板。
另一种解决方案是将请求堆栈或会话传递给模板加载器,从而可以自动检测组织,但这很困难,因为安全组件依赖于模板子系统,从而导致循环依赖问题。
I recently had to implement a CMS used by multiple parties where each party could completely customize their templates. To achieve this I implemented a custom Twig Loader.
The most difficult part was coming up with a naming convention for the templates guaranteed not to overlap with any existing templates, for example
<organisation_slug>!AppBundle:template.html.twig
.In case the template was not customised, the template
AppBundle:template.html.twig
would have to be loaded as fallback template.However, this is not possible with the Chain Loader (AFAIK) because there the template name cannot be modified. Therefore I had to inject the default loader (i.e. the loader chain) into my loader and use it to load the fallback template.
Another solution would be to pass the request stack or the session to the template loader, making it possible to automatically detect the organisation, but this is difficult because the security component depends on the templating subsystem, causing circular dependency issues.