Counter Cache trong Laravel
Bài đăng này đã không được cập nhật trong 8 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_countkhi 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_countlê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
commentsvàproductstrong 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_counttrong controllerCommentControllerhoặcCommentServicekhi 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
providersvà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