Counter Cache trong Laravel
Bài đăng này đã không được cập nhật trong 7 năm
1. Vấn đề
Input:
- Cho 2 bảng:
Products
(id
,name
,comment_count
,..) vàComments
(id
,product_id
,content
,..) có quan hệ 1-N.
Output:
- Tự động tăng hoặc giảm
Products
.comment_count
khi tạo hoặc xóa comment.
2. Thực hiện
- Cách 1:
- Cách đơn giản nhất là khi nào khi nào comment mới được tạo ta sẽ thực hiện tăng
comment_count
lên 1 đơn vị, khi nào comment bị xóa ta sẽ giảmcomment_count
đi 1 đơn vị: - Ở đây mình dùng trong Laravel, nên mình sẽ dùng migrate để tạo bảng
Schema::create('products', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->integer('comments_count')->default(0); // This is the counter that you have to add $table->timestamps(); });
Schema::create('comments', function (Blueprint $table) { $table->increments('id'); $table->integer('product_id'); $table->string('content'); $table->timestamps(); });
- Chạy lệnh sau để tạo bảng:
php artisan migrate
- Chạy lệnh sau để tạo bảng:
- Tiếp theo ta cần tạo giữa bảng
comments
vàproducts
trong modelComment
:public function product() { return $this->belongsTo('App\Product'); }
- Đến đây thì xong rồi, ta chỉ cần thêm đoạn tăng giảm
comment_count
trong controllerCommentController
hoặcCommentService
khi xóa hoặc tạo comment mới:public function store(Request $request) { $data = $request->only(`content`, `product_id`); $comment = Comment::create($data); if ($comment) { $comment->product->increament("comment_count"); } ... }
- Và xóa comment:
public function delete($id) { $comment = Comment::find($id); if ($comment) { $comment->product->decreament("comment_count"); } ... }
- Hoặc nếu bạn không muốn viết xử lý tăng comment_count trong controller hay service, bạn có thể bắt sự kiện
created
,deleted
để tự động tăng comment_count:protected static function boot() { static::created(function ($comment) { $comment->product->increment('comment_count'); }); static::deleted(function ($comment) { $comment->product->decrement('comment_count'); }); }
- Hàm này được viết trong model
Comment
- Hàm này được viết trong model
- Cách trên có vẻ khá dễ và được ae sử dụng khá nhiều đúng không, Ở mình muốn giới thiệu đến 1 cách khác còn dễ hơn nữa:
- Cách đơn giản nhất là khi nào khi nào comment mới được tạo ta sẽ thực hiện tăng
- Cách 2:
-
Sử dụng package Counter Cache for Laravel:
-
Thêm vào dòng sau vào
composer.js
:"kanazaca/counter-cache": "1.0.*"
-
Sau đó chạy lệnh
composer install
để cài đặt package -
Thêm
providers
vào fileconfig/app.php
:'providers' => array( // ... kanazaca\CounterCache\CounterCacheServiceProvider::class, )
-
Đến đây, thay vì làm như cách 1, ta chỉ cần include package vào model Comment và khai báo đúng chuẩn là xong, việc tăng giảm
comment_count
để package lo:namespace App; use Illuminate\Database\Eloquent\Model; use kanazaca\CounterCache\CounterCache; class Comments extends Model { use CounterCache; // you can have more than one counter public $counterCacheOptions = [ 'product' => [ 'field' => 'comment_count', 'foreignKey' => 'product_id', ] ]; public function product() { return $this->belongsTo('App\Product'); } }
-
Nếu bạn muốn filter trước khi tăng count bạn có thể làm như sau:
public $counterCacheOptions = [ 'product' => [ 'field' => 'comment_count', 'foreignKey' => 'product_id', 'filter' => 'CommentValidatedFilter' ] ]; // you can have more than one counter // this code will be executed before the counting (save and update method) public function CommentValidatedFilter() { if ($this->validated) { return true; } return false; }
-
Tài liệu tham khảo Counter Cache for Laravel
All rights reserved