آموزش مقدماتی لاراول - آشنایی با Soft Delete

گاهی لازم داریم که یک دیتا بصورت موقت حذف شده و امکان بازگردان آن موجود باشد. برای این منظور می‌توان از قابلیت Soft delete در لاراول استفاده کرد. در این آموزش قصد داریم به این ویژگی از لاراول بپردازیم و آنرا در پروژه خودمان پیاده‌سازی کنیم.


بیایید در پروژه‌ای که تا الان کار کردیم و برای کاربر‌ها این امکان رو در نظر بگیریم که اطلاعات یک آهنگ‌ رو بصورت موقت از دیتابیس پاک کنند و یا بصورت همیشگی! برای این منظور ابتدا یک فایل migration  ایجاد می‌کنیم:

php artisan make:migration add_deleted_at_to_songs_table --table songs

ابتدا فایل migration رو بصورت زیر بازنویسی و migrate رو اجرا می‌کنیم. ضمنا توجه کنید من اینجا برای rollback دستور حذف ستونی که اضافه کردم رو هم نوشتم، توجه داشته باشید اگر از mysql استفاده می‌کنید برای اجرای این دستور لازم دارید که پکیج doctrine/dbal هم نصب داشته باشید:

Image for post
Image for post

حالا به مدل آهنگامون برمی‌گردیم و خاصیت SoftDeletes رو به کلاس اضافه می‌کنیم:

// Song model:

use Illuminate\Database\Eloquent\SoftDeletes;

class Song extends Model
{
    use SoftDeletes;
    
    /// 
}

حالا اگه حذفی هم اتفاق بگیره حذف از دیتابیس نیست بلکه دیتا با روشهای معمول قابل رویت نیست برای نمونه اگر یکی از آهنگهارو حذف کنید خواهید دید که در صفحه آهنگها دیگه اون دیتا وجود نداره ولی اگه به جدول آهنگا برگردیم میبینیم که دیتا هنوز وجود داره با این تفاوت که ستون deleted_at مقداردهی شده:

Image for post
Image for post

من برای اینکه آهنگای پاک شده رو هم بتونیم ببینم یک صفحه ساده در نظر گرفتم و تابعی مشابه تابع index در کنترلر آهنگامون تعریف کردم با این تفاوت که در اون از متد withTrashed استفاده کردم. 

public function trashes()
{
    $songs = Song::withTrashed()->paginate(15);
    return view('songs.trashes', compact('songs'));
}

حال اگه به صفحه مورد نظرم بریم آهنگای پاک شده رو هم خواهیم دید:

Image for post
Image for post

اما اگه بخواهیم یک دیتا بطور کامل حذف شود باید از متد دیگری به نام forceDelete استفاده کنید:

public function forceDelete($id)
{
    Song::withTrashed()->find($id)->forceDelete();
    return redirect('songs');
}

نکته‌ای که اینجا وجود داره اینه که شما نمی‌توانید از تزریق مدل استفاده کنید و باید با استفاده از find به همراه withTrashed مدل رو پیدا کنید. مشابه همین دستور رو هم می‌تونید برای بازگردوندن مدل انجام بدید. برای اینکار هم یک تابع وجود داره بنام restore که شیوه کار هم بصورت زیر هست:

public function restore($id)
{
    Song::withTrashed()->find($id)->restore();
    return back();
}

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

Image for post
Image for post

فقط یکم کدمون برای صفحه آهنگای پاک شده باید اصلاح بشه. توجه کنید که زمانی که withTrashed رو استفاده می‌کنید شما به تمام رکوردهای در جدول من جمله آهنگهایی که پاک شدند دسترسی دارید اما ما تنها آهنگایی که در حال حاضر پاک شدند رو می‌خواهیم. پس باید کد بصورت زیر تغییر کنه:

public function trashes()
{
    $songs = Song::withTrashed()
    	->whereNotNull('deleted_at')
    	->paginate(15);

    return view('songs.trashes', compact('songs'));
}

همانطور که مشاهده می‌کنید من از whereNotNull استفاده کردم. البته این دستور معادل دستور زیر هست و باعث میشه تنها رکوردهایی رو داشته باشیم که بصورت موقت پاک شده‌اند (یعنی ستون deleted_at مقدار گرفته باشه)

whereNotNull('deleted_at') == where('deleted_at', '<>', null)

همچنین برای دستور where مواردی اضافی بسیاری وجود داره که ما تا به الان مواردی رو مطرح کردیم در آینده مخصوصا در مبحث روابط کاربردهای بیشتری هم مطرح خواهد شد، اما شما می‌توانید لیستی از این دستورات رو در داک لاراول و در زیر مشاهده کنید:

مورد دیگه تعریف policy مناسب برای حذف کامل و یا بازیابی دیتاست. گاهی ممکنه که نخواهیم هر کاربر بتونه حذف کامل رو انجام بده که برای این منظور بهتره policy مربوط به forceDelete jتنها برای ادمین تعریف کنید.

 اگر با این موضوع آشنایی ندارید پیشنهاد می‌کنم مقاله مربوطه رو حتما مطالعه کنید:


خب امیدوارم از این آموزش لذت برده باشید!