将twig渲染为html文件,避免重复代码添加变量

Posted

技术标签:

【中文标题】将twig渲染为html文件,避免重复代码添加变量【英文标题】:Rendering twig to html file, avoid duplicate code to add a variable 【发布时间】:2021-12-08 21:43:24 【问题描述】:

由于我有重复的代码,有没有更好的方法来做到这一点?

我有一个电子邮件分支,其中包含在浏览器中打开电子邮件的链接。

目前我必须渲染模板两次。

一次获取内容并将其保存到 S3 中的 html 文件。第二次在发送的邮件中添加S3链接,方便在线查看邮件。

$emailBody = $this->twig->render('EmailRo/incomplete-listing-moderation/accept-incomplete-listing.email.twig', [
    'user' => $admin,
    'avatar' => AmazonS3Service::URL_PREFIX.$admin->getPhoto(),
    's3html' => '',
]);
$s3 = $this->container->get('s3storage');

$fileName = rand(1000, 999999) . time() . '.html';
file_put_contents($fileName, $emailBody);

$file = $this->container->get('request_stack')->getCurrentRequest()->server->get('DOCUMENT_ROOT').'/'.$fileName;

$s3->upload('users/' . $fileName,
    file_get_contents($file),
    mime_content_type($file));
$s3html = AmazonS3Service::URL_PREFIX . 'emails/' . $fileName;

$emailBody = $this->twig->render('EmailRo/incomplete-listing-moderation/accept-incomplete-listing.email.twig', [
    'user' => $admin,
    'avatar' => AmazonS3Service::URL_PREFIX.$admin->getPhoto(),
    's3html' => $s3html,
]);

在树枝上我是这样渲染的

% if s3html %
<a href=" s3html " style="text-decoration: none;"><span style="font-family:'Montserrat','Arial','Helvetica', sans-serif !important; font-weight: normal; font-size:13px; line-height: 15px; color: #27AAE1; font-weight: 400;">
Email not displayed correctly? Read the online version in your browser.
</span></a>
% endif %

【问题讨论】:

为什么不添加一个占位符,例如模板中的s3html 并使用str_replace 更改呈现的html?这样你只需要渲染一次并做两次str_replaces 【参考方案1】:

IMO,我认为你可能为了一点好处而把事情复杂化了。

两次渲染模板对性能没有太大影响,无论如何都会被缓存。我想这个问题主要是因为代码“更整洁”,没有不必要的重复,这很好,但不是一个重要的问题。

但如果您想避免为同一个模板调用两次render()...

只要有一个不包含“在浏览器上读取”位的模板,然后只渲染它。

对于电子邮件版本,请添加“在浏览器上阅读”链接。

$htmlBody = $this->twig->render('EmailRo/incomplete-listing-moderation/accept-incomplete-listing.email.twig', [
    'user' => $admin,
    'avatar' => AmazonS3Service::URL_PREFIX.$admin->getPhoto(),
]);

// all the S3 logic, which returns an URL
$emailUrl = storeEmailHtmlSomewhere($emailBody);

$emailBody = <<< HTML
<a href="$emailUrl" style="text-decoration: none;"><span style="font-family:'Montserrat','Arial','Helvetica', sans-serif !important; font-weight: normal; font-size:13px; line-height: 15px; color: #27AAE1; font-weight: 400;">
Email not displayed correctly? Read the online version in your browser.
</span></a>

HTML;

// do what you need with that email
sendEmail($emailHeader . $emailBody);

如果需要,您可以简单地将这两个部分存储在不同的模板中,并在发送电子邮件时连接结果。


$emailHtmlBody = $this->twig->render('EmailRo/incomplete-listing-moderation/accept-incomplete-listing.email.twig', [
    'user' => $admin,
    'avatar' => AmazonS3Service::URL_PREFIX.$admin->getPhoto(),
]);

// all the S3 logic, which returns an URL
$emailUrl = storeEmailHtmlSomewhere($emailBody);

$emailHtmlHead = $this->twig->render('EmailRo/header-with-link.email.twig', [
    'emailUrl' => $emailUrl
]);

sendEmail($emailHtmlHead . $emailHtmlBody);

【讨论】:

【参考方案2】:

您可以使用 3 个模板而不是一个模板:类似于 base_mail.html.twig 的主要邮件内容,以及两个瘦包装器,例如 email_s3.html.twigemail.html.twig,您可以在其中将基本邮件原始 HTML 作为参数提供。

这会在控制器中给出类似的东西(未经测试,抱歉错别字):

$emailBase = $this->twig->render('base_mail.html.twig', [
    'user'   => $admin,
    'avatar' => AmazonS3Service::URL_PREFIX.$admin->getPhoto(),
]);

$emailBodyS3 = $this->twig->render('email_s3.html.twig', [
    'base'   => $emailBase,
    's3html' => /* ... */,
]);

// Handle $emailBodyS3 with S3

$emailBody = $this->twig->render('email.html.twig', [
    'base' => $emailBase,
]);

// Send the email with $emailBody

薄包装看起来像这样:

email.html.twig

<div> base | raw </div>

email_s3.html.twig

<div>
     base | raw 
    <a href=" s3html " style="text-decoration: none;"><span style="font-family:'Montserrat','Arial','Helvetica', sans-serif !important; font-weight: normal; font-size:13px; line-height: 15px; color: #27AAE1; font-weight: 400;">
        Email not displayed correctly? Read the online version in your browser.
    </span></a>
</div>

【讨论】:

我的意思是,你有点从 2 个渲染到 3 个渲染。无论如何,这太复杂了,如果 OP 想要这样的方法,那么我建议创建一个基本模板,其中包含一个空块 s3html 和第二个模板,该模板扩展主模板并使用 URLs3html 块/跨度> @DarkBee 我的方法避免了两次渲染可能很长的模板(电子邮件“基础”)。您基于块覆盖的建议仍然会两次呈现这个“可能很长的模板”。我不认为使用 3 个渲染而不是 2 个渲染会影响性能,尤其是对于像上面的包装器这样的小模板。 我不认为渲染模板会成为瓶颈,但我想有一天应该对这一点进行基准测试

以上是关于将twig渲染为html文件,避免重复代码添加变量的主要内容,如果未能解决你的问题,请参考以下文章

在Twig中插入html代码[重复]

如何将 TWIG 输出渲染到变量以供以后使用(symfony2)?

外部 JS 文件中的 Twig 变量

PHP将html放在树枝变量中?

Twig 模板渲染前端基本使用

Symfony Twig渲染