آموزش کامل استفاده از الگوی طراحی Observers در لاراول

آموزش کامل استفاده از الگوی طراحی Observers در لاراول

یکی از امکانات جذاب لاراول پیاده سازی الگوی Observer در ORM قدرتمند آن می باشد تا در هنگام اجرا بتوانیم برخی از فعالیت ها و رویدادها را گوش دهیم و از آنها برای بدست آوردن یا انجام فعالیت های خاصی استفاده نماییم.فرض کنید شما یک مدل Post دارید و می خواید زمانی که مطلب جدید در سایت ارسال می کنید بصورت خودکار slug مربوط به اون مطلب ایجاد و همزمان ذخیره یا ایمیل و پیغام خاصی برای کاربران یا مدیران سایت ارسال شود.

لاراول با استفاده از ORM  قدرتمند خود امکانات بسیار جذابی را برای توسعه دهنده گان وب فراهم آورده است. 

یکی از این امکانات وجود و پیاده سازی الگوی Observer در این ORM قدرتمند می باشد تا در هنگام اجرا برخی از فعالیت ها و رویدادها را بتوانیم گوش دهیم و از آنها برای بدست آوردن یا انجام فعالیت های خاصی استفاده نماییم.

اگر از لاراول (Laravel )  برای انجام پروژه های خود استفاده می کنید، ممکن است شما بخواهید در زمانی که مدل Eloquent شما پردازش می شود فعالیت خاصی را انجام دهید.

 Eloquent Laravel این امکان را برای شما فراهم آورده است تا در زمانی که شما در حال کار با مدل خود هستید، بتوانید برخی اعمال را نیز بصورت خودکار انجام دهید.

شاید هنوز درست متوجه نشده باشید، اما بزارید یه مثال بزنم:

فرض کنید شما یک مدل Post دارید و می خواید زمانی که مطلب جدید در سایت ارسال می کنید بصورت خودکار slug مربوط به اون مطلب ایجاد و همزمان ذخیره یا ایمیل و پیغام خاصی برای کاربران یا مدیران سایت ارسال شود.

A: خوب به کدهای زیر دقت کنید:

 

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    protected $table = 'posts';

    protected $fillable = ['title', 'slug', 'content'];

    protected static function boot()
    {
        parent::boot();
        static::saving(function ($model) {
            $model->slug = str_slug($model->title);
        });
    }
}

همونطور که مشاهده می کنید ما یک تابع بنام boot به مدل خود اضافه کردیم که در هنگام کار با مدل فراخوانی خواهد شد. حال در متد boot ما از تابعی بنام saving استفاده کردیم و تو اون تعریف کردیم که slug ما چطور و با استفاده از فیلد title ایجاد شود.

تابع saving قبل از save (ذخیره) مدل ما فراخوانی خواهد شد، و مواردی که برای آن تعریف کرده ایم اجرا خواهند شد و سپس عملیات ذخیره سازی انجام خواهد شد. 

Eloquent چندین تابع (قلاب) همانند saving را برای کار با مدل و نظارت بر آن برای ما فراهم آورده است که بصورت زیر می باشند:

retrieved: پس از اینکه یک رکورد بازیابی شد

creating:  قبل از اینکه یک رکورد ایجاد شود

created: پس از ایجاد یک رکورد

updating: قبل از بروزرسانی یک رکورد

updated: پس از اینکه یک رکورد بروزرسانی شد

saving: قبل از ذخیره یک رکورد

saved: پس از ذخیره یک رکورد

deleting: قبل از حذف یک رکورد

deleted: پس از حذف یک رکورد

restoring: قبل از اینکه یک رکورد که بصورت softdelete حذف شده بود بازگردانی شود

restored: پس از بازگردانی یک رکورد که بصورت softdelete  حذف شده بود

 

ایجاد Laravel Model Observers

تصور کنید شما در حال ایجاد یک نرم افزار بزرگ می باشد بنابراین اگر بخواهید درمدل خود  هرکدام از عملیات های بالا را انجام دهید، بدون شک مدل شما بسیار شلوغ، ناراحت کننده! خواهد شد!

اما چاره چیست؟

شما می توانید برای اینکار یک کلاس Observers ایجاد و همه رویداد های خود را در آن تعریف کنید.

برای ایجاد یک کلاس Observers شما می توانید در ترمینال خود دستور زیر را وارد نمایید:

php artisan make:observer PostObserver --model=Post

دستور بالا یک کلاس در دایرکتوری app/Observers با نام PostObserver ایجاد خواهد کرد.

حال شما می توانید همه دستورات مربوط به observers مدل خود را در این کلاس قرار دهید. برای نمونه کلاس PostObserver شما بصورت زیر خواهد بود:

namespace App\Observers;

use App\Post;

class PostObserver
{
    /**
     * Handle the post "created" event.
     *
     * @param  \App\Post  $post
     * @return void
     */
    public function created(Post $post)
    {
        //
    }

    /**
     * Handle the post "updated" event.
     *
     * @param  \App\Post  $post
     * @return void
     */
    public function updated(Post $post)
    {
        //
    }

