Anophel-آنوفل کوئری های پیشرفته در لاراول با Laravel Scope

کوئری های پیشرفته در لاراول با Laravel Scope

انتشار:
1

لاراول یک فریمورک محبوب PHP است که به دلیل مجموعه ای غنی از ویژگی هایش که توسعه وب را سریعتر و کارآمدتر می کند، شناخته شده است. یکی از این ویژگی ها، Laravel Scopes است که به توسعه دهندگان اجازه می دهد تا محدودیت های کوئری قابل استفاده مجدد و زنجیره ای را برای مدل ها تعریف کنند. در این مقاله به بررسی مفهوم Laravel Scopes می پردازیم و نحوه پیاده سازی آن ها را در پروژه های لاراول خود می آموزیم.

در قدم اول بیاید با لاراول اسکوپ آشنا شویم و سپس با انواع آن و نحوه استفاده از آن آشنا شویم.

لاراول Scope چیست؟

اسکوپ های لاراول Laravel Scope راهی برای کپسوله سازی قید های کوئری در متد های قابل استفاده مجدد و آسان برای استفاده است. آنها روشی مناسب برای اعمال شرایط به کوئری ها ارائه می دهند که به کاهش تکرار کد و بهبود سازماندهی کد کمک می کند.

ما از کوئری اسکوپ ها برای تعریف کوئری های پر مصرف از محدودیت‌های کوئری دیتابیس است. آنها به شما این امکان را می دهند که منطق کوئری را در مدل های Eloquent خود کپسوله کنید و کد شما را خواناتر، قابل نگهداری تر و اصل DRY (Don’t Repeat Yourself) را رعایت می کند.

دو نوع Query Scope در لاراول وجود دارد: الف) Local Scopes ب) Global Scopes

بیایید هر نوع را با جزئیات بررسی کنیم.

اسکوپ های گلوبال:

اسکوپ های گلوبال Global Scopes در خود مدل تعریف می شوند و به طور خودکار برای تمام کوئریهای انجام شده روی آن مدل اعمال می شوند. آنها راهی برای اضافه کردن شرایط کوئری رایج ارائه می دهند که همیشه باید اعمال شوند. به عنوان مثال، ممکن است بخواهید یک محدوده برای بازیابی فقط کاربران فعال یا فقط مقالات منتشر شده به طور پیش فرض اعمال کنید. اسکوپ های گلوبال زمانی مفید هستند که بخواهید شرایط خاصی را در سطح گلوبال بدون افزودن چیزی به هر کوئری اعمال کنید.

بیایید یک کلاس (اسکوپ) جدید برای app/Models/User.php ایجاد کنیم:

ایجاد Scope

برای ایجاد یک اسکوپ گلوبال جدید، از دستور “php artisan make:scope” استفاده کنید. این دستور اسکوپ را تولید می کند و آن را در دایرکتوری app/Models/Scopes برنامه شما قرار می دهد:

php artisan make:scope ActiveUserScope

ایجاد یک اسکوپ گلوبال یک فرآیند ساده است. با استفاده از دستور make:scope شروع کنید تا کلاسی تولید کنید که اینترفیس Illuminate\Database\Eloquent\Scope را پیاده سازی کند. این interface اجرای یک متد واحد را الزامی می کند: apply. در متد apply، شما این قابلیت را دارید که در صورت نیاز، محدودیت‌ها یا سایر انواع عبارت‌ها را به کوئری اضافه کنید.



public function apply(Builder $builder, Model $mode): void
{
	$builder->where('is_active',true);
}

آشنایی با ادغام مستمر و استقرار مدام

استفاده از گلوبال Scope

برای اعمال یک اسکوپ گلوبال به یک مدل، متد booted مدل را override کنید و متد addGlobalScope مدل را فراخوانی کنید. متد addGlobalScope نمونه ای از اسکوپ شما را به عنوان تنها آرگومان خود در نظر می گیرد:

protected static function booted():void
{
	static::addGlobalScope(new ActiveUserScope());
}

پس از افزودن scope در مثال بالا به مدل App\Models\User، فراخوانی متدهای ()all(),get(),first و غیره، کوئری SQL زیر را اجرا خواهید کرد:

select * from `users` where `is_active` = true

اسکوپ های گلوبال ناشناس

Eloquent انعطاف‌پذیری را برای تعریف اسکوپ های گلوبال با استفاده از closures فراهم می‌کند، که به ویژه برای ایجاد اسکوپ های ساده که نیازی به کلاس اختصاصی ندارند، مفید است. هنگام استفاده از یک closure برای تعریف یک اسکوپ گلوبال، یک نام اسکوپ سفارشی را به عنوان اولین آرگومان برای متد addGlobalScope مشخص کنید:

