Deleting from One-to-Many relationship Laravel - php

I have the two following models in one to many relationship:
Category.php
public function post()
{
return $this->hasMany('App\Category', 'category_id');
}
And Post.php
public function category()
{
return $this->belongsTo('App\Post', 'category_id');
}
I delete thee category that has few blog post under it.
Open the blog post whose category is deleted
Gets error as the category doesn't exist anymore
What is the best way to delete the category without causing the error ? Should I set the category_id of post to null while deleting their category ?

Use withDefault for if any category doesn't exist it'll give you null.
Category.php
public function post()
{
return $this->hasMany('App\Post', 'category_id')->withDefault();
}
Post.php
public function category()
{
return $this->belongsTo('App\Category', 'category_id')->withDefault();
}

Maybe this is gonna be the late answer but I will answer for Google searches anyway.
You can handle relationship cascading on the database If you don't want any null error about deleting the models on your project. Write this code to your project table migration.
$table->bigInteger('category_id')->unsigned();
$table->foreign('category_id')->references('id')
->on('categories')->onDelete('cascade');

Related

Laravel one to many relationship for my system

I want to output all the reviews based on one hotel of my system. Currently, i have a system which displays ALL reviews on each hotels. I have the following code
PostsController:
public function show($id)
{
$post = Post::find($id);
$review = Review::all();
return view('posts.show', compact('post', 'review'));
}
Posts.php:
protected $tables='posts';
function review()
{
return $this->hasMany('App\Review');
}
}
Review.php:
protected $tables='reviews';
function post()
{
return $this->hasMany('App\Post', 'posts_title', 'title');
}
I want to return matching reviews for the right hotel. I want to return posts_title (main column in posts table) and return the title (column in the reviews table).
Check the name of the file Posts.php According to your post function in Review Model it has to be Post.php. I don't know your database structure looks like but it will be better if you use Laravel best practices id for primary key and post_id for foreign key, Also i think the relation should be one to many it means one post has many reviews like that:
Post.php
public function reviews(){
return $this->hasMany('App\Review');
}
Review.php
public function post(){
return $this->belongsTo('App\Post');
}
Then you can use it like
$post = Post::with('reviews')->whereId($id)->first();
To get more information you can visit https://laravel.com/docs/6.x/eloquent-relationships#one-to-many

Laravel: 2nd level relationship only fetching single row

I am using Laravel 5.6 and I have relation between 3 tables. Cart->cartItem->Images
Here is my controller code:
$cart = Cart::where('created_by_id', Auth::user()->id)->with('cartDetails')->first();
Here is my cart model:
public function CartItem()
{
return $this->hasMany('App\Http\models\CartItem', 'cart_id')->with('images');
}
Here is the model of cartItem:
public function images()
{
return $this->belongsTo('App\Http\models\ProductImage', 'item_id', 'product_id');
}
Now in result I am getting only single image even though I have multiple images in the database. It always picking up the last inserted image.
I want to get all images or at least the first one but not the last one.
Please help.
You should use hasMany() relation instead of belongsTo():
public function images()
{
return $this->hasMany('App\Http\models\ProductImage', 'item_id', 'product_id');
}
if you have multiple images in the database of items then you have to use hasMany() insted of belongsTo().
public function images()
{
return $this->hasMany('App\Http\models\ProductImage', 'item_id', 'product_id');
}
When use belongTo() ?
suppose you have post and comment model. Now you want post of comment . That is inverse of a hasMany relationship.To define the inverse of a hasMany relationship, define a relationship function on the Comment (child) model which calls the belongsTo method
public function post()
{
return $this->belongsTo('App\Post');
}

Using group by and count with laravel eloquent

I have a Forum and Forum Response Model with following database tables:
forum.id
forum_response.id
forum_response.forum_id
forum_response.user_id
forum_response.text
The Forum Model relationship is:
public function responses()
{
return $this->belongsToMany(ForumResponse::class, 'forum__responses');
}
and the Forum Response relationship:
public function Forum()
{
return $this->belongsTo(Forum::class);
}
I would like to get the number of unique responses for a specific Forum, grouped by the user_id. I have tried the following return $this->hasMany(ForumResponse::class)->groupBy('user_id')->count(); but this is returning a higher value than I'm expecting.
Even though, I feel you have something wrong in your structure. But for now, you have an error in your relationships. Just change belongsToMany to hasMany
change this
public function responses()
{
return $this->belongsToMany(ForumResponse::class, 'forum__responses');
}
to this
public function responses()
{
return $this->hasMany(ForumResponse::class, 'forum__responses');
}

Retrieving collection from linked eloquent models laravel

