پرش به مطلب اصلی

وابستگی حذف

ماژول DeleteDependency برای جلوگیری از حذف رکوردهایی استفاده می‌شود که در بخش‌های دیگر سیستم وابستگی دارند یا بر اساس یک شرط نباید حذف شوند.

با استفاده از این ماژول می‌توان قبل از حذف رکورد، وابستگی‌های relation، شرط‌های سفارشی و ruleهای مبتنی بر flag را بررسی کرد و پیام مناسب به کاربر نمایش داد.


استفاده در مدل

برای فعال‌سازی قابلیت بررسی وابستگی حذف، trait زیر را به مدل اضافه کنید:

use Dornica\Foundation\DeleteDependency\Traits\HasDeleteDependency;

سپس وابستگی‌های مدل را در متد deleteDependencies تعریف کنید.

<?php

namespace Modules\Shop\app\Models;

use Dornica\Foundation\DeleteDependency\DTO\DeleteDependency;
use Dornica\Foundation\DeleteDependency\Traits\HasDeleteDependency;
use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
use HasDeleteDependency;

public function deleteDependencies(): array
{
return [
DeleteDependency::relation('products')
->label('shop::messages.products'),

DeleteDependency::condition(fn() => !$this->is_locked)
->label('shop::messages.locked_record'),
];
}

public function products()
{
return $this->hasMany(Product::class);
}

public function children()
{
return $this->hasMany(self::class, 'parent_id');
}
}

تعریف وابستگی‌ها

وابستگی بر اساس relation

اگر relation داده داشته باشد، حذف رکورد مسدود می‌شود.

DeleteDependency::relation('products')
->label('shop::messages.products');

در این مثال، اگر relation با نام products دارای رکورد باشد، مدل قابل حذف نیست.

ruleهای مبتنی بر flag

برای شرایط ساده‌تر یا flagهای مدل، می‌توان از DeleteFlagRule استفاده کرد:

DeleteDependency::condition(fn() => !$this->is_locked)->label('shop::messages.locked_record'),
DeleteDependency::condition(fn() => $this->can_delete),

ورودی condition می‌تواند bool یا Closure باشد.


تنظیمات پیش‌فرض

در فایل config/dornica-app.php می‌توان حالت پیش‌فرض نمایش پیام خطای وابستگی حذف را تعیین کرد:

'delete_dependency' => [
'default_mode' => 'general', // first | all | general
'general_message' => 'foundation::messages.delete_not_allow_cause_dependencies',
],
مقدارتوضیح
firstفقط اولین وابستگی مسدودکننده در پیام نمایش داده می‌شود.
allتمامی وابستگی‌های مسدودکننده در پیام نمایش داده می‌شوند.
generalیک پیام عمومی از کلید message نمایش داده می‌شود (بدون ذکر نام وابستگی‌ها).

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


بررسی پیام حذف

برای دریافت پیام خطای حذف:

// استفاده از حالت پیش‌فرض تنظیمات
if ($message = $category->getDeleteErrorMessage()) {
return back()->withFlash($message, 'error');
}

// تعیین حالت به‌صورت دستی (override تنظیمات)
if ($message = $category->getDeleteErrorMessage(DeleteDependencyMode::FIRST)) {
return back()->withFlash($message, 'error');
}

حالت‌های قابل استفاده:

حالتتوضیح
DeleteDependencyMode::FIRSTاولین وابستگی یا rule مسدودکننده را در پیام نمایش می‌دهد.
DeleteDependencyMode::ALLهمه وابستگی‌ها و ruleهای مسدودکننده را در پیام نمایش می‌دهد.
DeleteDependencyMode::GENERALپیام عمومی تنظیم‌شده در config('dornica-app.delete_dependency.general_message') را نمایش می‌دهد.
null (پیش‌فرض)از مقدار تنظیم‌شده در config('dornica-app.delete_dependency.default_mode') استفاده می‌شود.

متدهای کاربردی

$category->hasDependencies();
$category->getBlockingRelation();
$category->getAllBlockingRelations();

$category->hasDeleteFlagBlocks();
$category->getBlockingFlagRule();
$category->getAllBlockingFlagRules();

$category->getAllBlockingLabels();
$category->canBeDeleteOrFail();
$category->deletionBlockMessage();

اگر در زمان حذف، وابستگی فعال وجود داشته باشد، متد canBeDeleteOrFail یک exception از نوع DeletionGuardException پرتاب می‌کند.


attribute قابل حذف بودن

trait به صورت پیش‌فرض attribute با نام deletable را به مدل append می‌کند. حالت نمایش پیام از تنظیمات پیش‌فرض خوانده می‌شود.

$category->deletable->canDelete();
$category->deletable->getMessage();

DeleteProtection Facade

این ماژول یک singleton با نام delete-protection و یک facade برای استفاده مستقیم فراهم می‌کند.

use Dornica\Foundation\DeleteDependency\Facades\DeleteProtection;

DeleteProtection::check($category);
DeleteProtection::message($category);

// تعیین حالت نمایش پیام
DeleteProtection::message($category, DeleteDependencyMode::FIRST);

خروجی متدها:

متدخروجیتوضیح
checkboolمشخص می‌کند مدل قابل حذف است یا نه.
messagestring یا nullپیام مسدود شدن حذف را برمی‌گرداند. حالت پیش‌فرض از config خوانده می‌شود.

حذف محافظت‌شده

برای اجرای حذف از طریق سرویس داخلی:

use Dornica\Foundation\DeleteDependency\Enums\DestroyType;
use Dornica\Foundation\DeleteDependency\Facades\DeleteProtection;

$service = DeleteProtection::destroy()
->model(Category::class)
->target([1, 2, 3])
->atomic()
->execute();

$service->hasError();
$service->getErrors();
$service->getMessage();

حالت‌های حذف:

حالتتوضیح
DestroyType::ATOMICاگر حذف یکی از رکوردها خطا داشته باشد، کل عملیات rollback می‌شود.
DestroyType::PARTIALرکوردهای قابل حذف حذف می‌شوند و خطاهای رکوردهای ناموفق جمع‌آوری می‌شود.

متدهای اصلی builder:

متدتوضیح
modelکلاس مدل مورد نظر برای حذف را مشخص می‌کند.
targetرکورد، شناسه یا آرایه‌ای از شناسه‌ها را مشخص می‌کند.
atomicحذف را در حالت atomic اجرا می‌کند.
partialحذف را در حالت partial اجرا می‌کند.
typeنوع حذف را با enum مشخص می‌کند.
executeعملیات حذف را اجرا می‌کند و DestroyService برمی‌گرداند.

همچنین می‌توان نوع حذف را مستقیم با enum مشخص کرد:

$service = DeleteProtection::destroy(Category::class)
->target([1, 2, 3])
->type(DestroyType::PARTIAL)
->execute();

نکات

  • اگر هیچ وابستگی فعالی وجود نداشته باشد، خروجی getDeleteErrorMessage برابر null است.
  • ابتدا relationها بررسی می‌شوند و سپس ruleهای flag.
  • ترتیب تعریف ruleها مهم است؛ در حالت FIRST اولین مورد مسدودکننده در پیام نمایش داده می‌شود.
  • این ماژول از event حذف مدل استفاده می‌کند، بنابراین حذف مستقیم از query builder مانند Category::where(...)->delete() ممکن است event مدل را اجرا نکند.
  • حالت پیش‌فرض نمایش پیام از config('dornica-app.delete_dependency.default_mode') خوانده می‌شود و در تمام متدها قابل override است.