Hướng dẫn sử dụng Queues để gửi mail trong laravel

Laravel Queue là một cách hiệu quả để trì hoãn việc xử lý một tác vụ tốn thời gian trong hệ thống của bạn. Ví dụ về các tác vụ như vậy có thể bao gồm gửi email xác minh khi có người dùng đăng ký trên ứng dụng của bạn hoặc tính toán thống kê một số logic nào đó... Laravel Queue giúp trì hoãn các tác vụ như vậy, nó chạy ngầm cho nên nó sẽ cải thiện tốc độ khi người dùng thao thác trên web của bạn.

Xây dựng một ví dụ đơn giản

Chúng ta sẽ xây dựng một ứng dụng blog đơn giản cho phép bạn gửi bài đăng và gửi email bất cứ khi nào bài viết mới được tạo. Chúng ta sẽ sử dụng queue để xử lý việc gửi email.

Mục đích của bài hướng dẫn này là về queue trong laravel cho nên hiển nhiên việc cài đặt laravel bạn có thể tự thực hiện được. Tham khảo ở đây https://laravel.com/docs/5.8. Bạn cài laravel 5.8 bản mới nhất nhé.

Bắt đầu

Bước 1: Khởi tạo Model, Controller và Migration chỉ với một câu lệnh đơn giản như sau:

php artisan make:model Post -m -c

Bước 2: Tìm đến file CreatePostsTable.php bạn sửa như sau:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreatePostsTable extends Migration
{
   /**
    * Run the migrations.
    *
    * @return void
    */
   public function up()
   {
       Schema::create('posts', function (Blueprint $table) {
           $table->increments('id');
           $table->string('title');
           $table->string('body');
           $table->timestamps();
       });
   }

   /**
    * Reverse the migrations.
    *
    * @return void
    */
   public function down()
   {
       Schema::dropIfExists('posts');
   }
}

Bước 3: Bạn chạy lệnh sau, nó sẽ tạo các bảng để sử dụng queue, tham khảo tạo đây https://laravel.com/docs/5.8/queues#driver-prerequisites

php artisan queue:table

Bước 4: Trong file .env bạn sửa như sau:

QUEUE_DRIVER=database

Bước 5: Bạn chạy lệnh sau

php artisan migrate

Bước 6: Cấu hình email trong file .env

MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=[username]
MAIL_PASSWORD=[password]
MAIL_ENCRYPTION=null

Bước 7: Cấu hình routes trong web.php

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
 
Route::get('/index', '[email protected]');
Route::post('/posts', '[email protected]');

Bước 8: Tạo methods và views đơn giản như sau

Sửa file PostController.php

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Post;
class PostController extends Controller
{
        public function index()
        {
            return view('index');
        }    
        
        public function store(Request $request)
        {
            $request->validate([
               'title'=>'required|min:6',
               'body'=> 'required|min:6',
            ]);
            $post = new Post;
            $post->title = $request->title;
            $post->body = $request->body;
            $post->save();
            return redirect()->back()->with('status', 'Your post has been submitted successfully');
        }
}

Tạo file index.blade.php trong resources/views

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width">
<title>Laravel Queues</title>
<meta name="description" content="">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
</head>

<body>
<div class="container">
<div class="col-md-5">
<h4 class="page-header">Laravel Queues </h4> @foreach ($errors->all() as $error)
<p class="alert alert-danger">{{ $error }}</p>
@endforeach
@if (session('status'))
<div class="alert alert-success">
{{ session('status')}}
</div>
@endif
<form class="form-vertical" role="form" method="post" action="/posts">
{{csrf_field()}}
<div class="form-group">
<input type="text" name="title" class="form-control" placeholder="Title">
</div>
<div class="form-group">
<textarea class="form-control" rows="5" name="body" class="form-control" placeholder="Content"></textarea>
</div>
<div class="form-group">
<button type="submit" class="btn btn-info">Submit Post</button>
</div>
</form>
</div>
</div>
</body>
</html>

Bước 9: Gửi emails với Queues Tạo job

php artisan make:job SendPostEmail

Ở file job SendPostEmail.php vừa tạo, sửa lại nó như sau:

<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Mail;
use App\Post;

class SendPostEmail implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $post;

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

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        $data= array(
            'title'=> $this->post->title,
            'body'=> $this->post->body,
        );

        Mail::send('emails.post', $data, function($message){
            $message->from('[email protected]', 'Laravel Queues');
            $message->to('[email protected]')->subject('There is a new post');
        });
    }
}

Sửa lại file PostController.php.
Thêm code này vào đầu file:

Use App\Jobs\SendPostEmail;

Trong function store sửa lại như sau:

public function store(Request $request)
{
        $request->validate([
              'title'=>'required|min:6',
              'body'=> 'required|min:6',
        ]);
        $post = new Post;
        $post->title = $request->title;
        $post->body = $request->body;
        $post->save();
        $this->dispatch(new SendPostEmail($post));
        return redirect()->back()->with('status', 'Your post has been submitted successfully');
}

Đặc biệt bạn nên chú ý đến dòng code này:

$this->dispatch(new SendPostEmail($post));

Để queue được chạy thì bạn sẽ phải chạy lệnh này:

php artisan queue:work

Sau khi chạy lệnh trên, nếu trong trường hợp trên web đã thực hiện tạo post nào đó thì trên command chúng ta sẽ thấy nó chạy như job SendPostEmail.

Tài liệu tham khảo:
https://laravel.com/docs/5.8/queues
https://blog.eduonix.com/web-programming-tutorials/learn-implement-queues-laravel-5/