Why can't I delete this from my tables that have relationships? - php

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.

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

Related

I cannot delete data which have many-to-many relationship in laravel 9

I am using PHP 8.2.0, MySQL 8.2.0, and Laravel 9.48.0. This is my database migrations file pivot table (category_menu):
public function up()
{
Schema::create('category_menu', function (Blueprint $table) {
$table->foreignId('category_id')->constrained();
$table->foreignId('menu_id')->constrained();
});
}
This is the CategoryController.php:
public function destroy(Category $category)
{
Storage::delete($category->image);
$category->menus()->delete(); // many-to-many relationship
$category->delete();
return to_route('admin.categories.index');
}
Lastly, this is the MenuController.php:
public function destroy(Menu $menu)
{
Storage::delete($menu->image);
$menu->categories()->delete(); // many-to-many relationship
$menu->delete();
return to_route('admin.menus.index');
}
I have tried deleting one of the menu/category, but laravel keeps sending out an error:
SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails (larareserve.category_menu, CONSTRAINT category_menu_menu_id_foreign FOREIGN KEY (menu_id) REFERENCES menus (id))
delete `menus` from `menus` inner join `category_menu` on `menus`.`id` = `category_menu`.`menu_id` where `category_menu`.`category_id` = 4
SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails (larareserve.category_menu, CONSTRAINT category_menu_category_id_foreign FOREIGN KEY (category_id) REFERENCES categories (id))
delete `categories` from `categories` inner join `category_menu` on `categories`.`id` = `category_menu`.`category_id` where `category_menu`.`menu_id` = 7
I thought, this error might have to do with the migration's pivot table (category_menu). But, I just don't know how to fix this. I am currently one month old learning the laravel framework and right now, I am working on the tutorial project from youtube. Please help (educate) me anyone. I am sorry for all inconveniences.
Alright. Already got the solution from Laravel Cannot delete or update a parent row: a foreign key constraint fails
so what I did was, in my database migrations file pivot table (category_menu):
public function up()
{
Schema::create('category_menu', function (Blueprint $table) {
$table->foreignId('category_id')->constrained();
$table->foreignId('menu_id')->constrained()->onDelete('cascade');
});
}
CategoryController.php:
public function destroy(Category $category)
{
Storage::delete($category->image);
$category->menus()->delete(); // many-to-many relationship
$category->delete();
return to_route('admin.categories.index');
}
MenuController.php:
public function destroy(Menu $menu)
{
Storage::delete($menu->image);
//$menu->categories()->delete(); // many-to-many relationship
$menu->delete();
return to_route('admin.menus.index');
}
By adding ->onDelete('cascade') on the migration file, I can already delete the menu. I also put the syntax only on the menu item in the migration file and commented the line to delete the menu's category method on the MenuController, so that whenever I deleted the menu, the category won't be deleted. If I deleted the category, the menu related to it will also be deleted.
This is yet another solution for another type of outcome. Let say, whenever I want to delete the menu, only the menu gets deleted. And whenever I want to delete the category, only the category gets deleted.
Migration File (category_menu):
public function up()
{
Schema::create('category_menu', function (Blueprint $table) {
$table->foreignId('category_id')->constrained()->onDelete('cascade');
$table->foreignId('menu_id')->constrained()->onDelete('cascade');
});
}
CategoryController.php:
public function destroy(Category $category)
{
Storage::delete($category->image);
// $category->menus()->delete(); // many-to-many relationship
$category->delete();
return to_route('admin.categories.index');
}
MenuController.php:
public function destroy(Menu $menu)
{
Storage::delete($menu->image);
// $menu->categories()->delete(); // many-to-many relationship
$menu->delete();
return to_route('admin.menus.index');
}

Laravel 5.4 transaction and one-many relation

I just started laravel but I'm stuck to this point and I don't find a way to do it
Basically I insert an article with a category.
With select2, I select an existing category or I create a new one.
My article model :
public function category(){
return $this->belongsTo('App\Category');
}
My categories model :
public function articles(){
return $this->hasMany('App\Article');
}
My article migration :
public function up()
{
Schema::create('articles', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->longText('content')->nullable();
$table->timestamps();
});
}
My category migration :
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string('nom')->unique();
});
Schema::table('articles', function(Blueprint $table){
$table->integer('category_id')->unsigned()->index();
});
And finally my controller function to store article (I want to use transaction) :
public function store(Request $request)
{
$this->validate($request, [
'numero' => 'required',
'category' => 'required',
'title' => 'required'
]);
$article = new Article();
DB::transaction(function() use ($request) {
$category = Category::firstOrCreate(['nom' => $request->input('category')]);
$article->title = $request->input('title');
$article->save();
});
return response()->json([
'title' => $article->title
]);
}
So I know I don't save category id into article db but my category doesn't even insert, on my debug bar I've got this :
Begin Transaction
select * from batiments where (nom = 'HI') limit 1
Rollback Transaction
And my post page give me this error :
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicata du champ '' pour la clef 'batiments_nom_unique' (SQL: insert into batiments () values ())
Someone knpw how to insert or select if exist category and insert is id into article table ?
Thank
$table->integer('category_id')->unsigned()->index();
You set this field as index, just remove index(). Identity field must have only unique records, but your category_id may have same value many times.
code:
$table->integer('categorie_id')->unsigned();
$table->foreign('categorie_id')->references('id')->on('categories');
Laravel provides support for creating foreign key constraints, which are used to force referential integrity at the database level. For example, let's define a categorie_id column on the articles table that references the id column on a categories table
laravel.com/docs/5.4/migrations#foreign-key-constraints

