I got the the problem, that the id's of the FK's for my pivot table get mixed up before insert and thus I get an error because a category with an ID that high isn't available.
Here's how I try to insert:
$newAdvertisement = new Advertisement();
$newAdvertisement->name = $request->name;
$newAdvertisement->save();
$newAdvertisement->advertisementCategories()->attach($request->selectedCategory);
The Advertisement migration and class function:
public function advertisementCategories(): BelongsToMany
{
return $this->belongsToMany(
AdvertisementCategory::class,
'advertisement2advCategory',
'advertisementCategory_id',
'advertisement_id'
);
}
//Advertisement
Schema::create('advertisement', function (Blueprint $table) {
$table->id();
$table->string('name')->default('');
});
And here the category class function and migration:
public function advertisements(): BelongsToMany
{
return $this->belongsToMany(
Advertisement::class,
'advertisement2advCategory',
'advertisement_id',
'advertisementCategory_id'
);
}
Schema::create('advertisement2advCategory', function (Blueprint $table) {
$table->foreignId('advertisement_id');
$table->foreign('advertisement_id')
->references('id')
->on('advertisement')
->onDelete('cascade');
$table->foreignId('advertisementCategory_id');
$table->foreign('advertisementCategory_id')
->references('id')
->on('advertisementCategory')
->onDelete('cascade');
});
In the error message you can clearly see, that the advertisement_id and advertisementCategory_id get mixed up...
In this example an advertisement with the ID 19 has been created and the selected category (that exists) has ID 4, but the generated sql is trying to insert an advertisement with id 4 and a cagetory with id 19. Just How?
I'm using the latest version of laravel and php 8.1.1
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (umarketdb.advertisement2advCategory, CONSTRAINT advertisement2advcategory_advertisementcategory_id_foreign FOREIGN KEY (advertisementCategory_id) REFERENCES advertisementCategory (i) (SQL: insert into advertisement2advCategory (advertisementCategory_id, advertisement_id`) values (19, 4))
You need to switch the order of the 3rd and 4th arguments to belongsToMany. It is a little confusing with how things are named but as per the documentation:
"The third argument is the foreign key name of the model on which you are defining the relationship, while the fourth argument is the foreign key name of the model that you are joining to." - Laravel 8.x Docs - Eloquent - Relationships - Many to Many - Model Structure
So, if you are defining a relationship on the Category model to Advertisement lets say then the 3rd argument is the foreign key that references categories (category_id). The 4th argument is the foreign key that references the other model/table advertisements (advertisement_id).
Related
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');
}
I need to use a many-to-many relationship to one model. I have an Article model, and I want to make a function so that other articles, typically recommended, can be attached to one article.
This is the function, it should work correctly.
$article = Article::where('id', $request->article_id)->first();
$articles_ids = json_decode($request->articles_ids);
$article->articles()->attach($articles_ids);
I have a question about how to create a table of relations in the database and in the model correctly, I did it like this, but even the migration does not work for me
Model
public function articles()
{
return $this->belongsToMany('App\Models\Article');
}
public function article_recommended()
{
return $this->belongsToMany('App\Models\Article');
}
db
Schema::create('article_article_recommended', function (Blueprint $table) {
$table->unsignedBigInteger('article_recommended_id')->nullable();
$table->foreign('article_recommended_id')
->references('id')->on('article_recommended')->onDelete('set null');
$table->unsignedBigInteger('article_id')->nullable();
$table->foreign('article_id')
->references('id')->on('articles')->onDelete('cascade');
});
error in migration
SQLSTATE[HY000]: General error: 1824 Failed to open the referenced table
'article_recommended' (SQL: alter table `article_article_recommended` add constraint
`article_article_recommended_article_recommended_id_foreign` foreign key
(`article_recommended_id`) references `article_recommended` (`id`) on delete set null)
What are you trying to do should be fairly simple , it's like a following system where each user is related to many users ( same model ) but also same table !
you are here trying to create another table which i consider unnecessary , you only need two tables
articles & recommendations
and the recommendation tabel will act as a pivot table for articles with its self thus creating a many to many relationship with the same table .
Article.php
public function recommendations() {
return $this->belongsToMany(Article::class , 'recommendations' , 'article_id' , 'recommended_article_id');
}
create_recommendations_table.php
Schema::create('recommendations', function (Blueprint $table) {
$table->primary(['article_id','recommended_article_id']);
$table->foreignId('article_id');
$table->foreignId('recommended_article_id');
$table->timestamps();
$table->foreign('article_id')->references('id')->on('article')->onDelete('cascade');
$table->foreign('recommended_article_id')->references('id')->on('articles')->onDelete('cascade');
});
usage
$article->recommendations()->attach($articles_ids);
be sure that the ref-column has exact the same type as the source column (signed, unsigned etc.)
I want to know if I can add 2 auto-increment columns in the same table in laravel? but the second has different value to start with it?
uniID I want to start from 43600000,
Schema::create('students', function (Blueprint $table){
$table->increments('id');
$table->increments('uniID');
$table->integer('student_id');
$table->timestamps();});
DB::statement("ALTER TABLE students AUTO_INCREMENT = 43600000;");
Laravel doesn't support this because databases don't generally support it. The increments() and bigIncrements() column types cannot be used multiple times in the same table Schema and will fail on create:
PDOException: SQLSTATE[HY000]: General error: 1 table "students" has more than one primary key
But if uniId will always be 43600000 larger than id, you can use a computed attribute in Eloquent:
class Student
{
public function getUniIdAttribute()
{
return $this->id + 43600000;
}
}
Then you can use this in your controllers or Blade templates:
>>> $user = Student::first()
=> App\Student{#3078
id: 1,
...
}
>>> $student->uniId
=> 43600001
The downside to this approach is that you won't be able to use uniId as a foreign key in other tables.
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.
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();