    /**
     * Handle the post "deleted" event.
     *
     * @param  \App\Post  $post
     * @return void
     */
    public function deleted(Post $post)
    {
        //
    }

    /**
     * Handle the post "restored" event.
     *
     * @param  \App\Post  $post
     * @return void
     */
    public function restored(Post $post)
    {
        //
    }

    /**
     * Handle the post "force deleted" event.
     *
     * @param  \App\Post  $post
     * @return void
     */
    public function forceDeleted(Post $post)
    {
        //
    }
}

 

حال برای فعال کردن این کلاس شما باید آن را در   Service Container لاراول register کنید. برای اینکار فایل AppServiceProvider را باز و در متد boot() کد زیر را قرار دهید:

 Post::observe(PostObserver::class);

در نهایت فایل AppServiceProvider بصورت زیر خواهد بود:

namespace App\Providers;

use App\Post;
use App\Observers\PostObserver;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Post::observe(PostObserver::class);
    }
}

 

شما می توانید از هرکدام از توابع مربوط به صدا زدن که نیاز دارید در کلاس Observer خود استفاده نمایید. با این حال برای نمونه ( و البته یادگیری بهتر شما) ما در کلاس خود تنها می خواهیم از تابع saving که قبل از ذخیره سازی رکورد فراخوانی می شود استفاده نمایید. پس کلاس PostObserver ما بصورت زیر خواهد شد:

namespace App\Observers;

use App\Post;

class PostObserver
{
    /**
     * Handle the post "saving" event.
     *
     * @param  \App\Post  $post
     * @return void
     */
    public function saving(Post $post)
    {
        $post->slug = str_slug($post->title);
    }
}

 

با استفاده از کد بالا ما کار ّبخش A را بدون اینکه مدل خود را شلوغ کنیم انجام داده ایم، و به این صورت در هنگام ایجاد یک پست slug آن نیز توسط کلاس Observer ایجاد خواهد شد

 

مثال دو:

برای اینکه بیشتر متوجه قابلیت ها Observer شوید مثال دیگری را با همدیگه مرور خواهیم کرد.

فرض کنید شما یک جدول Post دارید که با جدول comment رابطه ی HasMany  دارد.

آیا اگر شما یک پست را حذف کنید بصورت خودکار نظرات آن پست هم حذف خواهند شد؟ پاسخ خیر است!

ما میتوانیم با استفاده  از Observer های Eloquent این کار را به راحتی انجام دهیم تا در هر بار حذف یک پست، تمام نطرات مربوط به آن پست نیز حذف شود.

برای نمونه مدل پست شما با مدل comment رابطه ای بصورت زیر دارد:

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    protected $table = 'posts';

    protected $fillable = ['title', 'slug', 'content'];

    public function comments()
    {
        return $this->hasMany(Comment::class);
    }
}

 

حال ما میتوانیم قلاب (همون تابع در نظر بگیرید:* ) deleting  رو در کلاس خودمون بصورت زیر بنویسم تا در قبل از حذف یک پست، تمامی نطرات آن حذف شوند:

namespace App\Observers;

use App\Post;

class PostObserver
{
    /**
     * Handle the post "saving" event.
     *
     * @param  \App\Post  $post
     * @return void
     */
    public function saving(Post $post)
    {
        $post->slug = str_slug($post->title);
    }

    /**
     * Handle the post "deleting" event.
     *
     * @param  \App\Post  $post
     * @return void
     */
    public function deleting(Post $post)
    {
        $post->comments()->delete();
    }
}

 

شما می توانید از دیگر متد ها یا قلاب های معرفی شده در مدل خود برای انجام فعالیت های خاص، برای نمونه ارسال ایمیل قبل برای کاربران خاص در هنگام ارسال مطلب جدید، ارسال پیغام برای مدیران در صورت ارسال نظر جدید در سایت و ... به راحتی استفاده نمایید.

 

برخی محدودیت ها:

هنگامی که شما قلاب های  saved یا  saving استفاده می کنید نباید از متد save() برای ذخیره سازی استفاده کنید.

 

نتیجه گیری:

Laravel Model Observers یک قابلیت بسیار کار آمد می باشد که به شما کمک می کند تا بتوانید فعالیت های بیشتری را در هنگام ایجاد، حذف، بروزرسانی مدل های خود انجام دهید.

 

درصورتی که سوالی در مورد این مطلب دارید از بخش نظرات ارسال فرمایید.

 


دسته بندی ها:

لاراول

ارسال نظر

برای اطلاع از پاسخ به نظر شما می توانید ایمیل یا شماره موبایل خود را وارد نمایید. *

ایمیل و شماره موبایل شما کاملا مخفی خواهد ماند و در سایت نمایش داده نخواهد شد. *

اگر نظری برای این مطلب ارسال شد از طریق ایمیل مرا اطلاع بده!
لسیت نظرات
سعید رضایی
عالی بود. ممنون

پاسخ به این نظر