DEV Community

Mahmoud Abdelfadiel
Mahmoud Abdelfadiel

Posted on

Laravel Global Scope

اهلا بيك صديقى مطور لارفيل تعالى انهارده نتعرف على ميزة فى لارافيل اسمها
Laravel Global Scope
باختصار شديد هى كا شرط كده بتطبق على مودل معين أو اكثر من مودل وبالشكل ده هتطبق على اى كويرى خاصة بالمودل من غير ما تكتبها لو مش فاهم تعالى اوضحلك الموضوع اكتر

قبل ما نبدأ تعالى اوضحلك المشكله بمثال عملى فى البدايه

هفترض على سبيل المثال ان عندى فى المشروع متجر للكتب والكتب هذه يتم اضافتها من قبل مستخدمين وانا هنا محتاج المستخدم اللى يقوم بتسجيل الدخول هو اللى يتعرضله الكتب اللى تم اضافتها فقط

ويقدر يتحكم فى الحذف والتعديل وكل العمليات
فا انت هنا مطالب فى كل كويرى تتأكد ان المستخدم اللى مسجل دخول تتأكد انه حقل ال
user_id == auth()->id()

فا بدل ماتكتب ده بقا كل الكويرى اللى هستخدمها ظهر عندنا بقا ال
Laravel Global Scope
عندى منها نوعين هما

  • انك تعملها فى كلاس منفصل وتستخدمها على أكثر من مودل
  • انك تعملها فى نفس المودل

نبدأ الاول

--- فى كلاس منفصل

هنكمل على نفس المثال هننشئى اولا مجلد جديد بداخل ال
app
وليكن اسمه
Scopes
هيكون عندى بالشكل ده
app/Scopes

وهنشأ بداخله ملف وليكن اسمه
AuthorScope.php

فى البدايه سوف نعطى الملف
namespace

<?php 
namespace  App\Scopes;
Enter fullscreen mode Exit fullscreen mode

ثم ننشأ بداخله
class

<?php 
namespace  App\Scopes;
class AuthorScope{

}
Enter fullscreen mode Exit fullscreen mode

ثم نقوم عمل استدعاء لل
Scope interface

<?php 
namespace  App\Scopes;
use Illuminate\Database\Eloquent\Scope;

class AuthorScope implements Scope{

}
Enter fullscreen mode Exit fullscreen mode

بعد ذلك نقوم بعمل فانكشن جديدة اسمها
apply

تأخذ اتنين براميتر الاول هما
Illuminate\Database\Eloquent\Model;
Illuminate\Database\Eloquent\Builder;

<?php 
namespace namespace App\Scopes;

use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

class AuthorScope implements Scope{


   /**
    * @param  \Illuminate\Database\Eloquent\Builder  $builder
    * @param  \Illuminate\Database\Eloquent\Model  $model
    * @return void
    */

   public function apply(Builder $builder, Model $model)
   {
       $builder->where('user_id', auth()->id() );
   }
}
Enter fullscreen mode Exit fullscreen mode

هكذا تعلمنا كيفية انشاء
--- scope
بشكل منفصل
سنتعلم كيفية تطبيقها على اى مودل موجود عندنا بداخل التطبيق
سنكمل على نفس المثال السابق

namespace App\Models;

use App\Scopes\AuthorScope;
use Illuminate\Database\Eloquent\Model;

class Book extends Model
{



   protected static function boot()
   {
       parent::boot();
       static::addGlobalScope(new AuthorScope);
   }
}
Enter fullscreen mode Exit fullscreen mode

وبذلك سوف يتم اضافة هذا الشرط على جميع الكويرى على هذا المودل على سبيل المثال

Book::all(); 
// سيتم اضافة هذا الشرط تلقائيا طالما هذا المودل مرتبط  
// Author Scope
// بمعنى ان الاستعلام السابق هو فى الاصل 
// Book::where( 'user_id' , auth()->id() );
Enter fullscreen mode Exit fullscreen mode

_ملاحظات هامة
_

1- فى حالة اردنا اضافة
select

سوف تكتب
addSelect

على سبيل المثال

<?php 
namespace namespace App\Scopes;

use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

class AuthorScope implements Scope{


   /**
    * @param  \Illuminate\Database\Eloquent\Builder  $builder
    * @param  \Illuminate\Database\Eloquent\Model  $model
    * @return void
    */

   public function apply(Builder $builder, Model $model)
   {
       $builder->addSelect(['id','title' , 'description' , 'user_id','created_at'] );
   }
}
Enter fullscreen mode Exit fullscreen mode

2- فى بعض الحالات نحتاج لعدم استخدام هذا ال
Scope
وفى هذه الحاله نقوم باستخدام

Book::withoutGlobalScopes(AuthorScope::class)->all();
Enter fullscreen mode Exit fullscreen mode

وفى حالة كان يوجد عندنا اكثر من واحد ونريد الغاء نقوم بتمريرهم كا مصفوفة
( Array )

Book::withoutGlobalScopes([AuthorScope::class , OtherScope ::class , .......... ])->all();
Enter fullscreen mode Exit fullscreen mode

وفى حالة الغاء الجميع نترك البارميتر فارغ بهذا الشكل

Book::withoutGlobalScopes()->all();
Enter fullscreen mode Exit fullscreen mode

وبهذا الشكل قد تعرفنا على كيفية الانشاء فى كلاس منفصل وتطبيقه على اى مودل متواجد بداخل التطبيق سنتعرف ايضا على كيفية الاستخدام بداخل المودل فى حالة كان بسيط ولا حاجه لفصله فى كلاس منفصل ستكون الطريقة كالاتى

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

class Book extends Model
{
   /**
    *
    * @return void
    */
   protected static function boot()
   {
       parent::boot();

       static::addGlobalScope('author', function (Builder $builder) {
           $builder->where('user_id',  auth()->id() );
       });
   }
}
Enter fullscreen mode Exit fullscreen mode

فى حالة اذا اردنا عدم استخدامه فى استعلام ما تكون بنفس الطريقه السابقه ولكن استخدام الاسم لانه لايوجد كلاس هنا بهذه الطريقة

Book::withoutGlobalScopes('author')->all();
Enter fullscreen mode Exit fullscreen mode

Top comments (0)