先看看目前剛新建好的 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") !!}
這樣就會成功換行了