Adding conditions to Laravel has() - php

I have a table named answers and its columns are id, answers, batch, candidate_id. I want to get all candidates that has no record of answers under batch number of 1.
Is there a way to add condition to this statement (this is in my candidate model) ?
return $this->has('answers', '=', 0)->get();
I tried this way but it didn't work:
return $this->has('answers', '=', 0)->whereBatch(1)->get();

You need whereHas:
$this->whereHas('answers', function ($q) {
$q->whereBatch(1);
}, '=', 0)->get();
Btw this is exactly the same as calling has with closure as 5th param:
$this->has('answers', '=', 0, 'and', function ($q) {
$q->whereBatch(1);
})->get();

Related

How to add a where clause when using "with" on an Eloquent query in Laravel

I have a query built where I'm using "with" to include related models. However, I'm not sure how to filter those related models in a where clause.
return \App\Project::with("projectLeaders")->join('companies', 'company_id', '=', 'companies.id')
->join('project_status', 'project_status.id', '=', 'projects.status_id')
->select('companies.*', 'project_status.name AS statusName', 'projects.*');
Please note the with("projectLeaders") in the query. So, ProjectLeaders is a relation that brings objects of kind Employee, how can I filter in that query those "Employees" whose attribute "Lastname" is like "Smith" ?
You can implement where class both tables. Please check following code and comments.
return \App\Proyecto::with(["projectLeaders" => function($query){
$query->where() //if condition with inner table.
}])->join('empresas', 'id_empresa', '=', 'empresas.id')
->join('tipo_estado_proyecto', 'tipo_estado_proyecto.id', '=', 'proyectos.id_tipo_estado_proyecto')
->where() //if condition with main table column.
->select('empresas.*', 'tipo_estado_proyecto.nombre AS nombreEstadoProyecto', 'proyectos.*');
You can use Closure when accessing relation using with. Check below code for more details:
return \App\Project::with(["projectLeaders" => function($query){
$query->where('Lastname', 'Smith') //check lastname
}])->join('companies', 'company_id', '=', 'companies.id')
->join('project_status', 'project_status.id', '=', 'projects.status_id')
->select('companies.*', 'project_status.name AS statusName', 'projects.*');
You may use the where method on a query builder instance to add where clauses to the query. The most basic call to where requires three arguments. The first argument is the name of the column. The second argument is an operator, which can be any of the database's supported operators. Finally, the third argument is the value to evaluate against the column.
return \App\Project::with("projectLeaders")->join('companies', 'company_id', '=', 'companies.id')
->join('project_status', 'project_status.id', '=', 'projects.status_id')
->where('lastname','=','Smith')
->select('companies.*', 'project_status.name AS statusName', 'projects.*');
Don't forget to return results with a get();
The query you have written is correct. But after building the query you need to fetch the data from database.
METHOD ONE
So adding get() method to your query:
return App\Project::with('projectLeaders')
->leftJoin('companies', 'company_id', '=', 'companies.id')
->leftJoin('project_status', 'project_status.id', '=', 'projects.status_id')
->select('companies.*', 'project_status.name AS statusName', 'projects.*')
->get();
METHOD TWO (with pagination)
return App\Project::with('projectLeaders')
->leftJoin('companies', 'company_id', '=', 'companies.id')
->leftJoin('project_status', 'project_status.id', '=', 'projects.status_id')
->select('companies.*', 'project_status.name AS statusName', 'projects.*')
->paginate(3);

Eloquent: How to 'WhereNotNull' from a ::with( ) result

I'm running the following query that has a with() relation.
$logbook_objectives = self::whereIn('lobjective_id', $logbook_objectives_ids)
->with(['objective' => function($q) use ($course_objective_ids){
$q->select(['objective_id', 'objective_code', 'objective_name'])
->whereIn('objective_id', $course_objective_ids)
->whereIn('objective_parent', $course_objective_ids, 'or');
}])
->withCount(['entryObjectives' => function ($q) use ($learner_id) {
$q->where('created_by', $learner_id);
}])
->get();
Sometimes the the returned 'objective' field is null because of the rules within the with function. How do I remove the results that have objective = null?
I tried using ->whereHas('objective') before the ->get() but it doesn't change anything. Is there another way to evaluate if the with function returned null keeping the same query?
Solutions I have on my head:
Use join instead, so I can evaluate null results in the same query.
Use a foreach look verifying if the objective field is null and remove found results from my returned list.
If objective table has 'objective_id' or any other key as primary key then place that key in whereNotNull just as given below:
$logbook_objectives = self::whereIn('lobjective_id', $logbook_objectives_ids)
->with(['objective' => function($q) use ($course_objective_ids){
$q->select(['objective_id', 'objective_code', 'objective_name'])
->whereIn('objective_id', $course_objective_ids)
->whereIn('objective_parent', $course_objective_ids, 'or')->whereNotNull('objective_id');
}])
->withCount(['entryObjectives' => function ($q) use ($learner_id) {
$q->where('created_by', $learner_id);
}])
->get();
The solution I found was to use a whereHas together with the with function. The query would be:
$logbook_objectives = self::whereIn('lobjective_id', $logbook_objectives_ids)
->with(['objective' => function($q) use ($course_objective_ids){
$q->select(['objective_id', 'objective_code', 'objective_name'])
->whereIn('objective_id', $course_objective_ids)
->whereIn('objective_parent', $course_objective_ids, 'or');
}])
->whereHas('objective', function($q) use ($course_objective_ids){
$q->select(['objective_id', 'objective_code', 'objective_name'])
->whereIn('objective_id', $course_objective_ids)
->whereIn('objective_parent', $course_objective_ids, 'or');
})
->withCount(['entryObjectives' => function ($q) use ($learner_id) {
$q->where('created_by', $learner_id);
}])
->get();
In that case only rows that the objective exists will be returned.

