Laravel eloquent relation search using child table record - laravel

Problem :
I want only that records where relational records [ user ] not null.
In my case I want only first record. where user is not null
Result:
User Table
id
name
email
Project Tabel
id
title
user_id [foreign key]
My code is like this
$projects = App\Project::with(['user' => function ($user) {
$user->where('name', '=', 'Ketan');
}])
->get();
foreach ($projects as $project) {
echo $project->title.' - '.$project;
}
My result is like this :

The below code is working
$projects = App\Project::whereHas('user', function ($user) {
$user->where('name', '=', 'Ketan');
}])->get();
Change 'with' to 'whereHas' and note that whereHas doesn't accept the array as the param
For reference Laracasts Link

I got solution of my question
$projects = App\Project::whereHas(['user' => function ($user) { <--Change Here
$user->where('name', '=', 'Ketan');
}])
->get();
Only Change 'with' to 'whereHas'
By this solution, I have got only those Project records in which user ( relational record ) is not null.

You can try:
$projects = App\Project::with(['user' => function ($user) {
$user->where('name', '=', 'Ketan');
}])
->get();
foreach ($projects as $project) {
if($project->user != null){
echo $project->title.' - '.$project;
}
}

Related

Laravel - Filter collection with closure on relationship

Wondering if there is a way to use closure on a relationship in order to filter the whole line if there isn't a value which corresponds?
Example code:
foreach ($paiementMethods as $value) {
$giftCards = GiftCard::with(['userEntered', 'userEmployee', 'client', 'payement', 'payement.payementMethods' => function($query) use ($value)
{
$query->where('id', $value);
}])
->where('date','>=', $dateStart)
->where('date','<=', $dateEnd)
->orderBy('updated_at', 'desc')->get();
$giftCardsCollection = $giftCardsCollection->merge($giftCards);
}
}
In this example, if $query->where doesn't find a row for the payement.payementMethods which matches the $value, I want the giftCard to return null. The result I get is the giftCard with only the relation on payement.payementMethods being empty.
My other solution would be to query the giftCard and after that checking the $value to see if I have to include the giftCard in the collection or not.
Best regards
I think using whereHas, it can be solved
$giftCards = GiftCard::with(['userEntered', 'userEmployee', 'client', 'payement', 'payement.payementMethods'])
->whereHas( 'payement.payementMethods', function($query) use ($paiementMethods) {
$query->whereIn('id', $paiementMethods);
})
->where('date','>=', $dateStart)
->where('date','<=', $dateEnd)
->orderBy('updated_at', 'desc')
->get();

how to select specific fields from the tables in laravel

This works but it gives all the fields of account table but only few are required.
$data = Loan::select('*')
->with([
'member' => function ($query) {
$query->addSelect('id', 'name');
},
'member.account'
])
->get();
This gives account: null
$data = Loan::select('*')
->with([
'member' => function ($query) {
$query->addSelect('id', 'name');
},
'member.account'=> function ($query) {
$query->addSelect('id', 'account'); // if this line is commented, all the fields are returned but I just need few fields.
}
])
->get();
Member model:
public function account()
{
return $this->hasOne(Account::class);
}
Account model:
public function member()
{
return $this->belongsTo(Member::class);
}
How can I get only the required fields of account table?
You can define the relationship and set it to give you specific columns like this.
on Member model
public function account()
{
return $this->hasOne(Account::class)->select(['id', 'account']);
}
You can try to define required fields in with:
$data = Loan::select('*')
->with([
'member' => function ($query) {
$query->addSelect('id', 'name');
},
'member.account:id,number'
])
->get();
Your are close you just need to select the foreign key column that points to your account model , I guess it would be account_id, So you basically need to select 3 columns from your table which are select(['id', 'name','account_id'])
$data = Loan::with(['member' => function ($query) {
$query->select(['id', 'name','account_id'])
->with(['account'=> function($query){
$query->select(['id','name']);
}]);
}])
->get();
So if you have another nested relation account -> type and you need specific columns from type so you need to select the foreign key column from accounts models as
with(['account'=> function($query){
$query->select(['id','name','type_id'])
->with(['type'=> function($query){
$query->select(['id','name']);
}]);
}]);

