Laravel: whereHas->WhereHas->Where query. Need to add wherePivot - laravel

I am selecting all the ScheduledPrograms from a certain data range that has Attendees that belong to a certain User. I want to add a filter to select only the SchduledPrograms where the pivot field registered=1
I.E. I need to add a wherePivot('registered', 1) for the many-to-many relation scheduledPrograms->attendees. I How do I do this? My mind is scrambled from all the where clauses.
$programs = ScheduledProgram::where('registration_start_date', '<=', $today)
->where('end_date', '>=', $today)
->whereHas('attendees', function($q) use($user)
{
$q->whereHas('user', function($q) use($user){
$q->where('id', $user->id);
});
})->get();
Models
Attendee->belongsTo('User')
->belongsToMany('ScheduledPrograms')
User->hasMany('Attendee')
ScheduledProgram->belongsToMany('Attendee')
`
ScheduledProgram Model
public function attendees()
{
return $this->belongsToMany('Attendee', 'prog_bookings')->withPivot('registered','paid');
}

wherePivot() can be used only for belongsToMany instances, but whereHas() closure function receives Builder instance instead.
So you can't use wherePivot() inside whereHas().

Method wherePivot works with model instances, not with the Model Query Builder.
I think when using whereHas method, the pivot table is already joined by eloquent, so just start using it in the whereHas method:
$programs = ScheduledProgram::where('registration_start_date', '<=', $today)
->where('end_date', '>=', $today)
->whereHas('attendees', function($q) use($user)
{
$q
//========= See this: =========
->where('prog_bookings.registered', '1')
->whereHas('user', function($q) use($user){
$q->where('id', $user->id);
});
})
->wherePivot('registered', 1)
->get();

did you try anything? What error do you get?
If the 'registered' field is in the pivot table between ScheduledPrograms and Atendees relation, you can add the where clause before the get():
$programs = ScheduledProgram::where('registration_start_date', '<=', $today)
->where('end_date', '>=', $today)
->whereHas('attendees', function($q) use($user)
{
$q->whereHas('user', function($q) use($user){
$q->where('id', $user->id);
});
})
->wherePivot('registered', 1)
->get();

Related

Laravel model get all results, but if model has relation then check for certain condition

Assume I have book models and borrow models. They are one-to-many relationships. I want to get a collection of all the books but return the result if the book is borrowed within the current week. But if it's not, then don't display. I've been trying whereHas(), but I think it didn't suit what I'm looking for.
$displayed_books = Books::orderBy('updated_at', 'DESC')
->ifHasborrow('borrow', function ($query) {
$query->where('start_date', '>=', currentweek())
->where('end_date', "<=", currentweek());
})
$displayedBooks = Books::orderBy('updated_at', 'DESC')
->where(function ($query) {
$query->whereHas('borrow', function($query) {
$now = Carbon::now();
$query->where([
['start_date', '>=', $now->startOfWeek()],
['end_date', '<=', $now->endOfWeek()]
]);
$query->orWhereDoesntHave('borrow');
})
})->get();

Conditionals on multiple Laravel relationships

I got table called Vehicles in whose model Vehicle are defined two relationships.
public function type(){
return $this->belongsTo("App\VehiclePivot", 'vehicle_type_id', "id");
}
and
public function workOrganization(){
return $this->belongsTo("App\WorkOrganization", 'workOrganization_id', "id");
}
When used as
$vehicles = Vehicle::with("type", "workOrganization");
they work great. Show for every vehicle their type and their work organization.
If i try
$vehicles = Vehicle::whereHas("type", function($query) use($request){
$query->where('name', '=', $request->type);
})->with("type")->get();
or
$vehicles = Vehicle::whereHas("workOrganization", function($query) use($request){
$query->where('name', '=', $request->workOrg);
})->with("workOrganization")->get();
They also work.
User can enter type or workOrganization, or both or neither of them.
If one is present, then only that relationship should "execute", if both, then both relationship should, also if it neither of them, then also both should execute.
Can it be done via eloquent?
I think you can use when
$vehicles = Vehicle::when(!empty($request->workOrg),function ($query) use($request){
$query->whereHas("workOrganization", function($query) use($request){
$query->where('name', '=', $request->workOrg);
});
})->when(!empty($request->type),function ($query) use($request){
$query->whereHas("type", function($query) use($request){
$query->where('name', '=', $request->type);
});
})
->with("workOrganization","type")
->get();

Laravel Eloquent making select on whereHas()

How can I select on whereHas() some columns in relation.
My current query looks like as it follows
Location::select(['title'])
->withCount(['job' => function($q) {
return $q->where('language_id', 1)->whereNull('deleted_at');
}])->whereHas('country', function ($q) {
return $q->where('id', '=', 80);
})->get();
and I tried
Location::select(['title', 'id as value'])->withCount(['job' => function($q) {
return $q->where('language_id', 1)->whereNull('deleted_at');
}])->whereHas('country', function ($q) {
return $q->select('title', 'iso3')->where('id', '=', 80);
})->get();
but nothing is getting returned on country relation. How do I refactor this query to get it work?
whereHas() doesn't eager load the relation, only filters results based on it. To eager load, use with().
Location::with('country:id,title,iso3')
->select(['title', 'id as value', 'country_id'])
->withCount(['job' => function($q) {
$q->where('language_id', 1)->whereNull('deleted_at');
}])
->whereHas('country', function ($q) {
$q->where('id', '=', 80);
})->get();

Pluck the values from WITH Eloquent in Laravel

I have a dropdown box that shows only the user with collector and borrower's role. Here's my code
public function create()
{
$users = User::whereHas('roles', function ($q) {
$q->where('roles.name', '=', 'collector')->orWhere('roles.name', '=', 'borrower');
})
->with('profile')
->get()
->pluck('name','id');
return view('dashboard.documents.create', compact('users'));
}
this code is fine but what I what to pluck is the column first_name, last_name and user_id from 'profile'.
How can I achieve that?
Thank you so much in advance!
You do one of these
$users = User::whereHas('roles', function ($q) {
$q->where('roles.name', '=', 'collector')->orWhere('roles.name', '=', 'borrower');})
->with('profile')
->select('name','id')
->get();
Or
$users = User::whereHas('roles', function ($q) {
$q->where('roles.name', '=', 'collector')->orWhere('roles.name', '=', 'borrower');})
->with('profile')
->get(['name','id']);
Both ways will return a collection with related models each model record will has the selected columns, if you want to convert it to an array you can add ->toArray() after the two ways and it will convert the collection to array.

How to use where conditional in with Laravel?

I do request using query:
return Baber::where(function ($query) use ($request) {
// HERE CONDITION WHERE FOR USER TABLE
})->with("user")->orderBy('id', 'desc')->get();
How can I use where() inside query, that it will be comparabled with user table in with("user")?
I mean the following:
return Baber::where(function ($query) use ($request) {
$query->where('user.created_at', $request->date);
})->with("user")->orderBy('id', 'desc')->get();
It's known as constraining eager loads.
Baber::with(['user' => function ($query) use ($request) {
$query->where('user.created_at', '=', $request->date);
}])
->orderBy('id', 'desc')
->get();

Resources