为什么不能从具有关系的表中删除它?

时间:2019-09-11 19:10:39

标签: php database laravel laravel-query-builder

为什么我不能从数据库中删除这些项目,它们每个都只有一种关系,而我却分别分离和删除它们。我有3个表供应商,品牌和产品。该错误提及“产品”表,但“供应商”表与“产品”表之间没有关系,该关系与“品牌”表有关,并且是一对一的关系。

表结构

Schema::create('vendors', function (Blueprint $table)
        {
            $table->increments('id');
            $table->string('name');
            $table->string('image')->nullable();
            $table->timestamps();
        });

Schema::create('brands', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name')->nullable();
            $table->integer('vendor_id')->unsigned();;
            $table->foreign('vendor_id')->references('id')->on('vendors');
            $table->timestamps();
        });

Schema::create('products', function (Blueprint $table) {
            $table->increments('id');
            $table->string('code');
            $table->string('sku')->nullable();
            $table->text('description_spanish');
            $table->text('description_english');
            $table->string('image')->nullable();
            $table->string('discount');
            $table->string('cif')->nullable();
            $table->string('color')->nullable();
            $table->string('color_ab')->nullable();
            $table->integer('brand_id')->unsigned();
            $table->timestamps();

            $table->foreign('brand_id')->references('id')->on('brands');
        });

供应商模型和关系

class Vendor extends Model
{
    protected $hidden = ['created_at','updated_at'];

    public function  brands(){
        return $this->hasMany(Brand::class);
    }
}

品牌模型和关系

class Brand extends Model
{
    public function vendor() {
        return $this->belongsTo(Vendor::class);
    }
}

与品牌的产品关系

public function brand()
    {
        return $this->belongsTo(Brand::class);
    }

供应商销毁功能

public function destroy($id)
    {
        DB::beginTransaction();
        $vendor = Vendor::findOrFail($id);
        $vendor->brands()->delete();
        $vendor->delete();
        DB::commit();

    }

品牌销毁功能

public function destroy($id)
    {
        DB::beginTransaction();
        $vendor = Brand::findOrFail($id);
        $vendor->vendors()->delete();
        $vendor->delete();
        DB::commit();
    }

产品破坏功能

public function destroy($id)
    {
        $product = Product::findOrFail($id);
        DB::beginTransaction();
        $product->sizes()->detach();
        $product->tags()->detach();
        $product->fields()->detach();
        $product->countries()->detach();
        $this->removeProductImage($product);
        $product->exportationFactors()->delete();
        $product->delete();
        DB::commit();
    }

当我尝试删除供应商时,我收到此错误

SQLSTATE[23000]: Integrity constraint violation: 
1451 Cannot delete or update a parent row: 
a foreign key constraint fails (`sondel`.`products`, 
CONSTRAINT `products_brand_id_foreign`FOREIGN KEY (`brand_id`) 
REFERENCES `brands` (`id`)) (SQL: delete from `brands` where 
`brands`.`vendor_id` = 2 and `brands`.`vendor_id` is not null)

当我尝试删除品牌时,我基本上有相同的错误

SQLSTATE[23000]: Integrity constraint violation: 
1451 Cannot delete or update a parent row: 
a foreign key constraint fails (`sondel`.`brands`, CONSTRAINT
 `brands_vendor_id_foreign` FOREIGN KEY (`vendor_id`) 
REFERENCES `vendors` (`id`)) (SQL: delete from `vendors` 
where `vendors`.`id` = 2)

我不确定自己在做什么错。

1 个答案:

答案 0 :(得分:0)

删除供应商的错误是因为您要删除与产品相关的供应商的所有品牌,因此,如果不删除其相关产品,就无法删除它们。 因此,您必须首先删除产品。在品牌模型上创建产品关系

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

然后在供应商销毁的情况下,使所有品牌循环通过并删除所有产品。

DB::beginTransaction();
$vendor = Vendor::findOrFail($id);
$vendor->brands->each(function ($brand) {
    $brand->products->each(function ($product) {
         $product->sizes()->detach();
         $product->tags()->detach();
         $product->fields()->detach();
         $product->countries()->detach();
         $this->removeProductImage($product);
         $product->exportationFactors()->delete();
         $product->delete();
    });
});
$vendor->brands()->delete();
$vendor->delete();
DB::commit();

Same On Brand的删除将获取其所有产品,然后先删除其产品。

DB::beginTransaction();
$brand = Brand::findOrFail($id);
$brand->products->each(function ($product) {
     $product->sizes()->detach();
     $product->tags()->detach();
     $product->fields()->detach();
     $product->countries()->detach();
     $this->removeProductImage($product);
     $product->exportationFactors()->delete();
     $product->delete();
});
$brand->delete();
DB::commit();

我建议您在所有三个模型上都使用Eloquent的delete事件,这样您就不必关心嵌套模型的外键,并且可以摆脱代码重复。参见:https://laravel.com/docs/6.0/eloquent#events