问题
Why can't I delete these items from my database, they only have one relationship each, and I'm detaching and deleting each respectively. I have 3 tables Vendor, Brand and Product. The error mentions the Products table but there are no relationships in the Vendor table to the Products table, the relationship is with the Brand table and it's a one to one relationship.
Table structure
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');
});
Vendor Model and relationship
class Vendor extends Model
{
protected $hidden = ['created_at','updated_at'];
public function brands(){
return $this->hasMany(Brand::class);
}
}
Brand Model and relationship
class Brand extends Model
{
public function vendor() {
return $this->belongsTo(Vendor::class);
}
}
Product relationship with Brand
public function brand()
{
return $this->belongsTo(Brand::class);
}
Vendor destroy function
public function destroy($id)
{
DB::beginTransaction();
$vendor = Vendor::findOrFail($id);
$vendor->brands()->delete();
$vendor->delete();
DB::commit();
}
Brand destroy function
public function destroy($id)
{
DB::beginTransaction();
$vendor = Brand::findOrFail($id);
$vendor->vendors()->delete();
$vendor->delete();
DB::commit();
}
Product destroy funcion
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();
}
when I try to delete a Vendor I recieve this error
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)
and when I try to delete a Brand I have basically the same error
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)
I'm not sure what I'm doing wrong.
回答1:
Error on Vendor Delete is Because You are deleting Vendor's all Brands which are again related to Products So, without deleting their related products you can't delete them. So, you have to delete products at first. Create a relation of Products on Brand Model
public function products(){
return $this->hasMany(Products::class);
}
Then on Vendor's destroy get its all brands loop through and delete all products.
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's delete get all its products and delete its products first.
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();
I would like to suggest you to use Eloquent's deleting event on all three models then you will not need to care about nested model's foreign key and you will get rid of code repitation. see: https://laravel.com/docs/6.0/eloquent#events
来源:https://stackoverflow.com/questions/57895468/why-cant-i-delete-this-from-my-tables-that-have-relationships