iT邦幫忙

2021 iThome 鐵人賽

DAY 27
0
Modern Web

Laravel 實務筆記系列 第 27

信件樣式與內容編輯

Markdown

先看看目前剛新建好的 Markdown 信件。

@component('mail::message')
# Introduction

The body of your message.

@component('mail::custom.blueButton', ['url' => ''])
Button Text
@endcomponent

Thanks,<br>
{{ config('app.name') }}
@endcomponent

Laravel 的 Markdown 信件結合了 Blade 的元件功能,盡可能用元件編排可以讓主要的信件內容更聚焦。

舉目前的架構來說,上面的 Markdown 信件首先用了 @component('mail::message') 引入 message 這個元件,而 message 又引入了 layout。

在 message 這個元件 (路徑:resources/views/vendor/mail/html/message.blade.php) 中可以找到如下的程式碼。

resources/views/vendor/mail/html/message.blade.php
{{ $slot }}

這個就像 React 裡的 children 一樣, @component 到 @endcomponent 間的內容會被置入這裡。

而 message 本身又被置入 layout 元件中,不過這邊不太一樣

resources/views/vendor/mail/html/layout.blade.php

{{ Illuminate\Mail\Markdown::parse($slot) }}

$slot 被放在 Markdown::parse 中,所以主要的 Markdown 編譯其實在這。

另外在 layout 中可以看到 {{ $header ?? '' }}{{ $subcopy ?? '' }}{{ $footer ?? '' }} ,這是 Blade 的功能,可以定義多個不同的 slot 。

對應 message 中的內容,用 @slot 指定要將內容放入哪個 $slot:

resources/views/vendor/mail/html/message.blade.php

@slot('header')
@component('mail::header', ['url' => config('app.url')])
{{ config('app.name') }}
@endcomponent
@endslot

自訂元件

先看信件引入元件的語法

@component('mail::message')

在編譯 Markdown 的時候,Laravel 會到 resources/views/vendor/mail
底下找對應 mail:: 後面字串的原件進行編譯,不過可以看到 mail 目錄底下其實沒有元件,而是兩個資料夾 html 跟 text 。

這是因為產生信件時會同時產生 html 信件內容與純文字信件內容,所以兩個目錄下都需要要有對應的元件以供編譯。

舉例來說,如果想要新增一個 dangerButton 元件的話,在 html 跟 text 底下都要建一個

當然兩者的內容不會相同,在 text 目錄下的元件只需要純文字。

建好後就可以用來建構信件啦,引入的方法跟其他元件一樣

@component('mail::blueButton', ['url' => ''])
Button Text
@endcomponent

不過全部的元件塞在同一個資料夾遲早會亂成一團,所以希望可以分資料夾放置元件。

這時候只要在引用時用.區分目錄就好。

@component('mail::custom.blueButton', ['url' => ''])
Button Text
@endcomponent

剩下就是編寫元件內容啦,使用的是 blade 語法,除了可以穿插 Laravel 的變數跟功能外跟 html 差不多,關於穿插 Laravel 變數跟功能的部分後面的段落再說。

更改樣式

目前信件尚在參照預設的 default 樣式,還在 vendor 套件目錄底下,如果要自行更改的話,要先將樣式發佈到專案目錄底下。

sail artisan vendor:publish --tag=laravel-mail

這樣就可以在 resources 目錄中找到 default 的樣式跟 layout ,可以從這裡編輯。

當然我們可以直接改 default.css ,不過也可以建立複數個 css 再另外引入。

複製一份 default 並將其改名為 custom.css ,然後改信件內文的背景色為米色

resources/views/vendor/mail/html/themes/custom.css

.inner-body {
    -premailer-cellpadding: 0;
    -premailer-cellspacing: 0;
    -premailer-width: 570px;
    background-color: wheat;  /*改米色*/
    border-color: #e8e5ef;
    border-radius: 2px;
    border-width: 1px;
    box-shadow: 0 2px 0 rgba(0, 0, 150, 0.025), 2px 4px 0 rgba(0, 0, 150, 0.015);
    margin: 0 auto;
    padding: 0;
    width: 570px;
}

接著在產生信件前指定樣式

app/Mail/CustomVerifyMail.php

<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class CustomVerifyMail extends Mailable
{
    use Queueable, SerializesModels;

    public function __construct()
    {
        //
    }
    
    public function build()
    { 
+       $this->theme = 'custom';  
        return $this->markdown('mail.custom.verify');
    }
}

這邊指定的樣式必須放在 resources/views/vendor/mail/html/themes 目錄下才能被參照到。

要在元件內引用 class 的話跟 html 相同,比較特別的是可以用 php 語法動態變更 class 。

<a href="{{ $url }}" class="button button-{{ $color ?? 'primary' }}" target="_blank" rel="noopener">{{ $slot }}</a>

更改內容

撰寫信件內容

如果是最後會被 Illuminate\Mail\Markdown::parse() 編譯的內容,就可以直接用 Markdown 語法書寫。

# Introduction

也可以穿插 Blade 語法

Thanks,<br>

如果需要 php 或 Laravel 功能編譯字串、引入環境變數或進行 i18n 翻譯的話,要用 {{ }} 框起來。

{{ strtoupper('Hello') }}

{{ config('app.name') }}

{{ __('i18n.translation') }}

比較特別的是如果字串裡有 \n 的話,一般的引入會被視為普通字元

{{ "Hello,\nWorld" }}

這時候需要換成一個特別的函式幫忙把 \n 通通換成<br/>

恩...,換是換好了....

換完的 <br/> 一樣會被視為普通字元,這時候要換個框{!! !!}來告訴 Blade 這串字要原原本本本的帶入模板,好讓 <br/> 生效。

{!! nl2br("Hello,\nWorld") !!}

這樣就會成功換行了


上一篇
信件
下一篇
通知
系列文
Laravel 實務筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言