Всем привет! Хочу расписать для вас инструкцию как быстро реализовать softDeletes в MoonShine
1. В ресурсе добавляем queryTag для того чтобы видеть удаленные записи
public function queryTags(): array
{
return [
QueryTag::make('Deleted', fn(Builder $q) => $q->onlyTrashed())
];
}
2. Опционально, но может пригодится - добавляем возможность просмотра удаленных записей (иначе нас ждет 404 страница)
protected function resolveItemQuery(): Builder
{
return parent::resolveItemQuery()->withTrashed();
}
3. Добавляем кнопки для восстановления удаленных записей и удаления, я не буду перегружать гайд кодом и реализую в режиме async ресурса. Также самостоятельно вы можете продублировать их в остальных методах
public function indexButtons(): array
{
return [
ActionButton::make('Restore')
->method('restore', events: [$this->getListEventName()])
->canSee(fn(Article $model) => $model->trashed()),
ActionButton::make('Force delete')
->method('forceDelete', events: [$this->getListEventName()])
->canSee(fn(Article $model) => $model->trashed()),
];
}
Соответственно если не async то вам необходимо создать ендпоинты и реализовать восстановление и удаление самостоятельно, останется только указать урл у кнопок
Также при необходимости вы можете добавить withConfirm и сделать тоже самое но внутри через formBuilder и метод asyncMethod
4. Собственно реализация методов удаления и восстановления, если пойдете путем своего контроллера то тоже самое будет в нем
public function restore(MoonShineRequest $request): MoonShineJsonResponse
{
/** @var Article $item */
$item = $request->getResource()->getItem();
$item->restore();
return MoonShineJsonResponse::make()->toast('Success');
}
public function forceDelete(MoonShineRequest $request): MoonShineJsonResponse
{
/** @var Article $item */
$item = $request->getResource()->getItem();
$item->forceDelete();
return MoonShineJsonResponse::make()->toast('Success');
}
5. Давайте также наведем красоту и скроем кнопку удаления и массового удаления на странице с активным queryTag
public function getDeleteButton(
?string $componentName = null,
string $redirectAfterDelete = '',
bool $isAsync = true
): ActionButton {
return parent::getDeleteButton($componentName, $redirectAfterDelete, $isAsync)
->canSee(fn(Article $model) => !$model->trashed());
}
public function getMassDeleteButton(
?string $componentName = null,
string $redirectAfterDelete = '',
bool $isAsync = true
): ActionButton {
return parent::getMassDeleteButton($componentName, $redirectAfterDelete, $isAsync)
->canSee(fn() => request()->input('query-tag') !== 'deleted');
}
Вот и все! Вам останется немного навести красоты и добавить условий под свои кейсы
Александр