问题描述
我使用这个结构来存储类别。
删除类别时如何删除所有子嵌套类别?
id | 姓名 | parent_id |
---|---|---|
1 | 测试 1 | 0 |
2 | 测试 2 | 1 |
3 | 测试 3 | 2 |
4 | 测试 4 | 3 |
5 | 测试 5 | 0 |
class Category extends Model
{
public function children()
{
return $this->hasMany(self::class,'parent_id','id');
}
public function parent()
{
return $this->belongsTo(self::class,'parent_id');
}
}
Schema::create('categories',function (Blueprint $table) {
$table->id();
$table->string('name');
$table->integer('parent_id');
});
解决方法
一个选项:点击 deleting
钩子,删除所有子项。
//in your model.
protected static function boot() {
parent::boot(); //need to call parent's boot method
static::deleting( function ($category) {
$category->children->each(function($cat){ //edit after comment
$cat->delete();
});
});
}
或者:
//in your model.
protected static function booted() { //booted method,no need to call parent boot
static::deleting( function ($category) {
$category->children()->delete();
});
}
在控制器中的销毁方法中:
public function destroy(Request $request,Category $category) {
$category->delete(); //OR Category::destroy($categoryIdYouWantToDestroy)
return "deleted";
}
调用 delete 方法时会发生什么?
您的模型将调度 deleting
和 deleted
事件。我们在 boot 方法中所做的是监听和响应删除事件。它转换为模型开始删除过程时,检索其子项并首先删除它们,然后删除模型。
了解有关活动的更多信息: https://laravel.com/docs/8.x/eloquent#events
,您可以简单地查询关系并删除所有项目:
$category->children()->delete(); // Run this line BEFORE deleting the category itself
$category->delete();
你想把这些行放在哪里取决于你:
- 如果你只删除一个特定控制器上的类别,你可以把它们放在那里
- 您可以连接到类别删除事件并在那里执行这些操作
- 您可以在类别模型中创建一个方法
deleteAll
,并在需要删除类别时随时调用它
您有两种删除层次结构类别的方法。
- 这个方法很简单:
SELECT * FROM table WHERE primary_key IN ("a","b","c")
- 另一种方式:
通过这种方式,您需要一个从数据库中获取树的查询。
然后你可以找到所有的ID都在你的类别下。
然后你可以删除所有这些 ID。
有关层次结构查询的更多信息,您可以查看:
https://www.mysqltutorial.org/mysql-recursive-cte/
需要更多信息?让我知道;)