这是一个适用于 Symfony 4(也可能是旧版本,虽然我没有测试过)的解决方案,它允许您使用存储在数据库中的模板,就像使用文件系统中的模板一样。
此答案假设您使用的是 Doctrine,但如果您使用的是另一个数据库库,则相对容易适应。
创建模板实体
这是一个使用注解的示例类,但您可以使用您已经在使用的任何配置方法。
src/Entity/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;
}
最少的字段是filename 和source,但最好包含last_updated,否则您将失去缓存的好处。
创建一个 DatabaseLoader 类
src/Twig/Loader/DatabaseLoader.php
<?php
namespace App\Twig\Loader;
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]);
}
}
类比较简单。 getTemplate从数据库中查找模板文件名,其余方法使用getTemplate实现Twig需要的接口。
将 DatabaseLoader 添加到您的服务配置中
config/services.yaml
services:
App\Twig\Loader\DatabaseLoader:
tags:
- { name: twig.loader }
现在您可以像使用文件系统模板一样使用数据库模板。
从控制器渲染:
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。