I am using laravel 5.3 and need a bit of help with Eloquent model queries. I have three models (UserDetails, Categories, Articles). I have a relationship between UserDetails->Categories (belongstoMany), and a relationship between Categories->Articles (belongstoMany) which work well. However how would I go about getting the relationship data between Userdetails->Categories->Articles.
Each individual relationship is working fine i.e. Userdetails::find(1)->categories and Categories::find(1)->Articles.
I have a feeling that scopes may be the answer but they don't seem to work when I've attempted it.
Relationships in models
UserDetails.php
public function Categories(){
return $this->belongstoMany('App\Categories', 'users_cats', 'user_id','cat_id');
}
Categories.php
public function articles(){
return $this->belongsToMany('App\Article', 'article_categories', 'categoryID', 'articleID');
}
Ive looked into HasManyThrough function but again, I'm having issues implementing it, as far as I can see it should be
return $this->hasManyThrough('App\Article', 'App\Categories', TertiaryForeignKey, FinalForeignKey, LocalForeignKey);
My tables are set up as
articles_categories pivot table
articleID – primary key of the article
categoryID – primary key of the category
users_cats pivot table
user_id – primary key of the userdetails
cat_id – primary key of the categories
Based on this it the hasManyThrough should look like this?
public function articles(){
return $this->hasManyThrough('App\Article', 'App\Categories', 'user_id', 'articleID', 'id');
}
however this returns the error
Column not found: 1054 Unknown column 'categories.user_id' in 'field list'
update
So if you want to have this kind of relationship
userdetails->categories->articles
then you need to make this:
Userdetail model:
public function categories()
{
return $this->hasMany(Category::class);
}
public function articles()
{
return $this->hasManyThrough(Article::class, Categories::class);
}
Category model:
public function userdetails()
{
return $this->belongsTo(Userdetails::class);
}
public function categories()
{
return $this->hasMany(Category::class);
}
Article model:
public function categories()
{
return $this->belongsToMany(Category::class);
}
Then you can call UserDetails::find(1)->articles->get(); directly
You just need to declare the relationship like this in the
UserDetails.php model:
public function categories()
{
return $this->hasMany(Categories::class);
}
in Categories.php model:
public function articles()
{
return $this->hasMany(Articles::class);
}
Then you can retrieve the collection of categories in your controller:
$userdetails = UserDetails::get();
pass that $categories variable into your View and display each record with an foreach loop (where the articles is the function in your model)
#foreach($userdetails->categories as $usercategories )
<div> {{$usercategories->name}} </div>
#foreach($usercategories->articles as $categoryarticles )
<div> {{$categoryarticles->name}} </div>
#endforeach
#endforeach
with the second foreach you will access the articles of the categories that belongs to the user.

Semi-complex Eloquent query

I am working on a eloquent query to compile a newsletter but I have hit a brick wall.
What I'm trying to do is create a UI where the user can select a publication and date. Ideally it would then compile a list of that publication's categories (where stories > 0) and stories belonging to it.
Here are my 3 models:
Story
public function user()
{
return $this->belongsTo('User', 'user_id');
}
public function publication()
{
return $this->belongsTo('Workbench\Dailies\Publication', 'publication_id');
}
public function category()
{
return $this->belongsTo('Workbench\Dailies\Category', 'category_id');
}
Publication
public function story()
{
return $this->belongsTo('Workbench\Dailies\Story');
}
public function stories()
{
return $this->hasMany('Workbench\Dailies\Story', 'publication_id');
}
public function category()
{
return $this->belongsTo('Workbench\Dailies\Category', 'publication_id');
}
Category
public function story()
{
return $this->belongsTo('Workbench\Dailies\Story', 'category_id');
}
public function publications()
{
return $this->belongsTo('Workbench\Dailies\Publication', 'publication_id');
}
public function stories()
{
return $this->hasMany('Workbench\Dailies\Story', 'category_id');
}
Here is how my tables look:
Story
content
user_id
publication_id
category_id
publish_date
Publication
id
name
Category
id
name
publication_id
Here is what I currently have in my Repository.
public function compileStories($input)
{
return Category::has('stories', '>', 0)
->with('publications')
->whereHas('stories', function ($query) use ($input)
{
$query->where('publish_date', $input['publish_date']);
$query->where('publication_id', $input['publication_id']);
});
}
Am I headed in the right direction here or is there any way to improve the code above? It is not currently functioning as expected.
There are a couple of things I see here that may help straighten you out.
First - Some of the models have strange relationships without knowing more about your whole application. The Story model does not need the publication relationship since it can be retrieved through the category relationship, unless you have need of it otherwise. The Category model does not need both a story and a stories relationship, again, unless there's more to the story I don't know. In your example, you should only need the hasMany relationship. The Publication model only needs the categories relationship.
Now, after some cleanup of the models, let's look at your query. Using the category model to return your results seems completely appropriate for your desired results. You can check for the publication without having to dive into your stories, though. I haven't tested it, but you may not need the use $input line since $input is in the larger scope. You're also missing a conditional check in your where statments in the whereHas clause. The query should be able to be simplified as follows:
Category::where('publication_id', '=', $input['publication_id'])
->whereHas('stories', function($query)
{
$query->where('publish_date', '=', $input['publish_date']);
})
->get()

Categories