Is it possible to make a multi level relation query with Eloquent on a deeper level than 1 level? My tables look like this :
post_comments-> id|comment|post_id|user_id|...
post_comment_replies-> id|reply|post_comment_id|user_id|...
users-> id|name|....
user_data-> id|avatar|...
And so I want to ask is it possible to get the Comments for a Post with all the Replies and the User Data for the person who replied to a comment in 1 query with Eloquent.
This is how my Comments Model looks like:
class PostComment extends Model{
public function replies(){
return $this->hasMany(PostCommentAwnsers::class);
}
public function user() {
return $this->belongsTo(User::class);
}
public function userInfo(){
return $this->belongsTo(UserInfo::class,'user_id','user_id');
}}
public function index($id){
$posts = Post::find($id);
$postComments = PostComment::where('post_id','=',$id)->paginate(5);
return view('post.show',[
'post' => $post,
'postComments' =>$postComments
]);
}
And as I get all the user data for a Comment I want to get all the user data for the person who replied.
I am really sorry if this has been awnsered or documented somewhere else but I just can't seem to find the exact solution to this problem.
You should look for eager loading : https://laravel.com/docs/5.3/eloquent-relationships#eager-loading
if you want to get all posts and their comments :
$posts = Post::with('comment')->get();
and if you want all posts with comments and replies of the comments :
$posts = Post::with('comment.reply')->get();
Related
To keep things simple, I'll give an example in code to what I'm trying to Achieve.
Let's assume that we have a model called User with the following code:
class User
{
public function posts()
{
return $this->hasOne(Post::class);
}
}
And the Post model look something like this.
class Post
{
public function comments()
{
return $this->hasMany(Comment::class);
}
}
And now what I want to be able to do is for example:
$user = Auth::user();
$comments = $user->post->comments; //here, I only want the "comment_id" and "comment_content" fields to be included, not all the Comment Model fields !
you can simply use hasManyThrough in user model to connect comments table.
read about hasManyThrough here: docs
and after having a relation between user and comments (hasManyThrough)
you can use load (Lazy eager loading) method
there is an piece of code you can use here
$user->load(["comments" => function($q){
$q->select("comment_id","comment_content");
}]);
read more about Lazy eager loading: docs
I have two tables named posts and categories. these two tables have one-to-many relationship and I wrote them in models like this:
class Post extends Model
{
...
public function category()
{
return $this->belongsTo(Category::class, 'category_id', 'id');
}
...
}
class Category extends Model
{
...
public function posts()
{
return $this->hasMany(Post::class, 'category_id', 'id');
}
...
}
This is work fine when I use $post = Post::find($id) in controller and retrieve one post and use $post->category to get category of this post. but what if I want to retrieve all posts and their categories together?
I mean, let's assume that I have 10 posts in DataBase and I have $posts = Post::get(); to get all posts. now, how I can get categories of each post?
One way is loop! for example:
foreach($posts as $post) {
$post['category'] = $post->category;
}
return response()->json($posts);
Yeah! I want to response in Json and I forgot to say earlier, sorry.
Is there better way to do this? I searched and I got nothing by my search. I'll be appreciated if anyone response to my problem. :)
The easiest way to include categories in each post model with json, is simply including it using with() and it will automatically transform it.
return Post::with('category')->get();
In Laravel you do not have to wrap models or collections in response->json(); it will automatically do that.
I have a has many relation between models: post and category in laravel application. I've defined these relations as:
public function category() {
return $this->belongsTo('artSite\category');
}
public function posts() {
return $this->hasMany('artSite\post');
}
Now I'm trying retrieve posts belonging to the particular category which are derived in http request:
Route::get('posts/categories/{categoryName}','postsViewController#showPostGivenCategory')
Below I show my controller function (it does work fine!):
public function showPostGivenCategory($categoryName) {
$category = category::where('category_name','=',$categoryName)-first();
$posts = category::find($category->id)->posts;
return view('pages.homePage')->with('categories',$categories)with('posts',$posts);
}
In this solution I'm creating 2 queries. Is any possible way to create 1 query to retrieve posts of particular category in has many relation?
Something like that doesn't work:
$posts = category::where('category_name','=',$categoryName)->posts;
Could someone help me with this problem? I would be very grateful, greetings.
we can get rid of the second line :
$posts = Category::find($category->id)->posts;
So You can say :
$posts = Category::where('category_name','=',$categoryName)->first()->posts;
I'm new to laravel and I'm using Laravel 5.2 I want to have all the comments of a particular post of a user. My tables are like :
User
-----
id
public function posts() {
$this->hasMany( 'App\Posts' )
}
Post
------
id
user_id
public function user() {
$this->belongsTo( 'App\User' )
}
public function comments() {
$this->hasMany( 'App\Comment' )
}
Comments
----------
id
post_id
public function post() {
$this->belongsTo( 'App\Post' )
}
Now what I want is to get all the post for a perticular user say the logged in user. I can get all the comments by the long way like :
$comments = [];
foreach( Auth::user()->posts as $post) {
foreach( $post->comments as $comment )
{
$comments[] = $comment->title
}
}
But I was wondering how to get the comments without making these loops using the relations only. Thanks in advance.
You can double the relationship from the existing user object:
$posts = \Auth::user()->posts()->with('comments')->get();
It should work for all levels.
In my project I have Organizations with Clients with a link table to Therapists, all multiple, and this works:
Organization::find(1)->clients()->with('therapists')->get();
so your case should work too. Let me know.
Essentially you want to eager load your data using with() and dot notation like so:
$user = User::with('posts.comments')->find(Auth::user()->id);
If you just want the comments, you can do:
$user = User::with('comments')->find(Auth::user()->id);
$comments = $user->comments();
I have three tables like this:
**Users**
id
**Posts**
id
user_id
**Favorites**
id
user_id
post_id
Currently, I made it so when I query my posts for display, it pulls all the related user data who created the post with that row which is great! But what I'm trying to do now is also add to see if the user Authorized (Logged in) has favorited the post (row) so I can display to that they already favorited it. I don't want to re-query for every post (i think its called the N+1 problem?). I'm using Laravel4
Post model
class Post extends Eloquent{
public function user(){
return $this->belongsTo('User');
}
User model
public function posts(){
return $this->hasMany('Post');
}
PostsController
public function index()
{
$posts = Post::with('user')->paginate(25);
return View::make('index', compact('posts'));
}
Step 1. Add favorites relationship in Post model.
public function favorites() {
return $this->hasMany('Favorite');
}
When querying the Model.
$auth_user_id = Auth::user()->id;
$posts = Post::with(array('user', 'favorites' => function($query) use ($auth_user_id){
$query->where('user_id', '=', $auth_user_id);
}))->get();
For more information refer to the eager load constraints,
http://laravel.com/docs/eloquent#eager-loading
Adding a many-to-many relationship using the favorites table as pivot would be one approach.
Add favorites relationship in User model:
public function favorites() {
return $this->belongsToMany('Post', 'favorites');
}
You should then be able to get all favorites by simply accessing
Auth::user()->favorites
To find whether the current post is a favorite, use
$isFavorite = Auth::user()->favorites->has($post->id);