From campaign table i want to delete campaign but i can't delete..following error occur

SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or
update a parent row: a foreign key constraint fails
(demopurpose_fundraising.campaign_product, CONSTRAINT
campaign_product_campaign_id_foreign FOREIGN KEY (campaign_id)
REFERENCES campaign (id)) (SQL: delete from campaign where id = 60)
campaign table schema :
Schema::create('campaign', function (Blueprint $table) {
$table->engine='InnoDB';
$table->increments('id');
$table->integer('users_id')->unsigned();
$table->foreign('users_id')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade');
$table->string('campaign_name');
$table->float('campaign_goal',8,2);
$table->string('discription',400);
$table->string('image');
$table->string('category');
$table->date('start_date');
$table->date('end_date');
$table->float('total_fund',8,2);
});
campaign_product table schema :
Schema::create('campaign_product', function (Blueprint $table) {
$table->engine='InnoDB';
$table->increments('id');
$table->integer('campaign_id')->unsigned();
$table->foreign('campaign_id')->references('id')->on('campaign')->onDelete('cascade')->onUpdate('cascade');
$table->integer('product_id')->unsigned();
$table->foreign('product_id')->references('id')->on('product')->onDelete('cascade')->onUpdate('cascade');
});
campaign_id is foreign key in campaign_product delete..
I want to delete campaign ..
How to delete campaign product then campaign ??
You cannot delete it unless you remove those campaign_id from campaign_product table. Detach products from the campaign_product table before you delete a campaign. Example:
$campaign = Campaign::query()->findOrFail($id); //find campaign
$campaign->products()->detach($campaign->product); //detach products from `campaign_products` table
$campaign->delete(); //delete the campaign
Read more about detaching many-to-many relationship record: https://laravel.com/docs/5.6/eloquent-relationships#updating-many-to-many-relationships
What you are seeing is you cant delete a model because it still has connection in your database. You want to make a function that first deletes all the relations before deleting the model in question.
Try adding this to you Campaign Model.
protected static function boot() {
parent::boot();
static::deleting(function($campaign) { // before delete() method, call this
$campaign->products()->delete();
// do the rest of the cleanup...
});
}
If you follow the process given in the link in the comments you can prevent this issue from happening in the future.

Laravel Cannot delete or update a parent row: a foreign key constraint fails

For some reason a user cannot delete a post if it has been liked, it was working before but when I linked posts with likes I have been getting this error, I can't even delete it in Sequel Pro, unless I delete the likes associated with the post first.
Error
SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or
update a parent row: a foreign key constraint fails
(eliapi8.likes, CONSTRAINT likes_post_id_foreign FOREIGN KEY
(post_id) REFERENCES posts (id)) (SQL: delete from posts where
id = 149)
Maybe it's my schema?
Posts Schema
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->text('body');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->timestamps();
});
Likes Schema
Schema::create('likes', function (Blueprint $table) {
$table->increments('id');
$table->integer('post_id')->unsigned();
$table->integer('user_id')->unsigned();
$table->foreign('post_id')->references('id')->on('posts');
$table->foreign('user_id')->references('id')->on('users');
$table->softDeletes();
$table->timestamps();
});
I can like and unlike a post, but a user cannot delete a post that has been liked.
PostController.php
public function destroy(Post $post){
$this->authorize('delete', $post);
$postl = Post::with('likes')->whereId($post)->delete();
if ($post->delete()) {
if($postl){
return response()->json(['message' => 'deleted']);
}
};
return response()->json(['error' => 'something went wrong'], 400);
}
Yes, it's your schema. The constraint on likes.post_id will prevent you from deleting records from the posts table.
One solution could be using onDelete('cascade') in the likes migration file:
Schema::create('likes', function (Blueprint $table) {
$table->integer('post_id')->unsigned();
$table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade');
});
This way, when a post is deleted, all related likes will be deleted too.
Or, if you have a relationship from the Post model to the Like model, you can $post->likes()->delete() before deleting the post itself.
I've tested with onDelete('cascade') but in my case it didn't work. The resource I tried to delete had a model with an hasMany()
/**
* Get the departments of the organization
*
* #return void
*/
public function org_departments()
{
return $this->hasMany(Department::class);
}
So, in the destroy() for the controller OrganizationUserController, instead of having
$organization->delete();
I ensured to delete the departments for that organization first and only then the $organization,
$organization->org_departments()->delete();
$organization->delete();
Then it was deleted just fine.
Change on delete to cascade, instead of restrict.
If you are in production mode just php artisan migrate:fresh. It will drop all tables
Note:Record would be deleted from tables
Why you Face this problem??
Actually you cant delete parent table having data in child table .
First you have to delete the child table data only than can you delete the parent table
you have two option to handle this issue.
1)->onDelete('cascade') with your forigner key in migrations
2) if you are in controller first delete $organization->org_departments()->delete(); so all your child would be deleted first than you can delete the parent child $organization->delete();

