繼續昨日 Laravel – 手動寄信功能 研究,今日試著測試 Laravel 的 Notifications 通知功能。

修改路由 route\web.php,新增一個 post 路由給這個功能用

Route::post('mails/sendnote','Admin\MailsController@sendnote')->name('sendnote');

延續使用手動發送信件功能的 blade 當作輸入內容的表單,修改 adminsendmailform.blade.php,新增給這個功能用的表單。這邊內容皆已經填入資料,只要輸入 To 欄位的 email address 即可,也就是說內容是可以被替換的。(例如: 表格、檔案…等)

<form id="sendnoteform" action="{{ route('admin.sendnote') }}" method="POST" role="form">
    @csrf
    <div class="card-body">
        <div class="form-group">
            <label>To</label>
            <input type="email" class="form-control {{ $errors->has('email') ? ' is-invalid' : '' }}" name="email" value="" placeholder="輸入Email">
            @if ($errors->has('email'))
            <span class="invalid-feedback" role="alert">
                <strong>{{ $errors->first('email') }}</strong>
            </span>
            @endif
        </div>
        <div class="form-group">
            <label>主旨</label>
            <input type="text" class="form-control {{ $errors->has('subject') ? ' is-invalid' : '' }}" name="subject" value="發送通知測試主旨" placeholder="輸入主旨">
            @if ($errors->has('subject'))
            <span class="invalid-feedback" role="alert">
                <strong>{{ $errors->first('subject') }}</strong>
            </span>
            @endif
        </div>
        <div class="form-group">
            <label for="exampleInputEmail1">標題</label>
            <input type="text" class="form-control {{ $errors->has('title') ? ' is-invalid' : '' }}" name="title" value="發送通知測試標題" placeholder="輸入標題">
            @if ($errors->has('title'))
            <span class="invalid-feedback" role="alert">
                <strong>{{ $errors->first('title') }}</strong>
            </span>
            @endif
        </div>
        <div class="form-group">
            <label>內容</label>
            <textarea class="form-control {{ $errors->has('content') ? ' is-invalid' : '' }} " rows="3" id="sendnote" name="content" placeholder="Enter ...">發送通知測試內容!!發送通知測試內容!!</textarea>
            @if ($errors->has('content'))
            <span class="invalid-feedback" role="alert">
                <strong>{{ $errors->first('content') }}</strong>
            </span>
            @endif
        </div>
    </div>
    <div class="card-footer text-center">
        <button type="submit" class="btn btn-primary">發送</button>
    </div>
</form>

新增 Request\Admin\AdminSendNoteRequest.php 驗證表單,養成好習慣只要是表單進來的資料一定都要驗證過,避免被攻擊或發生不可預期狀況。

<?php

namespace App\Http\Requests\Admin;

use Illuminate\Foundation\Http\FormRequest;
use Auth;

class AdminSendNoteRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    //必須登入才可以使用這個Request
    public function authorize()
    {
        return Auth::check();
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    //欄位規則
    public function rules()
    {
        return [
            'email'=>'required|email',
            'subject'=>'required|string|max:100',
            'title'=>'required|string|max:100',
            'content'=>'required|string|max:1000',
        ];
    }
}

建立 Notifications

php artisan make:notifications Admin\AdminSendNoteNotification
<?php

namespace App\Notifications\Admin;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;

//使用 AdminSendMail 的信件模板
use App\Mail\AdminSendMail as AdminSendMail;

class AdminSendNoteNotification extends Notification
{
    use Queueable;

    public $details;

    /**
     * Create a new notification instance.
     *
     * @return void
     */
    public function __construct($details)
    {
        $this->details = $details;
    }

    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return ['mail'];
    }

    /**
     * Get the mail representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return \Illuminate\Notifications\Messages\MailMessage
     */
    public function toMail($notifiable)
    {
        //使用 AdminSendMail 的信件模板
        return (new AdminSendMail($this->details))->to($this->details->email);

        //使用 MailMessage 方式
        // return (new MailMessage)
        //             ->line('The introduction to the notification.')
        //             ->action('Notification Action', url('/'))
        //             ->line('Thank you for using our application!');
    }

    /**
     * Get the array representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function toArray($notifiable)
    {
        return [
            //
        ];
    }
}

修改 MailsController,加入 sentnote function

/**
 * Notifications 測試
 */
public function sendnote(AdminSendNoteRequest $request)
{
    // dd($request);
    try{
        /**
         * 發送 notification 到一個沒有存在 database 中, 特定的接收方時,
         * 可以使用 Notification facade 的 method 來指定 channel
         * 這邊的route('mail')指的是通道
         */
        Notification::route('mail', $request->email)
                    ->notify(new AdminSendNoteNotification($request));
    }
    catch(Exception $e){
        $message = "信件寄出失敗";
        Session::put('error',$message);
    }
    $message = "通知已寄出給 $request->email";
    Session::put('success',$message);
    return view('admin.mails.adminsendmailform');
}

測試

說明

這功能似乎跟昨日的手動寄送信件一樣,但其主要功能並不只是只有寄送信件,它除了可以使用 mail 通道寄信外,也可以用來通知到其他的通道例如:SMS 簡訊、Slack 團隊溝通頻道、或者資料庫都可以使用,亦或者用來通知到其它網站例如: FB API、Google API … 等等,我只是拿其中一項作為簡單的功能測試。以相同的道理就可以延伸拓展到其他部份去。

最後修改日期: 2020 年 11 月 18 日