protected static function booted():void
{
	static::addGlobalScope('activeUser', function(Builder $builder){
		$builder->where('is_active',true);
	);
}

حذف اسکوپ های گلوبال

برای حذف یک اسکوپ گلوبال از یک کوئری خاص، از متد withoutGlobalScope استفاده کنید. این متد نام کلاس اسکوپ گلوبال را به عنوان تنها آرگومان خود می گیرد:

User::withoutGlobalScope(ActiveUserScope::class)->get();

از طرف دیگر، اگر اسکوپ گلوبال را با استفاده از یک closure تعریف کرده اید، نام رشته ای را که به اسکوپ گلوبال اختصاص داده اید ارائه دهید:

User::withoutGlobalScope('activeUser')->get();

برای حذف یک یا چند مورد از اسکوپ های گلوبال یا حتی همه آنها، می توانید از متد بدون GlobalScopes استفاده کنید:

// Remove all scopes...
User::withoutGlobalScopes()->get();

// Remove specific scopes...
User::withoutGlobalScopes([
    ActiveUserScope::class,
    HasEmailVerifiedScope::class
])->get();

اسکوپ های محلی

اسکوپ های لوکال به عنوان متد هایی در مدل تعریف می شوند و می توان از آنها برای اعمال محدودیت های کوئری بر اساس هر استفاده، استفاده کرد. این اسکوپ ها را می‌توان به کوئری ها متصل کرد و زمانی مفید هستند که می‌خواهید شرایط خاصی را به صورت پویا بر اساس ورودی کاربر یا عوامل دیگر اعمال کنید. اسکوپ های لوکال روشی انعطاف پذیر برای افزودن شرایط به کوئری ها بدون درهم ریختن کد Controllers/Services/Repositories ارائه می کنند.

اسکوپ ها باید به طور مداوم یا همان نمونه سازنده query یا void را برگرداند:

<?php

namespace App\Models;

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

class User extends Model
{
    /**
    * @param Builder $builder
    * @return void
    */
    public function scopeEmailVerified(Builder $builder): void
    {
        $builder->whereNotNull('email_verified_at');
    }


    /**
    * @param Builder $builder
    * @return void
    */
    public function scopeActiveUser(Builder $builder): void
    {
        $builder->where('is_active', true);
    }
}

آشنایی با تست نویسی در لاراول با PEST

استفاده از یک اسکوپ محلی

پس از تعریف scope، می توانید متد های آن را هنگام کوئری از مدل فراخوانی کنید. با این حال، توجه به این نکته مهم است که هنگام فراخوانی متد نباید پیشوند scope را وارد کنید. همچنین می‌توانید فراخوانی اسکوپ های مختلف زنجیره‌ای کنید:

use App\Models\User;
 
$users = User::emailVerified()->activeUser()->get();

کد SQL آن به صورت زیر خواهد بود:

select * from `users` where `email_verified_at` is not null and `is_active` = true

برای ترکیب چندین اسکوپ مدل Eloquent با استفاده از یک عملگر کوئری، ممکن است لازم باشد از closure ها برای دستیابی به گروه‌بندی لایجکال صحیح استفاده کنید:

User::emailVerified()->orWhere(function (Builder $query) {
    $query->activeUser();
})->get();

کد SQL آن به صورت زیر خواهد بود:

select * from `users` where (`email_verified_at` is not null or (`is_active` = true));

با این حال، از آنجایی که این کار می‌تواند دست و پا گیر شود، لاراول یک متد «مرتبه بالاتر» یا «Where» را ارائه می‌کند که به شما امکان می‌دهد بدون نیاز به closures، اسکوپ ها را به‌طور روان به هم متصل کنید:

User::emailVerified()->orWhere->activeUser();

اسکوپ های دینامیک

گاهی اوقات، ممکن است بخواهید اسکوپی را تعریف کنید که پارامترها را بپذیرد. برای انجام این کار، به سادگی پارامترهای اضافی خود را به متد اسکوپ خود وارد کنید. پارامترهای Scope باید بعد از پارامتر query$ اعلام شوند:

/**
* @param Builder $query
* @param string $role
* @return void
*/
public function scopeOfRole(Builder $query, string $role): void
{
    $query->where('role', $role);
}

پس از افزودن آرگومان های مورد نیاز به متد scope، می توانید این آرگومان ها را هنگام فراخوانی scope ارسال کنید:

$users = User::ofRole('admin')->get();

پیاده سازی اسکوپ های لاراول

اغلب نیاز به ایجاد Scope های زیادی وجود دارد. برای جلوگیری از ایجاد یک کلاس بیش از حد بزرگ با خطوط متعدد کد (scopes)، می توانید از یک Trait استفاده کنید که در آن تمام اسکوپ های شما تعریف می شود:

use App\Models\User\UserScopeHelper;

class User extends Model
{
    use UserScopeHelper;

    /** Your code */
}

خودم از این روش استفاده می کنم و توصیه می کنم در صورتی که اسکوپ های زیادی نیاز به تعریف دارید این روش باعث کد نویسی تمیز می شود و در هنگام دیباگ نیز سرعت تان را بیشتر خواهد کرد.

تست اسکوپ ها

تست نویسی بخش جدایی ناپذیر در کد نویسی است. تست اسکوپ ها برای اطمینان از اینکه آنها مطابق انتظار رفتار می کنند بسیار مهم است. در اینجا مثالی از نحوه تست یک اسکوپ محلی آورده شده است:

public function testActiveScope()
{
    User::factory()->count(3)->create(['status' => 'active']);
    User::factory()->count(2)->create(['status' => 'inactive']);
    
    $activeUsers = User::active()->get();
    $this->assertCount(3, $activeUsers);
    $this->assertTrue($activeUsers->every(fn ($user) => $user->status === 'active'));
}

آشنایی با کد نویسی تمیز در لاراول

مزایای لاراول Scope

1. قابلیت استفاده مجدد کد:  اسکوپ ها به شما امکان می دهد یک بار محدودیت های کوئری را تعریف کنید و از آنها در بخش های مختلف برنامه خود استفاده مجدد کنید. این به حذف کدهای تکراری کمک می کند و کدهای تمیزتر و قابل نگهداری تر را ترویج می کند.در ابتدای این مقاله نیز گفتیم باعث رعایت کردن اصل DRY می شود.


2. خوانایی بهبود یافته: با کپسوله کردن محدودیت‌های کوئری در متدهای نام‌گذاری شده، اسکوپ ها کد را گویاتر و درک آن ها آسان‌تر می‌کنند. Scope ها همچنین به کاهش نویز شرایط کوئری تکراری کمک می کنند و در نتیجه کوئری های تمیزتر و خواناتر می شوند.


3. انعطاف پذیری: اسکوپ های لاراول انعطاف پذیری را در افزودن شرایط به صورت پویا به کوئری ها ارائه می دهند. با اسکوپ های محلی، می‌توانید به راحتی چندین متد اسکوپ را بر اساس شرایط مختلف زنجیره‌ای کنید و کد خود را با نیازهای متغیر سازگارتر کنید.

 

بهترین روش ها برای پیاده سازی اسکوپ های لاراول

پیاده‌سازی اسکوپ های لاراول نیازمند توجه به جزئیات و بهترین روش ها برای اطمینان از اجرای روان و مؤثر کد است. در اینجا شش روش برتر برای پیاده سازی اسکوپ های لاراول در پروژه های شما آورده شده است:


1. نام اسکوپ مناسب را انتخاب کنید : نام اسکوپ باید رفتار دقیق کوئری را منعکس کند. یک نام توصیفی و مختصر درک هدف اسکوپ را آسان تر می کند.


2. از Scopes به طور محدود استفاده کنید : اسکوپ های بیش از حد می تواند حفظ کد شما را سخت کند. استفاده از scope ها را تنها زمانی در نظر بگیرید که انتظار دارید به طور مکرر از کد استفاده مجدد کنید.


3. اسکوپ ها را Atomic نگه داری کنید : هر اسکوپ باید فقط یک محدودیت کوئری خاص داشته باشد. این به حفظ وضوح و خوانایی کد شما کمک می کند.


4. از محدودیت‌های Query Builder استفاده کنید : اسکوپ های لاراول می‌توانند از تمام محدودیت‌های query builder موجود در لاراول استفاده کنند. این شامل where ، clauses، joins و limits می شود.


5. استفاده از اسکوپ های محلی : اسکوپ های محلی در داخل یک مدل تعریف می شوند و می توانند در داخل مدل برای فیلتر کردن یا کوئری استفاده شوند. این به حفظ کد تمیز و مختصر کمک می کند.


6. اسکوپ های خود را تست کنید : تست برای اطمینان از اینکه کد شما همانطور که انتظار می رود کار می کند مهم است. تست های واحد ایجاد کنید تا بررسی کنید که اسکوپ به درستی کوئری را فیلتر می کند.


با پیروی از این روش ها، می توانید اسکوپ های لاراول را به طور موثر و کارآمد در پروژه های خود پیاده سازی کنید. اسکوپ های لاراول ابزار قدرتمندی هستند که می توانند به شما کمک کنند تا به کوئری های پایگاه داده سازگار، ایمن و قابل استفاده مجدد در برنامه های لاراول خود برسید.

40 تا از مهم ترین الکونت های لاراول که هر توسعه دهنده لاراول باید بداند.

معماری ماژولار در لاراول : بررسی کامل همراه با مثال


نتیجه

Laravel Scopes یک راه قدرتمند و زیبا برای تعریف محدودیت‌های کوئری قابل استفاده مجدد برای مدل‌ها ارائه می‌کند. با کپسوله کردن شرایط کوئری در اسکوپ، توسعه دهندگان می توانند به کد تمیزتر دست یابند، قابلیت استفاده مجدد کد را افزایش دهند و قابلیت نگهداری برنامه های لاراول را بهبود بخشند. با سهولت پیاده سازی و انعطاف پذیری خود، اسکوپ های لاراول یک ابزار ارزشمند برای هر توسعه دهنده لاراول هستند.

#لاراول#لاراول_اسکوپ#laravel#laravel_scopes
نظرات ارزشمند شما :

در حال دریافت...

مقاله های مشابه

در حال دریافت...