laravel join multiple tables with nested data - laravel

I have a situation where I need data within data while doing a DB call.
For example I have a post, that has many comments, but then there is a user to that comment in another table.
So I have
$post = Posts::where('id', $id)->with('comments')->first();
and Posts model is
public function comments()
{
return $this->hasMany('App\Models\Comments', 'postId', 'postId');
}
This works well, I get the post and all the comments but now I need to get the users for those comments. How would I include that?

This would be
$post = Posts::where('id', $id)->with('comments', 'comments.user')->first();
or what ever you have called the user relation on the comment. or
class Comment extends Model
{
protected $with = ['user'];
public function user()
{
return $this->belongsTo(User::class);
}
}
Will always return the user with the comment.

Related

Merging two queries into one using Eloquent

I have this two queries to display information in 3 tables Users, Comments, and Posts. so I made this function:
public function show($id)
{
$posts = Post::with(['comments'])->findOrFail($id);
$user = User::find($posts->user_id);
echo "<h1>".$posts->title.'</h1>';
echo "<h2>".$user->name.'</h2>';
foreach ($posts->comments as $comment) {
echo $comment->body.'<br>';
}
}
on this function I using two variable $posts and $user, can I merge this two variable using eloquests command like Post::with(['user','comments'])'? so I can use just $posts variable and use it like $posts->users->name to access user name.
i was trying using this way:
$posts = Post::with(['comments','users'])->findOrFail($id);
but when i echo the post it showing that the user was null:
{"id":1,"user_id":1,"title":"Oleh id 1","body":"ini adalah content","created_at":"2017-10-18 03:25:54","updated_at":"2017-10-18 03:25:54","comments":[{"id":1,"post_id":1,"body":"Keren banget deh artikelnya, TOP","created_at":"2017-10-18 03:43:50","updated_at":"2017-10-18 03:43:50"},{"id":2,"post_id":1,"body":"Keren banget deh artikelnya, TOP","created_at":"2017-10-18 03:43:53","updated_at":"2017-10-18 03:43:53"},{"id":3,"post_id":1,"body":"Keren banget deh artikelnya, TOP","created_at":"2017-10-18 03:43:54","updated_at":"2017-10-18 03:43:54"}],"users":null}
Here's my model if you need it. My post model:
class Post extends Model
{
/**
* Get the comments for the blog post.
*/
public function comments()
{
return $this->hasMany('App\Comment');
}
public function users(){
return $this->belongsTo('App\User');
}
}
my Comment model
class Comment extends Model
{
/**
* Get the post that owns the comment.
*/
public function post()
{
return $this->belongsTo('App\Post');
}
}
You’ll have an easier time sticking to Laravel’s conventions for naming relationships.
A Post has many Comments, which belong to a User. Given this set up:
class Post extends Model
{
public function comments()
{
return $this->hasMany(Comment::class);
}
}
class Comment extends Model
{
public function post()
{
return $this->belongsTo(Post::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}
You can then query a post’s comments and users like this:
$comments = $post->comments()->with('user')->get();
You could also eager-load the user relation on comments if you always wanted the user returned with a comment:
class Comment extends Model
{
protected $with = ['user'];
public function user()
{
return $this->belongsTo(User::class);
}
}
Then your query would be simplified:
$comments = $post->comments;
Hope this helps you!!
What I am guessing is you want the list of all posts with the users. If relation is defined, try with the join
$posts = DB::table('posts')
->join('users', 'users.id', '=', 'posts.user_id')
->select('posts.*', 'users.name as user_name')
->where('posts.comments', '<>', NULL)
->get();
#NOTE: If you are using soft deletes you might wanna add where('posts.deleted_at', null)
After couple of days searching finally i got the answer, i can get merge the query like this:
$posts = Post::with(['comments','users'])->findOrFail($id);
but in the Post Model the function not "Users" but "User".

Laravel 5.2 How to delete parent record from belongsTo relationship?

My Pricing model
protected $fillable = [
'zone_id',
'is_short_time',
'is_service_feeder',
'route_id',
'value',
];
public function route()
{
return $this->belongsTo(Route::class);
}
My Route Model
protected $fillable = [
'zone_id',
'from_city_id',
'to_city_id',
'is_in_the_city',
];
public function pricing(){
return $this->hasOne(Pricing::class);
}
Here is my controller
public function feeder_destroy($zoneid, $pricingfeederid)
{
$pricing_feeder = Pricing::find($pricingfeederid)->where('zone_id', $zoneid)->where('is_service_feeder', 1);
$pricing_feeder->route()->delete();
$pricing_feeder->delete();
}
The error says
Call to undefined method Illuminate\Database\Query\Builder::route()
I want to delete pricing record and route record too.
What wrong with my code? How should it's look like?
Any help appreciated.
Your controller should
$pricing_feeder = Pricing::find($pricingfeederid)->where('zone_id', $zoneid)->where('is_service_feeder', 1)->first();
Dont forget first() at the end.
Then use like so $pricing_feeder->route->delete();
Try this... $pricing_feeder->route->delete(); Removing () from route()
Your error is on the relation, not the Parent.
not the fanciest but you can delete the route that comes with pricing by adding this method to your route model
public function delete()
{
// delete all related pricing
$this->pricing()->delete();
// delete the route as well
return parent::delete();
}
then just call $pricing_feeder->route->delete();
Ok so I have this model relationships
In Post model
public function user(){
return $this->belongsTo(User::class);
}
In User model
public function post(){
return $this->hasMany(Post::class);
}
and the following code deleted all the posts and the user
$user = \App\User::findOrFail(1);
$user->post[1]->delete();
$user->delete();
Your code does not work, becouse you need to add a first() method call:
$pricing_feeder = Pricing::find($pricingfeederid)->where('zone_id', $zoneid)->where('is_service_feeder', 1)->first();
Than I'd check the returned object if is null. If is not, than you can delete the related relationship and the model as well.
Also, when calling the delete() methods use the relationships as follows:
$pricing_feeder->route->delete();

Laravel Eloquent eager loading not working

In my blog application there users can post articles and comments on there. When I go to any user profile http://eloquent-laravel.app/user/Name then I want to eagerly loaded all articles and comments of that certain user. Here's my code but it's not eagerly loading all articles and comments.
$user = \App\User::with(['articles', 'comments'])->where('name', $name)->first();
return view('articles.user', compact('user'));
User Model's code
public function articles()
{
return $this->hasMany(Article::class);
}
public function comments()
{
return $this->hasManyThrough(Comment::class, Article::class, 'user_id', 'article_id');
}
How can I eagerly loaded these articles and comments?
But if i remove the where clause then eager loading is working. But I do need to get a certain user with all articles and comments eagerly loaded.
Thanks
Okk try this.. in your Article model add
public function comments()
{
return $this->hasMany(Comment::class);
}
now from your controller or repository add
$user = \App\User::with(['articles.comments' => function ($query)use($userId) {
$query->where('user_id',$userId);
}])->where('name', $name)->get();
here you will get a particular user's all articles along with his comments only
in another situation(like you want all the comments and posts of a user) you can do this :
add this in User Model
public function comments()
{
return $this->hasMany(Comment::class);
}
and then try
$user = \App\User::where('name', $name)->with(['articles', 'comments'])->get();
try this :
$user = \App\User::where('name', $name)->with(['articles', 'comments'])->first();

Laravel 4 - Display username based on ID

I have a posts and a users table.
In the posts table, i have a posts_author which is the ID of the user from the users table.
Is there an easy way to display the email address of the user, which is in the users table?
Cheers,
As long as you've set your relationships up it should just be a simple query.
http://laravel.com/docs/eloquent#relationships
Look at the one to many relationships.
(1 User, Multiple posts)
Remember to set the inverse of the relationship up also
If your model has the right relationships then should be as simple as $post->author->email().
You must tweak the author relationship because Eloquent assumes the key will be named author_id.
// Post
public function author() {
return $this->belongsTo('Author', 'posts_author');
}
// Author
public function posts() {
return $this->hasMany('Post');
}
Remember to use eager loading in case you are retrieving emails from more than one post object, or you will end up with n+1 queries.
Providing that you've configured the relationships properly, it should be pretty easy.
Post Model:
class Post extends Eloquent
{
protected $table = 'posts';
public function author()
{
return $this->belongsTo('User', 'posts_author');
}
}
Then User Model:
class User extends Eloquent
{
protected $table = 'users';
public function posts()
{
return $this->hasMany('Post', 'posts_author');
}
}
Then when loading the post you can do the following.
$post = Post::with('author')->find($id);
This will tell Eloquent to join on the users table and load the user data at the same time. Now you can just access all of the user information like this:
$post->author->username;
$post->author->email;
$post->author->id;
// etc etc
Obviously this is just a skeleton, but the assumption is that you have the rest setup.

Laravel 4.1: proper way to retrieve all morphedBy relations?

Just migrated to 4.1 to take advantage of this powerful feature.
everything seems to work correctly when retrieving individual 'morphedByXxxx' relations, however when trying to retrieve all models that a particular tag belongs to -- i get an error or no results.
$tag = Tag::find(45); //Tag model name = 'awesome'
//returns an Illuminate\Database\Eloquent\Collection of zero length
$tag->taggable;
//returns Illuminate\Database\Eloquent\Relations\MorphToMany Builder class
$tag->taggable();
//returns a populated Collection of Video models
$tag->videos()->get();
//returns a populated Collection of Post models
$tag->posts()->get();
My Tag Model class loooks like this:
class Tag extends Eloquent
{
protected $table = 'tags';
public $timestamps = true;
public function taggable()
{
//none of these seem to function as expected,
//both return an instance of MorphToMany
//return $this->morphedByMany('Tag', 'taggable');
return $this->morphToMany('Tag', 'taggable');
//this throws an error about missing argument 1
//return $this->morphToMany();
}
public function posts()
{
return $this->morphedByMany('Post', 'taggable');
}
public function videos()
{
return $this->morphedByMany('Video', 'taggable');
}
}
And the Post and Video models look like this:
class Post extends Eloquent
{
protected $table = 'posts';
public $timestamps = true;
public function tags()
{
return $this->morphToMany('Tag', 'taggable');
}
}
I am able to add/remove Tags to Posts and Videos as well as retrieve the related Posts, and Videos for any Tag -- however -- what is the proper way to retrieve all Models having the Tag name 'awesome'?
Was able to figure it out, would love to hear comments on this implementation.
in Tag.php
public function taggable()
{
return $this->morphToMany('Tag', 'taggable', 'taggables', 'tag_id')->orWhereRaw('taggables.taggable_type IS NOT NULL');
}
in calling code:
$allItemsHavingThisTag = $tag->taggable()
->with('videos')
->with('posts')
->get();
I just used this on Laravel 5.2 (not sure if it is a good strategy though):
Tag model:
public function related()
{
return $this->hasMany(Taggable::class, 'tag_id');
}
Taggable model:
public function model()
{
return $this->belongsTo( $this->taggable_type, 'taggable_id');
}
To retrieve all the inverse relations (all the entities attached to the requested tag):
#foreach ($tag->related as $related)
{{ $related->model }}
#endforeach
... sadly this technique doesn't offer eager load functionalities and feels like a hack. At least it makes it simple to check the related model class and show the desired model attributes without much fear to look for the right attributes on the right model.
I posted a similar question in this other thread as I am looking for relations not known in advance.

Resources