Soft Delete در Laravel — حذف نرم، بازیابی و forceDelete
«پست را حذف کن» در CMS یعنی معمولاً «از سایت پنهان کن، نه از دیتابیس پاک کن». Soft Delete با ستون deleted_at همین را میدهد — audit trail، بازیابی اشتباه کاربر، و compliance. در این پورتفولیو Post، Category و Tag همه SoftDeletes دارند.
فعالسازی
use Illuminate\Database\Eloquent\SoftDeletes;
class Post extends Model
{
use SoftDeletes;
}
$table->softDeletes(); // migration
رفتار پیشفرض
Post::all() و query عادی رکوردهای حذفشده را نمیبینند — global scope خودکار.
حذف و بازیابی
$post->delete(); // soft
$post->restore(); // بازیابی
$post->forceDelete(); // حذف واقعی از DB
Query با trashed
Post::withTrashed()->find($id);
Post::onlyTrashed()->paginate(20);
Post::withTrashed()->where('slug', $slug)->first();
رابطه و soft delete
اگر parent soft delete شود، children چه؟ خودتان cascade منطقی تعریف کنید — Laravel خودکار cascade نمیدهد مگر در migration foreign key.
// در Observer deleting
$post->comments()->delete(); // soft هر کدام SoftDeletes داشته باشد
unique با soft delete
slug unique بعد از soft delete conflict میدهد — راهحل: unique composite با deleted_at یا append timestamp به slug هنگام delete.
Filament / admin trash
لیست onlyTrashed + action restore و forceDelete — UX حرفهای.
تفاوت Soft Delete و status=archived
archived هنوز در query عادی دیده میشود با فیلتر؛ soft delete از query جدا میشود. گاهی هر دو لازم است.
performance
index روی deleted_at برای جدول بزرگ. بهینهسازی.
جمعبندی
Soft delete برای entityهای قابل بازیابی ضروری است. global scope، Observer برای cleanup.