ميزة Soft Delete في Laravel: الحذف الناعم للسجلات
مقدمة
تُعد ميزة Soft Delete (الحذف الناعم) من أهم المميزات التي يوفرها إطار العمل Laravel للتعامل مع حذف السجلات دون فقدانها فعليًا من قاعدة البيانات.
عند تفعيل هذه الميزة على جدول معين، لا يُحذف السجل فعليًا عند استدعاء عملية الحذف، بل يُضاف حقل باسم deleted_at إلى الجدول، وتكون قيمته الافتراضية null. عند حذف السجل، لا يُزال من قاعدة البيانات، بل يتم تحديث هذا الحقل بقيمة timestamp تمثل وقت الحذف.
وبذلك:
- إذا كانت قيمة deleted_at تساوي null → السجل غير محذوف.
- إذا كانت قيمة deleted_at تحتوي على تاريخ → السجل محذوف، والتاريخ يمثل وقت الحذف.
في هذا المرجع سنستعرض كيفية تفعيل واستخدام Soft Delete خطوة بخطوة، بالاعتماد على جدول articles كمثال.
1. تفعيل Soft Delete في ملف Migration
عند إنشاء الجدول لأول مرة
public function up()
{
Schema::create('articles', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->softDeletes();
$table->timestamps();
});
}عند إضافتها لجدول موجود مسبقًا
في حال كان جدول articles موجودًا مسبقًا، ونريد إضافة الحقل لاحقًا، ننشئ migration جديد:
php artisan make:migration add_soft_deletes_to_article_table --table="articles"
public function up()
{
Schema::table('articles', function (Blueprint $table) {
$table->softDeletes();
});
}ثم تنفيذ الأمر:
php artisan migrate
بهذا يتم إضافة حقل deleted_at إلى جدول articles.
2. تجهيز الـ Model
داخل Article Model، نستخدم الـ Trait الخاص بـ SoftDeletes:
class Article extends Model
{
use HasFactory;
use SoftDeletes;
protected $dates = ['deleted_at'];
}3. جلب البيانات العادية
عند استخدام دوال الجلب الافتراضية مثل findOrFail، سيتم استثناء السجلات المحذوفة تلقائيًا (Laravel يضيف شرط WHERE deleted_at IS NULL ضمنيًا):
Route::get('/article/{article}', function ($article) {
return Article::findOrFail($article);
});4. جلب البيانات مع المحذوفة (withTrashed)
إذا أردنا جلب جميع السجلات، بما فيها المحذوفة، نستخدم withTrashed:
Route::get('/article/{article}', function ($article) {
return Article::withTrashed()->findOrFail($article);
});5. عرض السجلات المحذوفة فقط (onlyTrashed)
لعرض السجلات المحذوفة حصرًا، نستخدم onlyTrashed:
$articles = Article::onlyTrashed()->get(); return $articles;
6. استعادة السجلات المحذوفة (restore)
استعادة جميع السجلات المحذوفة
Article::onlyTrashed()->restore();
استعادة سجل معين
Route::get('/article/{article}', function ($article) {
return Article::withTrashed()->findOrFail($article)->restore();
});7. الحذف النهائي للسجلات (forceDelete)
بما أن السجل لا يُحذف فعليًا عند استخدام Soft Delete، فإن حذفه بشكل كامل ونهائي من قاعدة البيانات يتم عبر forceDelete:
حذف جميع السجلات المحذوفة نهائيًا
Article::onlyTrashed()->forceDelete();
حذف السجلات المحذوفة منذ فترة معينة فقط (مثلاً أقدم من 30 يومًا)
Article::onlyTrashed()
->where('deleted_at', '<', Carbon::now()->subDays(30))
->forceDelete();حذف سجل محدد نهائيًا
Article::onlyTrashed()->find(2)->forceDelete();
8. تمرير withTrashed مباشرة على الـ Route (Laravel 8.55+)
ابتداءً من Laravel 8.55، أصبح بالإمكان تمرير withTrashed مباشرة على تعريف الـ Route عند استخدام Route Model Binding، بدلًا من استدعائها داخل جسم الدالة:
Route::get('/article/{article}', function (Article $article) {
return $article;
})->withTrashed();وفي حال كان السجل محذوفًا، ستتم إعادته مع القيمة الظاهرة في حقل deleted_at:
{
"id": 3,
"title": "Sed iusto eius quis.",
"created_at": "2021-09-11T07:59:39.000000Z",
"updated_at": "2021-09-11T10:14:39.000000Z",
"deleted_at": "2021-09-11T10:14:39.000000Z"
}جدول ملخّص للدوال
| الدالة | الوظيفة |
|---|---|
| softDeletes() | إضافة حقل deleted_at في الـ migration |
| SoftDeletes (Trait) | تفعيل السلوك داخل الـ Model |
| withTrashed() | جلب جميع السجلات بما فيها المحذوفة |
| onlyTrashed() | جلب السجلات المحذوفة فقط |
| restore() | استعادة سجل أو سجلات محذوفة |
| forceDelete() | حذف السجل نهائيًا من قاعدة البيانات |
الخلاصة
توفّر ميزة Soft Delete في Laravel طبقة أمان إضافية عند التعامل مع حذف البيانات، حيث تمنح المطور مرونة في:
- حذف السجلات دون فقدانها فعليًا.
- استعادتها لاحقًا عند الحاجة عبر restore().
- عرضها بشكل منفصل عبر onlyTrashed() أو تضمينها عبر withTrashed().
- حذفها نهائيًا عند التأكد من عدم الحاجة إليها عبر forceDelete().
هذه الميزة مفيدة بشكل خاص في الأنظمة التي تتطلب إمكانية التراجع عن الحذف، أو الاحتفاظ بسجل تاريخي للبيانات المحذوفة لأغراض التدقيق (Audit).
بستفيد جدا اتمني المجتوي يستمر متاح ديما وتزيد عليه ربنا يبارك في حضرتك
ربنا يبارك فيك، شكرًا لمتابعتك المستمرة. المحتوى مستمر إن شاء الله، وهناك المزيد قادم قريبًا.
اشكرك على الاسلوب السهل والمباشر والامثلة كتير واضحة استمر نفعك الله ونفع بك
آمين، ونفعك الله بما تتعلم. أحرص دائمًا أن يكون الشرح مباشرًا مع أمثلة عملية تسهّل الفهم، وسعيد أن هذا الأسلوب وصل لك بالشكل المطلوب.
ممتاز ياهندسه
شكرًا جزيلًا لك!
بارك الله فيك
وفيك بارك الله.
ربنا يجزيك كل انا متابع كل درس تنشره ومستفيد جدا أستمر ربنا يباركلك
ربنا يبارك فيك ويجزيك خير، ومتابعتك للدروس أول بأول أكبر دافع للاستمرار. المزيد قادم إن شاء الله.
استمر انت اضافة قوية جداااا للمحتوى العربي ربنا يجازيك خير
شكرًا جزيلًا على هذه الكلمات، وربنا يجزيك خير. هذا بالضبط ما أطمح إليه، تقديم إضافة حقيقية للمحتوى التقني العربي، وتشجيعك يدفعني للاستمرار أكثر.