Laravel Collection Query, Where I am going wrong?

My tables looks like this
area_trip
|id|dispatch_id|trip_id|status|
equipment_trip
|equipment_id|trips_id|dispatch_id|
trips
|id|dispatch_id|status
I am trying to pass collection to my resource. Can someone check my query and tell me what I am doing wrong as following query returning all the data matches dispatch_id whether it matches equipment_id or not. Btw I am new to laravel.
return
Resources::collection(
area_trip::where('dispatch_id', $request->dispatch_id)
->where('status', 1)
->orWhere('status', 9)
->whereHas('equipment_trip', function($query) use ($request) {
$query->where('equipment_trip.equipment_id', '=', $request->equipment_id);
})
->with(['equipment_trip', 'createdBy', 'updatedBy', 'area', 'trips'])
->orderBy('tripStartDate', 'ASC')
->orderBy('status', 'ASC')
->get());
Here is the relationship set up in area_trip model
public function equipment_trip()
{
return $this->belongsTo(equipment_trip::class, 'trip_id', 'trips_id');
}
I believe your whereHas sub query is incorrect also instead of where and orWhere use where in and you can define all statuses necessary, try this:
Resource::collection(area_trip::where('dispatch_id', $request>dispatch_id)
->whereIn('status', [1, 9])
->whereHas('equipment_trip', function($query) use ($request) {
return $query->where('equipment_id', '=', $request->equipment_id);
})
->with(['equipment_trip', 'createdBy', 'updatedBy', 'area', 'trips'])
->orderBy('tripStartDate', 'ASC')
->orderBy('status', 'ASC')
->get());

cant get the data I want from two different tables using Laravel

I have a table called instructor_class: user_id, class_id and I have another table classes: id, time, active.
I would like to show classes for a single user but only those classes that active is 0 or 1.
My current code looks like this:
return InstructorClass::with('classes.session')->where('user_id', '=', $userId)->get();
This code is displaying me everything, then I tried the following code:
$active = 1;
return InstructorClass::with(['classes' => function ($q) use ($active) {
$q->where('active', '=', $active); // '=' is optional
}])
->where('user_id', '=', $userId)
->get();
This again returns me same records, but of course the class property is null for each record, which at some point looks correct, but my point is if the 'active' field does not corresponds at the classes table do not show the record, seems like the where() stm within with() is optional..
I am kinda stuck here...
Would appreciate your help, opinions!
You can use ::has('classes') to only return the models that have related classes
return InstructorClass::has('classes')->with(['classes' => function ($q) use ($active) {
$q->where('active', $active);
}])
->where('user_id', '=', $userId)
->get();
Never thought it could be this simple:
return InstructorClass::with('classes.session')
->join('classes', 'classes.id', '=', 'instructor_class.class_id')
->where('classes.active', '=', 1)
->where('user_id', '=', $userId)
->get();

Call to a member function whereHas() on a non-object in laravel

In my controller I have wrote this following code
$usersCount = User::where('activated', '=', 1)->where('group_id', '=', 1)->where('availability_date', '<=', $opportunity_date)->count();
$locations_array_result = explode(",",$locations_array_result);
foreach ($locations_array_result as $param)
{
$usersCount = $usersCount->whereHas('location', function($q) use($param){
$q->where('location_id', '=', $param );
});
}
This code giving following error
Call to a member function whereHas() on a non-object
Can anyone help me to find out what i have done wrong!!!
$usersCount is already a number from the 1st line of your sample.
You want instead to replace $usersCount->whereHas with User::whereHas in your foreach loop.
Taking a very wild guess here, I would think you need to get all users with these requirements
->where('group_id', '=', 1)->where('availability_date', '<=', $opportunity_date)
plus having a location_id value which exists on an array named $locations_array_result
If this is the case, this is all you need:
User::where('activated', '=', 1)->where('group_id', '=', 1)->where('availability_date', '<=', $opportunity_date)->whereIn('location_id', $locations_array_result)->get();
EDIT
Following your comment below, I assume user has many to many relation with locations (defined in your model), so eager loading and then using a condition with a callback should do the job:
$users = User::where('activated', '=', 1)
->where('group_id', '=', 1)
->where('availability_date', '<=', $opportunity_date)
->with(array('location' => function($query) use ($locations_array_result)
{
$query->whereIn('location_id', $locations_array_result);
}))->get();

Categories