Скоупи в Laravel є потужним інструментом для фільтрації даних та забезпечення правильного доступу в мультитенантних додатках. Розглянемо різні типи скоупів та їх застосування.
1. Глобальні скоупи
Глобальні скоупи застосовуються до всіх запитів моделі.
Приклад глобального скоупу для фільтрації за проектом:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?php namespace App\Scopes; use Illuminate\Database\Eloquent\Scope; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Builder; class ProjectScope implements Scope { public function apply(Builder $builder, Model $model) { $projectId = request()->header('X-Project-ID'); if ($projectId) { $builder->where('project_id', $projectId); } } } |
Застосування до моделі:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?php namespace App\Models; use App\Scopes\ProjectScope; use Illuminate\Database\Eloquent\Model; class ProjectRole extends Model { protected static function boot() { parent::boot(); static::addGlobalScope(new ProjectScope); } } |
2. Локальні скоупи
Локальні скоупи дозволяють визначати часто використовувані набори обмежень, які можна легко повторно використовувати в додатку.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class ProjectUser extends Model { public function scopeAdmins($query) { return $query->whereHas('roles', function ($q) { $q->where('name', 'admin'); }); } public function scopeActive($query) { return $query->where('status', 'active'); } } |
Використання:
|
1 |
$activeAdmins = ProjectUser::admins()->active()->get(); |
3. Динамічні скоупи
Динамічні скоупи дозволяють передавати параметри для більшої гнучкості.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class ProjectPermission extends Model { public function scopeOfType($query, $type) { return $query->where('type', $type); } } |
Використання:
|
1 |
$readPermissions = ProjectPermission::ofType('read')->get(); |
4. Скоупи для зв’язків
Скоупи можна застосовувати і до зв’язків між моделями.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Project extends Model { public function activeUsers() { return $this->hasMany(ProjectUser::class)->active(); } } |
5. Видалення глобальних скоупів
Іноді потрібно виконати запит без застосування глобального скоупу.
|
1 |
$allRoles = ProjectRole::withoutGlobalScope(ProjectScope::class)->get(); |
Найкращі практики використання скоупів
- Послідовність: Використовуйте скоупи послідовно в усьому додатку для забезпечення цілісності даних.
- Читабельність: Називайте скоупи зрозуміло, щоб їхнє призначення було очевидним.
- Повторне використання: Створюйте скоупи для часто використовуваних запитів, щоб зменшити дублювання коду.
- Тестування: Обов’язково тестуйте скоупи, особливо глобальні, щоб переконатися, що вони працюють правильно в різних сценаріях.
- Продуктивність: Слідкуйте за продуктивністю при використанні складних скоупів, особливо при їх комбінуванні.
Використання скоупів у мультитенантних додатках дозволяє ефективно забезпечувати ізоляцію даних між тенантами та спрощує логіку фільтрації даних у всьому додатку.