# Introduction
學習一個框架, Ray 的想法是, 在深入理解底層實作的原理之前, 應該先知道這個框架的 使用方法
; 先學習怎麼使用這個前人造的輪子, 再學習怎麼樣造一個輪子。
所以本篇文章重點在於細讀官方文件, 並將內容理解後以 Q&A 的方式記錄下來, 加速學習以及查詢。
# Driver / Transport Prerequisites
# Mailgun Driver
以下的 Laravel example code 的意思是?
- Example:
<?php
// config/services.php
'mailgun' => [
'domain' => env('MAILGUN_DOMAIN'),
'secret' => env('MAILGUN_SECRET'),
'endpoint' => env('MAILGUN_ENDPOINT', 'api.eu.mailgun.net'),
], - Answer:
設定 mail driver mailgun service, 如果不是使用 United States Mailgun region, 可以自定義在 endpoint
# Postmark Driver
以下的 Laravel example code 的意思是?
- Example:
<?php
composer require wildbit/swiftmailer-postmark - Answer:
使用 postmark mail driver 需要安裝的套件
以下的 Laravel example code 的意思是?
- Example:
<?php
// config/services.php
'postmark' => [
'token' => env('POSTMARK_TOKEN'),
], - Answer:
mail driver psotmark 的設定
以下的 Laravel example code 的意思是?
- Example:
<?php
// config/mail.php
'postmark' => [
'transport' => 'postmark',
'message_stream_id' => env('POSTMARK_MESSAGE_STREAM_ID'),
], - Answer:
可自定義 postmark mail driver 的 message_stream
# SES Driver
以下的 Laravel example code 的意思是?
- Example:
composer require aws/aws-sdk-php
- Answer:
要在 Laravel 使用 AWS 的服務, 如 s3, SES, SQS 時, 需安裝 AWS SDK
以下的 Laravel example code 的意思是?
- Example:
<?php
// config/services.php
'ses' => [
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
'options' => [
'ConfigurationSetName' => 'MyConfigurationSet',
'Tags' => [
['Name' => 'foo', 'Value' => 'bar'],
],
],
], - Answer:
除了 AWS 預設的 key, secret, region 之外, 還可設置 additional 的 setting
# Generating Mailables
以下的 Laravel example code 的意思是?
- Example:
php artisan make:mail OrderShipped
- Answer:
建立一個 mailable class, 會放在 app/Mail
# Writing Mailables
# Configuring The Sender
# Using The from Method
以下的 Laravel example code 的意思是?
- Example:
<?php
// in mailable class
public function build()
{
return $this->from('example@example.com')
->view('emails.orders.shipped');
} - Answer:
在 mailable class 的 build 中, 可以使用 from 來指定由的 from
# Using A Global from address
以下的 Laravel example code 的意思是?
- Example:
<?php
// config/mail.php
'from' => ['address' => 'example@example.com', 'name' => 'App Name'], - Answer:
可在 config/mail.php 定義 global 的 from, 即寄件人信箱, 若需要 ad hoc 可在 mailable class 的 build method 中使用 from() 定義
以下的 Laravel example code 的意思是?
- Example:
<?php
// config/mail.php
'reply_to' => ['address' => 'example@example.com', 'name' => 'App Name'], - Answer:
定義 reply_to address
當收到 mail 時, 預設按下 reply 會寄給 FROM address, 若要指定一個跟 FROM address 不同的 reply address, 可在此定義
# Configuring The View
以下的 Laravel example code 的意思是?
- Example:
<?php
public function build()
{
return $this->view('emails.orders.shipped');
} - Answer:
在 mailable class 的 build method 內, 使用 view() 來指定渲染該 mail 的 template
# Plain Text Emails
以下的 Laravel example code 的意思是?
- Example:
<?php
public function build()
{
return $this->view('emails.orders.shipped')
->text('emails.orders.shipped_plain');
} - Answer:
可以同時定義 HTML 以及 plain text version, 當 user 切換為 plain text version 時, 就會顯示該版本
# View Data
# Via Public Properties
以下的 Laravel example code 的意思是?
- Example:
<?php
namespace App\Mail;
class OrderShipped extends Mailable
{
use Queueable, SerializesModels;
public $order;
public function __construct(Order $order)
{
$this->order = $order;
}
public function build()
{
return $this->view('emails.orders.shipped');
}
}
// on template
<div>
Price: {{ $order->price }}
</div> - Answer:
當使用 mailable class 時, 可在 constructor 內定義 property, 此 property 可在 template 中被調用
# Via The with Method:
以下的 Laravel example code 的意思是?
- Example:
<?php
class OrderShipped extends Mailable
{
use Queueable, SerializesModels;
protected $order;
public function __construct(Order $order)
{
$this->order = $order;
}
public function build()
{
return $this->view('emails.orders.shipped')
->with([
'orderName' => $this->order->name,
'orderPrice' => $this->order->price,
]);
}
}
// template file
<div>
Price: {{ $orderPrice }}
</div> - Answer:
如果 mailable 中的 property 使用 protected 或 private 的話, 則必須使用 with() 將 data pass 過去
# Attachments
以下的 Laravel example code 的意思是?
- Example:
<?php
public function build()
{
return $this->view('emails.orders.shipped')
->attach('/path/to/file', [
'as' => 'name.pdf',
'mime' => 'application/pdf',
]);
} - Answer:
在 mailable class 的 build method 中, 可以使用 attach() 定義 attachment, arg2 還可以定義檔名以及 mine type
# Attaching Files from Disk
以下的 Laravel example code 的意思是?
- Example:
<?php
public function build()
{
return $this->view('emails.orders.shipped')
->attachFromStorage('/path/to/file', 'name.pdf', [
'mime' => 'application/pdf'
]);
} - Answer:
在 mailable class 的 build method 中, 使用 attachFromStorage, attach filesystem disk 的 file 到 email, arg2 可指定檔名, arg3 可指定 mine type
以下的 Laravel example code 的意思是?
- Example:
<?php
public function build()
{
return $this->view('emails.orders.shipped')
->attachFromStorageDisk('s3', '/path/to/file');
} - Answer:
在 mailable class 的 build method 中, 使用 attachFromStorageDisk, attach filesystem disk 的 file 到 email, arg1 可指定要使用哪一個 disk
# Raw Data Attachment
以下的 Laravel example code 的意思是?
- Example:
<?php
public function build()
{
return $this->view('emails.orders.shipped')
->attachData($this->pdf, 'name.pdf', [
'mime' => 'application/pdf',
]);
} - Answer:
attach raw data, 通常是 attach 當次 request 產生的 pdf, 在 memory 中, 並沒有存到 disk 中, arg2 可指定檔名 arg3 可指定 mine type
# Inline Attachments
以下的 Laravel example code 的意思是?
- Example:
<?php
<body>
Here is an image:
<img src="{{ $message->embed($pathToImage) }}">
</body> - Answer:
email template 中, 可以使用 $message variable 的 embed method 來實現 inline attachment
# Embedding Raw Data Attachments
以下的 Laravel example code 的意思是?
- Example:
<?php
<body>
Here is an image from raw data:
<img src="{{ $message->embedData($data, 'example-image.jpg') }}">
</body> - Answer:
在 mail template 中, 如果 memory 中已有檔案, 可以使用 embedData method 來實現 inline attachment
# Customizing The SwiftMailer Message
以下的 Laravel example code 的意思是?
- Example:
<?php
public function build()
{
$this->view('emails.orders.shipped');
$this->withSwiftMessage(function ($message) {
$message->getHeaders()->addTextHeader(
'Custom-Header', 'Header Value'
);
});
} - Answer:
在 mailable class 的 build method 中, 使用 withSwiftMessage(), 可註冊一個 closure, 會跟著 SwiftMailer message instance 被觸發, 可在送出 mail 前做一些客製化
# Markdown Mailables
# Generating Markdown Mailables
以下的 Laravel example command 的意思是?
- Example:
<?php
php artisan make:mail OrderShipped --markdown=emails.orders.shipped - Answer:
建立一個 mailable class, 以及相對應的 markdown template
以下的 Laravel example code 的意思是?
- Example:
<?php
public function build()
{
return $this->from('example@example.com')
->markdown('emails.orders.shipped', [
'url' => $this->orderUrl,
]);
} - Answer:
在 mailable class 的 build method 中, 使用 markdown(), arg1 指定 markdown template, arg2 可帶入 array, 該 array data 會在 template 中可被以變數的方式使用
# Writing Markdown Messages
以下的 Laravel Mailable Markdown Template example code 的意思是?
- Example:
<?php
@component('mail::message')
# Order Shipped
Your order has been shipped!
@component('mail::button', ['url' => $url])
View Order
@endcomponent
Thanks,<br>
{{ config('app.name') }}
@endcomponent - Answer:
Laravel 的 Mailable Markdown Template 結合了 Blade 的 component 以及 Markdown 語法, 可使用 Laravel 預設的 email UI component
# Button Component
以下的 Laravel Mailable Markdown Template example code 的意思是?
- Example:
<?php
@component('mail::button', ['url' => $url, 'color' => 'success'])
View Order
@endcomponent - Answer:
使用 Laravel 內建的 email UI component, 為一個 button, 可指定 url 以及 color, color 又可指定 primary, success, 以及 error
# Panel Component
以下的 Laravel Mailable Markdown Template example code 的意思是?
- Example:
<?php
@component('mail::panel')
This is the panel content.
@endcomponent - Answer:
使用 Laravel 內建的 email UI component, panel 的效果會讓該區塊的背景顏色稍為不同, 可以達到引起注意力的效果
# Table Component
以下的 Laravel Mailable Markdown Template example code 的意思是?
- Example:
<?php
@component('mail::table')
| Laravel | Table | Example |
| ------------- |:-------------:| --------:|
| Col 2 is | Centered | $10 |
| Col 3 is | Right-Aligned | $20 |
@endcomponent - Answer:
使用 Laravel 內建的 email UI component, 就是 Markdown table 的效果
# Customizing The Components
以下的 Laravel example commadn 的意思是?
- Example:
<?php
php artisan vendor:publish --tag=laravel-mail - Answer:
可以匯出 Laravel 內建的 mail template, 匯出後可依照自己的需求去做進一步客製化, 會匯出到resources/views/vendor/mail
資料夾
# Customizing The CSS
Laravel 中, 如果我要客製化 Markdown template 的 CSS, 該怎麼做?
- 在 export components 後, 修改
resources/views/vendor/mail/html/themes
資料夾中的 default.css - 在
resources/views/vendor/mail/html/themes
資料夾中建立一個新的 CSS file, 並在config/mail.php
中修改 theme 要吃的檔案 - 若要針對單一 mailable class 修改, 可在 mailable class 中的
$theme
property 中, 指定要吃的 theme css file
# Sending Mail
以下的 Laravel example code 的意思是?
- Example:
<?php
class OrderShipmentController extends Controller
{
public function store(Request $request)
{
$order = Order::findOrFail($request->order_id);
// Ship the order...
Mail::to($request->user())->send(new OrderShipped($order));
}
} - Answer:
使用 Mail facade 的 to(), 指定收件人, 會自動到該 User model 尋找 name column 以及 email column, 然後再指定 mailable class
以下的 Laravel example code 的意思是?
- Example:
<?php
Mail::to($request->user())
->cc($moreUsers)
->bcc($evenMoreUsers)
->send(new OrderShipped($order)); - Answer:
也可使用 cc (Carbon Copy) 以及 bcc (Blind Carbon Copy) method 來寄信
# Looping Over Recipients
以下的 Laravel example code 的意思是?
- Example:
<?php
foreach (['taylor@example.com', 'dries@example.com'] as $recipient) {
Mail::to($recipient)->send(new OrderShipped($order));
} - Answer:
有時會需要使用 loop 來將同一個 mailable class 寄給很多收件人, 這時務必在每一個 iteration 中都要使用 new Mailable Instance, 否則 to() 會將 email append 到 mailable instance, 這樣就會變成每一個 iteration 都會寄給之前的所有收件人
# Sending Mail Via A Specific Mailer
以下的 Laravel example code 的意思是?
- Example:
<?php
Mail::mailer('postmark')
->to($request->user())
->send(new OrderShipped($order)); - Answer:
Laravel 預設會使用 config/mail.php 中的 default mailer 來寄信, 也可使用 mailer() 來特別指定
# Queueing Mail
# Queueing A Mail Message
以下的 Laravel example code 的意思是?
- Example:
<?php
Mail::to($request->user())
->cc($moreUsers)
->bcc($evenMoreUsers)
->queue(new OrderShipped($order)); - Answer:
使用 queue 來發送 mail
# Delayed Message Queueing
以下的 Laravel example code 的意思是?
- Example:
<?php
Mail::to($request->user())
->cc($moreUsers)
->bcc($evenMoreUsers)
->later(now()->addMinutes(10), new OrderShipped($order)); - Answer:
使用 later(), 可以發送 delayed queue message
# Pushing To Specific Queues
以下的 Laravel example code 的意思是?
- Example:
<?php
$message = (new OrderShipped($order))
->onConnection('sqs')
->onQueue('emails');
Mail::to($request->user())
->cc($moreUsers)
->bcc($evenMoreUsers)
->queue($message); - Answer:
使用 queue 發送 mail, 並指定其 connection 以及 queue
# Queueing By Default
以下的 Laravel example code 的意思是?
- Example:
<?php
use Illuminate\Contracts\Queue\ShouldQueue;
class OrderShipped extends Mailable implements ShouldQueue
{
//
} - Answer:
如果已經確定這個 mailable 會固定使用 queue 來發送, 可以 implement ShouldQueue interface
# Queued Mailables & Database Transaction
以下的 Laravel example code 的意思是?
- Example:
<?php
use Illuminate\Contracts\Queue\ShouldQueue;
class OrderShipped extends Mailable implements ShouldQueue
{
public $afterCommit = true;
} - Answer:
有時我們會在 transaction 中發送 queued mailable, 但在 transaction 完成之前 mailable 就已經 dispatch 了, 這會造成預期外的錯誤, 如要避免此情況, 可將 mailable class 的 $afterCommit property 設為 true, 這樣 queued mail 就會等到當下所有的 open transaction 都完成了才會寄出
# Rendering Mailables
以下的 Laravel example code 的意思是?
- Example:
<?php
use App\Mail\InvoicePaid;
use App\Models\Invoice;
$invoice = Invoice::find(1);
return (new InvoicePaid($invoice))->render(); - Answer:
render method 會以 string 的方式 return HTML content
# Previewing Mailables In The Browser
以下的 Laravel example code 的意思是?
- Example:
<?php
Route::get('/mailable', function () {
$invoice = App\Models\Invoice::find(1);
return new App\Mail\InvoicePaid($invoice);
}); - Answer:
在設計 mailable class 時, 會希望可以即時地看到畫面, 這時可以直接 return mailable instance
需注意這並不會 return inline attachment, 如需測試 inline attachment, 可使用 MailHog 或 HELO
# Localizing Mailables
以下的 Laravel example code 的意思是?
- Example:
<?php
Mail::to($request->user())->locale('es')->send(
new OrderShipped($order)
); - Answer:
使用 locale() 來指定 locale
# User Preferred Locales
以下的 Laravel example code 的意思是?
- Example:
<?php
use Illuminate\Contracts\Translation\HasLocalePreference;
class User extends Model implements HasLocalePreference
{
public function preferredLocale()
{
return $this->locale;
}
}
// in controller
Mail::to($request->user())->send(new OrderShipped($order)); - Answer:
當 notifiable model implement HasLocalePreference interface 之後, 可在 preferredLocale() 中定義要使用的 locale, 當使用 to() 發送 mailable 給指定 user 時, 會自動抓取資料庫中的 locale
# Testing Mailables
以下的 Laravel example code 的意思是?
- Example:
<?php
use App\Mail\InvoicePaid;
use App\Models\User;
public function test_mailable_content()
{
$user = User::factory()->create();
$mailable = new InvoicePaid($user);
$mailable->assertSeeInHtml($user->email);
$mailable->assertSeeInHtml('Invoice Paid');
$mailable->assertSeeInText($user->email);
$mailable->assertSeeInText('Invoice Paid');
} - Answer:
可使用 mailable testing method 來驗證 mailable 是否包含指定的 string, assertSeeInHtml 跟 assertSeeInText 差別在於 HTML version mail 跟 plain text version mail
# Mail & Local Development
Laravel 中, 如果要測試 mail 是否有被發送, 可使用哪兩種方式?
Log driver 或一些其他的服務, 像是 HELO, Mailtrap, MailHog
# Events
以下的 Laravel example code 的意思是?
- Example:
<?php
protected $listen = [
'Illuminate\Mail\Events\MessageSending' => [
'App\Listeners\LogSendingMessage',
],
'Illuminate\Mail\Events\MessageSent' => [
'App\Listeners\LogSentMessage',
],
]; - Answer:
可註冊 listener 監聽兩種 mail event, MessageSending event 在 mail 發送前被觸發, MessageSent 在發送後觸發, 注意如果只是 queue 的話並不會觸發, 待該 job 真正被 worker pick up 被執行時才會觸發
留言