Scope trong Laravel 5.5
Global Scopes Global Scopes cho phép bạn tạo các ràng buộc cho TẤT CẢ các truy vấn tới Model. Trong Laravel, chức năng soft delete sử dụng như một global scopes để thực hiện việc pull "non-deleted" từ các model. Viết một global scopes cho mình sẽ có thể cung cấp sự tiện lợi, dễ dàng , để đảm ...
Global Scopes
Global Scopes cho phép bạn tạo các ràng buộc cho TẤT CẢ các truy vấn tới Model. Trong Laravel, chức năng soft delete sử dụng như một global scopes để thực hiện việc pull "non-deleted" từ các model. Viết một global scopes cho mình sẽ có thể cung cấp sự tiện lợi, dễ dàng , để đảm bảo cho mỗi truy vấn tới Model đều nhận được sự ràng buộc nhất định.
Viết Global Scopes
Việc viết 1 global scopes khá đơn giản. Ta sẽ định nghĩa 1 class, class này sẽ implements từ IlluminateDatabaseEloquentScope interface. Interface này sẽ yêu cầu bạn implements một phương thức : apply. Phương thức apply có thể thêm where trong truy vấn của bạn nếu bạn cần sử dụng nó:
<?php namespace AppScopes; use IlluminateDatabaseEloquentScope; use IlluminateDatabaseEloquentModel; use IlluminateDatabaseEloquentBuilder; class AgeScope implements Scope { /** * Apply the scope to a given Eloquent query builder. * * @param IlluminateDatabaseEloquentBuilder $builder * @param IlluminateDatabaseEloquentModel $model * @return void */ public function apply(Builder $builder, Model $model) { $builder->where('age', '>', 200); } }
Sử dụng
Để đăng kí 1 Global Scopes cho một model, bạn nên thực hiện việc override(ghi đè) lên phương thức boot, sử dụng phương thức addGlobalScope:
<?php namespace App; use AppScopesAgeScope; use IlluminateDatabaseEloquentModel; class User extends Model { /** * The "booting" method of the model. * * @return void */ protected static function boot() { parent::boot(); static::addGlobalScope(new AgeScope); } }
Sau khi đăng kí, truy vấn của bạn sẽ có sự thay đổi theo cách mà bạn đã tạo ra một Global Scopes trong Model. Ví dụ như User::all() sẽ được hiểu là:
select * from `users` where `age` > 200
Anonymous Global Scopes
Eloquent cũng cho phép bạn định nghĩa một Global Scopes sử dụng Closures, điều này khá hữu ích cho các scope đơn giản mà không cần tạo class riêng biệt :
<?php namespace App; use IlluminateDatabaseEloquentModel; use IlluminateDatabaseEloquentBuilder; class User extends Model { /** * The "booting" method of the model. * * @return void */ protected static function boot() { parent::boot(); static::addGlobalScope('age', function (Builder $builder) { $builder->where('age', '>', 200); }); } }
Xóa một Global Scopes
Nếu bạn muốn xóa một Global Scopes, bạn hãy sử dụng phương thức withoutGlobalScope. Phương thức này sẽ chấp nhận tên class của Global Scopes là tham số duy nhất:
User::withoutGlobalScope(AgeScope::class)->get();
Nếu bạn muốn xóa bỏ một vài Global Scope hoặc thậm chí tất cả Global Scopes, sử dụng phương thức withoutGlobalScopes :
// Remove all of the global scopes... User::withoutGlobalScopes()->get(); // Remove some of the global scopes... User::withoutGlobalScopes([ FirstScope::class, SecondScope::class ])->get();
Local Scopes
Local Scopes cho phép bạn định nghĩa tập hợp các ràng buộc chung mà bạn có thể tái sử dụng trong ứng dụng của bạn. Ví dụ bạn có thể cần phải thường xuyên truy xuất tất cả người dùng mà được gọi là "popular users". Để định nghĩa một scope, bạn cần đặt tiền tố scope trong một hàm của Eloquent model. Scope luôn trả về một instance của Query Builder. VD:
<?php namespace App; use IlluminateDatabaseEloquentModel; class User extends Model { /** * Scope a query to only include popular users. * * @param IlluminateDatabaseEloquentBuilder $query * @return IlluminateDatabaseEloquentBuilder */ public function scopePopular($query) { return $query->where('votes', '>', 100); } /** * Scope a query to only include active users. * * @param IlluminateDatabaseEloquentBuilder $query * @return IlluminateDatabaseEloquentBuilder */ public function scopeActive($query) { return $query->where('active', 1); } }
Sử dụng
Với mỗi scope đã được định nghĩa , bạn có thể gọi phương thức của scope khi truy vấn đến model. Tuy nhiên, bạn không nên include tiền tố scope khi mà gọi đến phương thức đó. Bạn cũng sử dụng các truy vấn hay điều kiện như bình thường.
$users = AppUser::popular()->active()->orderBy('created_at')->get();
Dynamic Scopes
Đôi khi, bạn cũng muốn định nghĩa một scope chấp nhận các tham số. Để bắt đầu, thêm các tham số vào scope của bạn. Các tham số của Scope nên được định nghĩa sau tham số $query. Ví dụ:
<?php namespace App; use IlluminateDatabaseEloquentModel; class User extends Model { /** * Scope a query to only include users of a given type. * * @param IlluminateDatabaseEloquentBuilder $query * @param mixed $type * @return IlluminateDatabaseEloquentBuilder */ public function scopeOfType($query, $type) { return $query->where('type', $type); } }
Giờ đây, bạn có thể truyền tham số khi gọi đến Scope:
$users = AppUser::ofType('admin')->get();
Kết Luận
Qua bài viết này, hi vọng các bạn có thể hiểu được lợi ích của Scope cũng như áp dụng được Scope trong Laravel vào project của mình. Mong nhận được ủng hộ của các bạn. Mình xin kết thúc bài viết ở đây. Bài viết dựa trên trang chủ của Laravel. Tham khảo tại : Query Scope trong Laravel 5.5.