How to implement relationship in where condition Laravel's eloquent?

I have two tables:
Students
Results
The two tables have one to may relationship.
Student model:
public function results()
{
return $this->hasMany('App\Result');
}
Result model:
public function student()
{
return $this->belongsTo('App\Student');
}
In the students table I have a field called average_score.
How can I execute the following query, this is not working it says "Undefined property: Illuminate\Database\Query\Builder::$student":
$data = Result::with('student')->where('score', '>=', function($q){
$average_score = $q->student->average_score;
return $average_score;
})->get();
In order to get the results that are only higher or equal to than the "average_score".
If score and average_score are columns of the same table (student), try this;
$data = Result::with(['student' => function ($query) {
$query->whereColumn('score', '>=', 'average_score');
}])->get();
If score and average_score are columns of the different tables, try this;
$data = Result::with('student')->whereHas('student', function($q) {
$q->whereColumn('students.average_score', '<=', 'results.score');
})->get();
You can use whereHas to find those results:
$data = Result::with('student')->whereHas('student', function($q) {
$q->whereColumn('average_score', '<=', 'Results.score');
})->get();
get value from column Results.average_score then compare to student.score:
Result::with([
'student' => function($query) {
$query->where("score",">=", "Results.average_score"););
}
])

Excluding pivot rows in Eloquent ORM query

(laravel 4.2)
There are four tables involved; users, posts, flags, and post_flags.
I want to retrieve every post a certain user has, and retrieve the flags set for the post, but only the flags that are set by the user in question.
For example: A post can have flags: 1,2,2,3 where flag 2 is set twice. Once by User A, once by User B. I don't want to see the flags that User B has set.
The Eloquent query in my controller:
$posts = Post::whereHas('companies', function($q) use($company_id) {
$q->where('id', '=', $company_id);
})->with('flags')->get();
The Relation in my Post model:
public function flags() {
return $this->belongsToMany('PostFlag', 'post_postflags', 'post_id', 'flag_id')
->withTimestamps()->withPivot('owner');
}
How would I achieve this using Eloquent ORM?
UPDATE
My final query, thanks to andrewtweber:
Final query
$posts = Post::whereHas('users', function($q) use($id) {
$q->where('id', '=', $id);
})->get()->load([
'flags' => function($query) use($id) {
$query->where('owner', '=', $id)->orWhere('owner', '=', 'SYSTEM');
}
]);
Use wherePivot
http://laravel.com/api/4.2/Illuminate/Database/Eloquent/Relations/MorphToMany.html
$flags = $post->flags()
->wherePivot('user_id', '=', $user_id)
->get();
Or with eager loading
$posts->load([
'flags' => function ($query) use($user_id) {
$query->wherePivot('user_id', '=', $user_id);
}
]);

Laravel 4 Eager Loading constraints

I want to get all Items (topics) WITH their comments, if comments user_id = $id. I try something like this, but it isn't working. So if Item hasn't got any comment with user_id = $id, then I don't need this Item.
In DiscussionsItem model I have methode:
public function discussionsComments() {
return $this->hasMany('DiscussionsComment', 'discussionsitem_id');
}
My query in controller is like this:
$items = DiscussionsItem::whereBrandId($brand_id)
->whereBrandCountryId($country_id)
->with(['discussionsComments' => function($query) use ($id) {
$query->where('user_id', '=', $id);
}])
->whereHas('discussionsComments', function($query) use ($id) {
$query->where('user_id', '=', $id);
})
->with(['views' => function($query) use ($id) {
$query->where('user_id', $id)->count();
}])
->orderBy('created_at', 'DESC')->get();
My problem is that I get items with comments, where comments user_id != $id.
P.S. I need to take 5 comments, but I cant imagine how to do that, because ->take(5) in my eager load is not working.
You can do a custom scope, or just limit the amount returned by your relation:
public function discussionsComments() {
return $this->hasMany('DiscussionsComment', 'discussionsitem_id')
->latest()
->take(5);
}

Resources