Laravel Global Scope
Published: 2022-11-21 11:46:18

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

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

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

فا بدل  ماتكتب ده بقا كل الكويرى اللى هستخدمها ظهر عندنا بقا ال 
**_Laravel Global Scope_**
عندى منها نوعين  هما 
- انك تعملها فى كلاس منفصل وتستخدمها على أكثر من مودل 
- انك تعملها فى نفس المودل 

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

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

فى البدايه سوف نعطى الملف 
namespace 
```php 
<?php 
namespace  App\Scopes;
```
ثم ننشأ بداخله 
class 
```php
<?php 
namespace  App\Scopes;
class AuthorScope{

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

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

class AuthorScope implements Scope{

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

تأخذ اتنين براميتر الاول هما 
Illuminate\Database\Eloquent\Model;
Illuminate\Database\Eloquent\Builder; 
```php
<?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() );
   }
}
```

هكذا تعلمنا كيفية انشاء 
---  scope 
بشكل منفصل 
سنتعلم كيفية تطبيقها على اى مودل موجود عندنا بداخل التطبيق 
سنكمل على نفس المثال السابق 
```php
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);
   }
}
```

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

```php
Book::all(); 
// سيتم اضافة هذا الشرط تلقائيا طالما هذا المودل مرتبط  
// Author Scope
// بمعنى ان الاستعلام السابق هو فى الاصل 
// Book::where( 'user_id' , auth()->id() );
```
**_ملاحظات هامة 
_**
1- فى حالة اردنا اضافة 
select 

سوف تكتب 
addSelect

على سبيل المثال 
```php
<?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'] );
   }
}
```
2- فى بعض الحالات نحتاج لعدم استخدام هذا ال 
Scope 
وفى هذه الحاله نقوم باستخدام 
```php
Book::withoutGlobalScopes(AuthorScope::class)->all();
```
وفى حالة كان يوجد عندنا اكثر من واحد   ونريد الغاء    نقوم بتمريرهم كا مصفوفة 
( Array ) 
```php
Book::withoutGlobalScopes([AuthorScope::class , OtherScope ::class , .......... ])->all();
```

وفى حالة الغاء الجميع نترك البارميتر فارغ بهذا الشكل 
```php
Book::withoutGlobalScopes()->all();
```

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

```php
<?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() );
       });
   }
}
```

فى حالة اذا اردنا عدم استخدامه فى استعلام ما تكون بنفس الطريقه السابقه ولكن استخدام الاسم لانه لايوجد كلاس هنا بهذه الطريقة 
```php
Book::withoutGlobalScopes('author')->all();
```