Laravel 4.2 many to many relation, use something else then the default ID

I have 2 models and both they aren't using the ID from the table, but the field internal_id. So i customized my pivot schema but i got stuck on connecting them. Im getting the error:
General error: 1215 Cannot add foreign key constraint (SQL: alter table `seoshop_category_product` add constraint seoshop_category_product_category_id_foreign foreign key
(`category_id`) references `seoshop_categories` (`internal_id`) on delete cascade)
The code for the migration is:
Schema::create('seoshop_category_product', function(Blueprint $table)
{
$table->increments('id');
$table->integer('category_id')->unsigned()->index();
$table->foreign('category_id')->references('internal_id')->on('seoshop_categories')->onDelete('cascade');
$table->integer('product_id')->unsigned()->index();
$table->foreign('product_id')->references('internal_id')->on('seoshop_products')->onDelete('cascade');
$table->timestamps();
});
Both fields as seoshop_products.internal_id as seoshop_categories.internal_id are existing, column types are both int(11).
Can someone tell me what is going wrong?
Migrations for the tables seoshop_categories and seoshop_products
//seoshop_products
public function up()
{
Schema::create('seoshop_products', function(Blueprint $table)
{
$table->increments('id');
$table->integer('shop_id');
$table->integer('internal_id')->signed()->index();
$table->integer('internal_variant_id');
$table->string('visible');
$table->string('tags');
$table->timestamps();
});
}
//Table seoshop_categories
public function up()
{
Schema::create('seoshop_categories', function(Blueprint $table)
{
$table->increments('id');
$table->integer('internal_id')->signed()->index();
$table->datetime('seoshop_created_at');
$table->datetime('seoshop_updated_at');
$table->text('full_description');
$table->timestamps();
});
}
Okay so now i've create my table, and its working as how it should. I need to get my product with categories (many-2-many). So i use
SEOshopProduct::find(1)->with('categories')->get();
After a dd() the categories are empty and i've looked into my query how it is called:
[8] array(3) {
["query"] "select `seoshop_categories`.*, `seoshop_category_product`.`product_id` as `pivot_product_id`, `seoshop_category_product`.`category_id` as `pivot_category_id` from `seoshop_categories` inner join `seoshop_category_product` on `seoshop_categories`.`id` = `seoshop_category_product`.`category_id` where `seoshop_category_product`.`product_id` in (?)"
["bindings"] array(1) {
[0] 8
}
["time"] 0.37
}
The internal_id's of both products and categories is greater then 10.000 and i dont see it back in the query.
My models:
Product:
public function categories(){
return $this->belongsToMany('SEOshopCategory', 'seoshop_category_product', 'product_id', 'category_id');
}
Categories:
public function products(){
return $this->belongsToMany('SEOshopCategory', 'seoshop_category_product', 'category_id', 'product_id');
}
To setup the foreign key constraint, the field definitions need to match exactly. In this case, however, the seoshop_category_product.category_id field is defined as an UNSIGNED INT, but the referenced seoshop_categories.internal_id field is defined as a SIGNED INT. The same is true for the foreign key for your products.
So, you can either update the internal_id fields on your categories and products tables to be unsigned, or you can update your foreign key fields on your pivot table to be signed.
You can tell Laravel what the local and foreign keys are when you define the relationship in your model...
class Product extends Eloquent
{
public function categories() {
return $this->hasMany('Category', 'internal_id', 'id');
}
}
class Category extends Eloquent
{
public function products() {
return $this->hasMany('Product', 'internal_id', 'id');
}
}

Categories