Laravel eloquent call optional relationship in query - php

I am trying to get a query with Laravel eloquent. I have a table posts which has a morph relationship column author. This author column can refer to a users table or admins table. So this is the way I am getting the author of each posts:
$query = Post::with(['author']);
Now, there's another table I want to include if the author is a user, which is address. The problem is, there's no address relationship in admin table.
So, when I try to do this,
$query = Post::with([
'author' => function ($q) {
$q->with('address');
}
]);
It throws me Illuminate\Database\Eloquent\RelationNotFoundException exception as the relation address is not defined for admin.
How do I solve this problem? I want fetch all the posts with author and include address in the authors that has an address

You can solve that by using the whereHas combine with whereDoesntHave to include both Author who has address and who doesn't have
$query = Post::with([
'author' => function ($q) {
$q->whereHas('address');
$q->orWhereDoesntHave('address');
}
]);
It you only whereHas without orWhereDoesntHave it will return only post which has author with existing address and not author which doesn't have address so to eager load both who has and who hasn't you include both wherHas and orWhereDoesntHave
whereDoesntHave
whereHas
orWhereDoesntHave

Related

Eloquent: Relationships with 3 tables in laravel 5

I have three models namely Header, Details, Item. The Header have id, customer_id, the Details have id, header_id (FOREIGN KEY), and item_id (FOREIGN KEY), and the Item have id, name. Now, I want to relate that tables using laravel eloquent relationships. I've been able to do that with:
class Details extends Model
{
public function item() {
return $this->belongsTo('App\Item', 'bill_item_id');
}
public function header() {
return $this->belongsTo('App\Header', 'header_id');
}
}
The problem is in my controller, I want to get the details but details don't have customer_id.
$detail = Details::where('customer_id', $id)->get();
$detail->load('header', 'item');
The customer_id field is in the header model. if I get all the details, it's working fine but I want to get specific customer.
Write your code like this
$details = Details::with('header')->where('customer_id', $id)->get();
OR
$details = Details::with(['header'=>function($query) use ($id){
$query->where('customer_id', $id);
}])->get()
This will get result depended on your relation.
you can use with for where the field in relation
Details::with([ 'header' => function($query) use ($id) {$query->where('customer_id', $id);}])->get();

Laravel relationship to show all posts by authors that they follow

Can normally figure these relationships out but stumped on this one.
I have a basic blog platform that allows user to sign up and post blog posts.
Users can also follow other users.
I am trying to make a view where I can see all of the blog posts by the authors that I follow
I have the normal users table, and then a blog posts table which contains the user_id of the creator.
For followers, I then have a pivot table called followers which has user_id and follower_id.
This is my basic line to get all posts:
$posts = Post::orderBy('created_at', 'DESC')->get();
How can I change that so it only shows the posts where there post user_id is a field that matches in the followers table?
Thanks.
You may try something like this:
App\User Model:
public function favoriteAuthors()
{
return $this->belongsToMany(
User::class, // as Author
'followers', // pivot table
'follower_id', // as follower_id
'user_id', // as author_id
);
}
public function posts()
{
return $this
->hasMany(Post::class, 'user_id', 'id')
->orderBy('created_at', 'DESC');
}
Then load all posts of your favorite authors:
$posts = User::with('favoriteAuthors.posts')->find(auth()->user()->id);
Also you can use something like this:
if($me = auth()->user()) {
$me->load(['favoriteAuthors.posts']);
}
Now the $me will contain users that you follw and each users will contain their posts.

Laravel simple constraint on eager load

I have a user model, which belongs to one site. One site can have many users.
User table
id
name
email
....
company_site_id
Site table
id
name
The relationship is defined in User as follows:
public function site()
{
return User::belongsTo('App\CompanySite', 'company_site_id', 'id');
}
I want to simply get all users assigned to a site (lets say with a site ID of 1).
$users = \App\User::with(array('site' => function($query)
{
$query->where('id', '=', 1);
}))->get();
dd(count($users));
However this is returning all of the users irrespective of their site.
You are getting all the users that is why, with the use of ->get();.
Use the whereHas method. This will query your relationship and return only the models that have the relation results you are wanting/querying;
$users = User::whereHas('site', function($q)
{
$q->where('id', '=', 1);
})->get();
So Users that have site with an id of 1 will be returned in this instance.

Select a table based on select result from another table

I have a table Registrationrequests where I have course_id and user_id and some other field.
$users_id = Registrationrequest::where('course_id', $query_course_user)->where('registered', 1)->get();
From the above query it gives me an array of result. But I need to take the details of these user_id from another table Users. I'm using Laravel. Table models are Registrationrequest and User
How can I get the user details from the above select result? I'm not that good in Joins. Any advice?
Use Eloquent's whereHas method:
$courseId = Request::get('course_id');
$users = User::whereHas('registrationRequests', function($query) use ($courseId)
{
$query->where('course_id', $courseId)->where('registered', 1);
});
This assumes you have set up the proper relationship in your User model. If not, add this method to your user model:
public function registrationRequests()
{
return $this->hasMany('Registrationrequest');
}

Laravel eager loading - relationship query

Say I have this 3 tables Blog, Post, Comment which has corresponding models Blog, Post, Comment.
No here is the relation between them:
Blog has many Post, posts()
Post belongs to Blog, blog()
Post has many Comment, comments()
Comment belongs to Post post()
Now I want to execute some query like this:
Blog::with(array('posts.comments' => function($q)
{
//query Post columns
})->find(1);
As I know the $q is corresponding to the Comment table. Is there any way to query the Post table?
Query nested relation like this:
$blog = Blog::with(['posts' => function ($q) {
$q->where('column','value'); // query posts table
}, 'posts.comments' => function ($q) {
$q->where('commentsColumn','anotherValue'); // query comments table
}])->find(1);
Eloquent will load posts accordingly, only then will it fetch the comments for those posts.

Categories