【问题标题】:Rendering twig to html file, avoid duplicate code to add a variable将twig渲染为html文件,避免重复代码添加变量
【发布时间】: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

标签: symfony twig


【解决方案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 个渲染会影响性能,尤其是对于像上面的包装器这样的小模板。
    • 我不认为渲染模板会成为瓶颈,但我想有一天应该对这一点进行基准测试
    猜你喜欢
    • 2014-03-07
    • 2015-03-02
    • 2021-05-08
    • 1970-01-01
    • 1970-01-01
    • 2021-08-04
    • 1970-01-01
    相关资源
    最近更新 更多