Laravel Eloquent:带版本控制的分类与产品关联及删除校验实现
嘿,我来帮你搞定这个Laravel里的分类删除校验问题!要实现删除Category时同时检查products和products_version表的关联记录,咱们可以分几步来做:
1. 先搞定基础关联
首先在你的Category模型里,先建立和Product的一对多关联,这是常规操作:
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; class Category extends Model { use SoftDeletes; // 你的fillable属性等其他配置 protected $fillable = ['name', ...]; // 关联Product模型 public function products() { return $this->hasMany(Product::class); }
2. 加入版本表的校验逻辑
核心需求是要检查products_version表,咱们可以利用Laravel模型的deleting事件来拦截删除操作,这样不管是调用delete()还是批量删除,都会触发校验。直接在Category模型的booted方法里写逻辑就行:
protected static function booted() { static::deleting(function ($category) { // 先检查是否有活跃的关联产品 if ($category->products()->exists()) { throw new \Exception('这个分类下面还有关联的产品,不能删除哦!'); } // 再检查产品版本表中是否有该分类的记录 $hasVersionedProducts = \DB::table('products_version') ->where('category_id', $category->id) ->exists(); if ($hasVersionedProducts) { throw new \Exception('这个分类存在关联的产品版本记录,无法删除!'); } }); } }
3. (可选)用Eloquent关联操作版本表
如果你觉得直接用DB门面不够优雅,也可以给products_version表建一个模型,比如ProductVersion:
namespace App\Models; use Illuminate\Database\Eloquent\Model; class ProductVersion extends Model { // 指定表名,因为默认是复数形式,这里要对应你的表名 protected $table = 'products_version'; // 如果版本表没有created_at/updated_at字段,记得关掉timestamps public $timestamps = false; }
然后在Category模型里添加这个关联:
public function productVersions() { return $this->hasMany(ProductVersion::class, 'category_id'); }
这样,版本表的校验代码就可以改成更Eloquent的写法:
if ($category->productVersions()->exists()) { throw new \Exception('这个分类存在关联的产品版本记录,无法删除!'); }
4. 软删除的小提醒
如果你的Category也用了SoftDeletes,上面的deleting事件会在软删除和强制删除时都触发。要是你只想在强制删除的时候做校验,可以加个判断:
static::deleting(function ($category) { // 只有强制删除时才校验 if ($category->isForceDeleting()) { if ($category->products()->exists()) { throw new \Exception('这个分类下面还有关联的产品,不能强制删除!'); } if ($category->productVersions()->exists()) { throw new \Exception('这个分类存在关联的产品版本记录,无法强制删除!'); } } });
这样配置完之后,删除分类时就会自动校验两张表的关联记录啦!
内容的提问来源于stack exchange,提问作者Jelmer Bouman
相关产品推荐
相关产品推荐

