Laravel: Tìm hiểu về Notifications (Phần 2)
Database Notifications ### Prerequisites Kênh ```database``` notification lưu thông tin thông báo vào một bảng cơ sở dữ liệu. Bảng này sẽ chứa thông tin như là kiểu thông báo cũng như kiểu dữ liệu JSON để mô tả thông tin của thông báo. Bạn có thể query vào bảng để hiển thị thông báo trong giao ...
Database Notifications
### Prerequisites Kênh ```database``` notification lưu thông tin thông báo vào một bảng cơ sở dữ liệu. Bảng này sẽ chứa thông tin như là kiểu thông báo cũng như kiểu dữ liệu JSON để mô tả thông tin của thông báo.
Bạn có thể query vào bảng để hiển thị thông báo trong giao diện người dùng trong ứng dụng của bạn. Nhưng trước khi bạn làm điều này, bạn cần tạo một bảng để lưu thông báo của bạn. Bạn dùng lệnh notifications:table để tao file migrate chứa các thuộc tính của bảng:
php artisan notifications:table php artisan migrate
### Formatting Database Notifications Nếu một thông báo hỗ trợ được lưu trong cơ sở dữ liệu, bạn nên định nghĩa một phương thức ```toDatabase``` hoặc ```toArray``` trong class notification. Phương thức này sẽ nhận về một entity ```$notifiable``` và nên trả về một plain PHP array. Mảng trả về này sẽ được encode JSON và lưu tại column ```data``` của bảng ```notifications```. Hãy xem ví dụ về phương thức ```toArray```: ``` /** * Get the array representation of the notification. * * @param mixed $notifiable * @return array */ public function toArray($notifiable) { return [ 'invoice_id' => $this->invoice->id, 'amount' => $this->invoice->amount, ]; } ```
**```toDatabase ```Vs. ```toArray```** Phương thức ```toArray``` cũng được sử dụng bởi kênh ```broadcast``` để xác định dữ liệu vào broadcast đến JavaScript client. Nếu bạn muốn có hai mảng representations khác nhau cho kênh ```database``` và ```broadcast```, bạn nên định nghĩa một phương thức ```toDatabase``` thay thế phương thức ```toArray```.
### Accessing The Notifications Mỗi thông báo đã được lưu vào database, bạn cần một cách thuận tiện để truy cập chúng từ các thực thể thông báo của bạn. ```IlluminateNotificationsNotifiable``` trait được mặc định thêm vào bởi Laravel trong model ```AppUser```, bao gồm một ```notifications``` Eloquent relationship nó sẽ trả về thông báo cho entiry (thực thể). Để lấy thông báo, bạn có thể truy cập phương thức này như bất kỳ Eloquent relationship. Mặc định, thông báo sẽ được sắp xếp theo ```created_at``` timestamp: ``` $user = AppUser::find(1);
foreach (user−>notificationsasuser->notifications as user−>notificationsasnotification) { echo $$otification->type; }
Nếu bạn chỉ muốn nhận những thông báo "unread", bạn có thể sử dụng ```unreadNotifications``` relationship. Một lần nữa, những thông báo đó sẽ được sắp xếp theo ```created_at``` timestamp:
$$ser = AppUser::find(1);
foreach (user−>unreadNotificationsasuser->unreadNotifications as user−>unreadNotificationsasnotification) { echo $$otification->type; }
<br> ### Marking Notifications As Read Thông thường, bạn sẽ muốn đánh dấu thông báo "read" khi nghười dùng xem nó. ```IlluminateNotificationsNotifiable``` trait cung cấp một phương thức ```markAsRead```, nó sẽ cập nhật column ```read_at``` trong record của notification database:
$$ser = AppUser::find(1);
foreach (user−>unreadNotificationsasuser->unreadNotifications as user−>unreadNotificationsasnotification) { $$otification->markAsRead(); }
Tuy nhiên, thay vì dùng vòng lặp qua mỗi thông báo, bạn có thể sử dụng phương thức ```markAsRead``` trực tiếp trong một collection của thông báo:
$$ser->unreadNotifications->markAsRead();
Ngoài ra bạn cũng có thể sử dụng cập nhật hàng loạt để đánh dấu tất cả các thông báo đã đọc mà không cần lấy ra chúng từ database:
$$ser = AppUser::find(1);
$$ser->unreadNotifications()->update(['read_at' => now()]);
Dĩ nhiên, bạn cũng có thể ```delete``` các thông báo từ table entirely:
$$ser->notifications()->delete();
<br> ## Broadcast Notifications <br> ### Prerequisites Trước khi broadcasting thông báo, bạn nên cấu hình giống với [event broadcasting services](https://laravel.com/docs/5.5/broadcasting). Event broadcasting cung cấp một cách để tiếp cận vào server-side bắn ra Laravel từ JavaScript client. <br> ### Formatting Broadcast Notifications Kênh ```broadcast``` thông báo broadcasts sử dụng [event broadcasting](https://laravel.com/docs/5.5/broadcasting) services, cho phép JavaScript client để bắt thông báo realtime. Nếu một thông báo hỗ trợ broadcasting, bạn nên định nghĩa một phương thức ```toBroadcast``` trong class notification. Phương thức này sẽ nhận một entiry ```$notifiable``` và nên trả về một ```BroadcastMessage``` instance. Dữ liệu trả về sẽ được encoded thành JSON và broadcast vào JavaScript client của bạn. Hãy xem ví dụ phương thức ```BroadcastMessage```:
/**
- Get the broadcastable representation of the notification.
- @param mixed $$otifiable
- @return BroadcastMessage */ public function toBroadcast(notifiable) { return new BroadcastMessage([ 'invoice_id' => this->invoice->id, 'amount' => $$his->invoice->amount, ]); }
**Broadcast Queue Configuration** Tất cả các broadcast thông báo được xếp hàng đợi để phát sóng. Nếu bạn muốn cấu hình queue connection hoặc queue name được sử dụng cho hàng đợi broadcast operation, bạn có thể sử dụng phương thức ```onConnection``` và ```onQueue``` của ```BroadcastMessage```:
return (new BroadcastMessage($$ata)) ->onConnection('sqs') ->onQueue('broadcasts');
<br> ### Listening For Notifications Thông báo sẽ được broadcast trong private chanel được định dạng sử dụng một ```{notifiable}.{id}``` convention. Vì vậy, nếu bạn gửi thông báo vào một ```AppUser``` instance với id là ```1```, notification sẽ broadcast trong ```App.User.1``` private chanel. Khi sử dụng [Laravel Echo](https://laravel.com/docs/5.5/broadcasting), bạn có thể dễ dàng lắng nghe một thông báo trên kênh sử dụng phương thức helper ```notification```:
Echo.private('App.User.' + userId) .notification((notification) => { console.log(notification.type); });
**Customizing The Notification Channel** Nếu bạn muốn tuỳ chỉnh các chanel thông báo entity nhận được broadcast notifications on, bạn có thể định nghĩa phương thức ```receiveBroadcastNotificationsOn``` trên notifiable entity:<?php namespace App; use IlluminateNotificationsNotifiable; use IlluminateBroadcastingPrivateChannel; use IlluminateFoundationAuthUser as Authenticatable; class User extends Authenticatable { use Notifiable; /** * The channels the user receives notification broadcasts on. * * @return string */ public function receivesBroadcastNotificationsOn() { return 'users.'.$this->id; } } ```
## SMS Notifications
### Prerequisites Gửi thông báo SMS trong Laravel được cung cấp bởi [Nexmo](https://www.nexmo.com/). Để gửi được thông báo qua Nexmo, bạn cần cài đặt ```nexmo/client``` Composer package và thêm một vài cấu hình tùy chọn vào trong file cấu hình ``config/services.php``` của bạn. Bạn có thể copy ví dụ cấu hình sau để bắt đầu: ``` 'nexmo' => [ 'key' => env('NEXMO_KEY'), 'secret' => env('NEXMO_SECRET'), 'sms_from' => '15556666666', ], ``` Tùy chọn ```sms_from``` là số điện thoại sẽ gửi SMS. Bạn nên tạo một số điện thoại trong Nexmo control panel.
### Formatting SMS Notifications Nếu một thông báo hỗ trợ gửi SMS, bạn nên định nghĩa một phương thức ```toNexmo``` trong class notification. Nó sẽ nhận một entity ```$notifiable``` và trả về một ```IlluminateNotificationsMessagesNexmoMessage``` instance: ``` /** * Get the Nexmo / SMS representation of the notification. * * @param mixed $notifiable * @return NexmoMessage */ public function toNexmo($notifiable) { return (new NexmoMessage) ->content('Your SMS message content'); } ```
**Unicode Content** Nếu tin nhắn SMS của bạn chứa ký tự ```unicode```, bạn nên gọi phương thức ```unicode``` khi xây dựng ```NexmoMessage``` instance: ``` /** * Get the Nexmo / SMS representation of the notification. * * @param mixed $notifiable * @return NexmoMessage */ public function toNexmo($notifiable) { return (new NexmoMessage) ->content('Your unicode message') ->unicode(); } ```
### Customizing The "From" Number Nếu bạn muốn gửi thông báo từ một số điện thoại khác với số điện thoại từ file cấu hình ```config/services.php```, bạn có thể dùng phương thức ```from``` trong ```NexmoMessage``` instance: ``` /** * Get the Nexmo / SMS representation of the notification. * * @param mixed $notifiable * @return NexmoMessage */ public function toNexmo($notifiable) { return (new NexmoMessage) ->content('Your SMS message content') ->from('15554443333'); } ```
### Routing SMS Notifications Khi gửi thông báo qua kênh ```nexmo```, thông báo hệ thống sẽ tự động tìm thuộc tính ```phone_number``` trong notifiable entity. Nếu bạn muốn tùy biến số điện thoại được gửi đến, định nghĩa một phương thức ```routeNotificationForNexmo``` trong entity: ``` <?php namespace App; use IlluminateNotificationsNotifiable; use IlluminateFoundationAuthUser as Authenticatable; class User extends Authenticatable { use Notifiable; /** * Route notifications for the Nexmo channel. * * @return string */ public function routeNotificationForNexmo() { return $this->phone; } } ```
## Slack Notifications
### Prerequisites Trước khi bạn có thể gửi thông báo qua Slack, bạn cần cài thư viện Guzzle HTTP library qua Composer: ``` composer require guzzlehttp/guzzle ``` Bạn cũng sẽ cần cấu hình tích hợp ["Incoming Webhook"](https://api.slack.com/incoming-webhooks) cho Slack team. Integration này sẽ cung cấp cho bạn một URL mà bạn có thể sử dụng khi [routing Slack notifications](https://laravel.com/docs/5.5/notifications#routing-slack-notifications).
### Formatting Slack Notifications Nếu một thông báo hỗ trợ qua thông báo của Slack mesage, bạn nên định nghĩa một phương thức ```toSlack``` trong class notification. Phương thức này sẽ nhận một entity ```$notifiable``` và trả về một ```IlluminateNotificationsMessagesSlackMessage``` instance. Thông báo Slack có thể chứa nội dung text cũng như "đính kèm". Hãy xem ví dụ đơn giản của phương thức ```toSlack```: ``` /** * Get the Slack representation of the notification. * * @param mixed $notifiable * @return SlackMessage */ public function toSlack($notifiable) { return (new SlackMessage) ->content('One of your invoices has been paid!'); } ``` Trong ví dụ trên chúng ta chỉ gửi một dòng text vào Slack, nó sẽ tạo ra một dòng text và nhìn như bên dưới: ![](https://viblo.asia/uploads/13cca046-d1d1-4cff-8b41-280d04313307.png)
**Customizing The Sender & Recipient** Bạn có thể sử dụng phương thức````from``` và ```to``` để tùy chỉnh người gửi và người nhận. Phương thức ```from``` chấp nhận username và emoji identifier, trong khi phương thức ```to``` chấp nhận chanel hoặc username: ``` /** * Get the Slack representation of the notification. * * @param mixed $notifiable * @return SlackMessage */ public function toSlack($notifiable) { return (new SlackMessage) ->from('Ghost', ':ghost:') ->to('#other') ->content('This will be sent to #other'); } ``` Bạn cũng có thể sử dụng một hình ảnh làm biểu tượng của mình thay vì một emoji: ``` /** * Get the Slack representation of the notification. * * @param mixed $notifiable * @return SlackMessage */ public function toSlack($notifiable) { return (new SlackMessage) ->from('Laravel') ->image('https://laravel.com/favicon.png') ->content('This will display the Laravel logo next to the message'); } ```
### Slack Attachments Bạn cũng có thể "attachments" vào Slack. Attachments cung cấp nhiều định dạng phong phú hơn là simple text. Trong ví dụ này, chúng ta sẽ gửi một thông báo lỗi về exception xảy ra trong ứng dụng, gồm link để xem chi tiết về exception: ``` /** * Get the Slack representation of the notification. * * @param mixed $notifiable * @return SlackMessage */ public function toSlack($notifiable) { $url = url('/exceptions/'.$this->exception->id); return (new SlackMessage) ->error() ->content('Whoops! Something went wrong.') ->attachment(function ($attachment) use ($url) { $attachment->title('Exception: File Not Found', $url) ->content('File [background.jpg] was not found.'); }); } ``` Ví dụ trên sẽ sinh ra một thông báo slack nhìn giống như sau: ![](https://viblo.asia/uploads/7a4c5fb3-2fb1-43d6-9cb5-fec6a5f8ac85.png) Attachments cũng cho phép bạn chỉ định một mảng được gửi cho người dùng. Mảng này sẽ được hiện theo kiểu bảng rất dễ để đọc: ``` /** * Get the Slack representation of the notification. * * @param mixed $notifiable * @return SlackMessage */ public function toSlack($notifiable) { $url = url('/invoices/'.$this->invoice->id); return (new SlackMessage) ->success() ->content('One of your invoices has been paid!') ->attachment(function ($attachment) use ($url) { $attachment->title('Invoice 1322', $url) ->fields([ 'Title' => 'Server Expenses', 'Amount' => '$1,234', 'Via' => 'American Express', 'Was Overdue' => ':-1:', ]); }); } ``` Ví dụ trên sẽ sinh ra một thông báo slack giống như sau: ![](https://viblo.asia/uploads/64563b35-b368-4a45-a40d-79c92d6a7354.png)
**Markdown Attachment Content** Nếu một số attachment fields của bạn có chứa Markdown, bạn có thể sử dụng phương thức ```markdown``` để hướng dẫn Slack parse và display các trường đính kèm đã chọn dưới dạng văn bản được định dạng Markdown. Các giá trị được chấp nhận bởi phương thức này là: ```pretext```, ```text```, and / or ```fields```. Để biết thêm thông tin về định dạng tập tin đính kèm Slack, xem [Slack API documentation](https://api.slack.com/docs/message-formatting#message_formatting): ``` /** * Get the Slack representation of the notification. * * @param mixed $notifiable * @return SlackMessage */ public function toSlack($notifiable) { $url = url('/exceptions/'.$this->exception->id); return (new SlackMessage) ->error() ->content('Whoops! Something went wrong.') ->attachment(function ($attachment) use ($url) { $attachment->title('Exception: File Not Found', $url) ->content('File [background.jpg] was *not found*.') ->markdown(['text']); }); } ```
### Routing Slack Notifications Để route Slack notifications đến vị trí thích hợp, định nghĩa một phương thức ```routeNotificationForSlack``` trong notifiable entity. Phương thức này sẽ trả về một webhook URL nơi mà thông báo sẽ được phục vụ. Webhook URLs có thể được sinh bởi "Incoming Webhook" service vào Slack team: ``` <?php namespace App; use IlluminateNotificationsNotifiable; use IlluminateFoundationAuthUser as Authenticatable; class User extends Authenticatable { use Notifiable; /** * Route notifications for the Slack channel. * * @return string */ public function routeNotificationForSlack() { return $this->slack_webhook_url; } } ```
Tài liệu: https://laravel.com/docs/5.5/notifications