robotsinside/laravel-deletable
Composer 安装命令:
composer require robotsinside/laravel-deletable
包简介
Gracefully handle deletion of Eloquent models with related entities.
README 文档
README
This package can be used to gracefully handle the deletion of Eloquent models which are related to other models through HasOne, HasMany, BelongsTo, BelongsToMany or Morph* relationships.
It provides a number of helpful additions:
- Validate delete requests with the provided
DeletableRequestclass - Check for the existence of related models before soft deleting a model instance
- Emulate the cascade behaviour provided at the DB layer
Table of contents
- Installation
- Usage
- Use cases
- Supported safeDelete modes (use when soft deleting)
- Testing
- Security
- Coffee Time
- License
Installation
-
Run
composer require robotsinside/laravel-deletable. -
Optionally register the service provider in
config/app.php
/* * Package Service Providers... */ \RobotsInside\DeletableServiceProvider::class,
Auto-discovery is enabled, so this step can be skipped.
Usage
Use the RobotsInside\Deletable\Deletable trait in your models. You must also define a protected deletableConfig() method which returns the configuration array.
<?php namespace App; use Illuminate\Database\Eloquent\Model; use RobotsInside\Deletable\Deletable; class Post extends Model { use Deletable, SoftDeletes; protected function deletableConfig(): array { return [ 'relations' => [ 'authors', ] ] } public function authors() { return $this->belongsToMany(Author::class); } }
Use cases
1. Avoid SQLSTATE[23000]: Integrity constraint violation
A Post implements a HasMany relation with a Like model.
<?php $post = Post::create(['title' => 'My post']); $like = new Like; $like->post()->associate($post); $like->save() $post->delete(); // SQLSTATE[23000]: Integrity constraint violation
To avoid this error and provide the user with some more helpful feedback, we can use the DeletableRequest class.
<?php namespace App\Http\Controllers; use App\Post; use RobotsInside\Deletable\Requests\DeletableRequest; class PostController extends Controller { /** * Remove the specified resource from storage. * * @param DeletableRequest $request * @param Post $post * @return \Illuminate\Http\Response */ public function destroy(DeletableRequest $request, Post $post) { $post->delete(); return redirect()->route('posts.index'); } }
Now we can display the Integrity contraint violation as validation errors instead..
<div>
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
</div>
// Output: This Post has one or more Likes.
2. Check if a model is deletable
This feature supports all relation types. It's particularly helpful when Laravel's soft deletes are in use, since soft-deleting always succeeds without throwing an Integrity Constraint Violation error.
<?php $post = Post::create(['title' => 'My post']); $author = Author::create(['name' => 'Billy Bob']); $post->authors()->save($author); if($post->deletable()) { $post->delete(); }
3. Validate deletes
To validate delete requests, you can type-hint the provided RobotsInside\Deletable\Requests\DeletableRequest class in your controller method.
This class will attempt to automatically resolve the model's route binding, however it currently only supports a single URI route binding.
+-----------+--------------+---------------+---------------------------------------------- | Method | URI | Name | Action +-----------+--------------+---------------+---------------------------------------------- | DELETE | posts/{post} | posts.destroy | App\Http\Controllers\PostController@destroy
If your route has more than one binding, such as authors/{author}/posts/{post}, you'll need to create your own form request, which extends DeletableRequest and define a getRouteModel method which returns the models' route binding.
Below is an example for routes with more than one route binding. This is all that is required for validation to kick in.
<?php namespace App\Http\Requests; use RobotsInside\Deletable\Requests\DeletableRequest; class DeletePostRequest extends DeletableRequest { protected function getRouteModel() { return 'post'; } }
As before, type-hint the extended form request in your controller.
<?php namespace App\Http\Controllers; use App\Http\Requests\DeletePostRequest; class PostContoller extends Controller { ... /** * Remove the specified resource from storage. * * @param App\Http\Requests\DeletePostRequest; * @param App\Post $post * @return \Illuminate\Http\Response */ public function destroy(DeletePostRequest $request, Post $post) { $post->delete(); return back(); } }
4. Customising the validation messages
If you don't want to rely on the default validation messages, you can define a deletableValidationMessage method on your model. You are free to add custom messages for each related model that is preventing a delete.
<?php namespace App\Models\Post; use App\Models\Author; use App\Models\Like; use Illuminate\Database\Eloquent\Model; use RobotsInside\Deletable\Deletable; class Post extends Model { use Deletable; public function deletableValidationMessage($model) { switch ($model) { case Like::class: return 'Posts with likes cannot be deleted.'; break; case Author::class: return 'Posts written by authors cannot be deleted.'; break; default: return 'This model cannot be deleted.'; break; } } ...
Supported safeDelete modes (use when soft deleting)
When using the safeDelete method, you have the option of defining a mode to be used when deleting a record. The mode can be set on the model's deletableConfig array.
- exception (default) (optional)
- cascade
- custom
Note that the mode configuration key can be left empty in exception mode, but must be set for cascade and custom modes.
Exception mode (default)
Soft deleting a model in this situation will fail. If the model in question is referenced by another model, an UnsafeDeleteException will be thrown.
<?php $post = Post::create(['title' => 'My post']); $author = Author::create(['name' => 'Billy Bob']); $post->authors()->save($author); Post::find(1)->safeDelete(); // UnsafeDeleteException
Cascade mode
In this mode related models will also be deleted.
<?php use App\Post; $post = Post::create(['title' => 'My post']); $author = Author::create(['name' => 'Billy Bob']); $post->authors()->save($author); Post::find(1)->safeDelete(); // My Post and Billy Bob will be deleted.
Custom mode
- Set mode to
custom. - Set the handler method
- Define the handler method on the model
If soft deleting fails, the handler method is called.
<?php namespace App; use Illuminate\Database\Eloquent\Model; use RobotsInside\Deletable\Deletable; class Post extends Model { use Deletable, SoftDeletes; protected function deletableConfig() { return [ 'mode' => 'custom', 'handler' => 'myHandler', 'relations' => [ 'authors' ] ]; } public function authors() { return $this->belongsToMany(Author::class); } public function myHandler() { app('log')->info('Unsafe delete of ' . __CLASS__); } }
Testing
Run the provided tests:
composer test
Security
If you discover any vulnerabilities, please email robertfrancken@gmail.com instead of using the issue tracker.
Coffee Time
Will work for ☕☕☕
License
The MIT License (MIT). Please see License File for more information.
robotsinside/laravel-deletable 适用场景与选型建议
robotsinside/laravel-deletable 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 1.22k 次下载、GitHub Stars 达 1, 最近一次更新时间为 2020 年 05 月 17 日, 在 PHP 生态内属于活跃度较高的组件。
我们在过去多个企业项目中使用过 robotsinside/laravel-deletable 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 robotsinside/laravel-deletable 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
统计信息
- 总下载量: 1.22k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 1
- 点击次数: 0
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2020-05-17