I make a request like this :
Event::where('team_id', Auth::user()->currentTeam->id)
->whereHas('animals', function ($query) use ($decodedId) {
$query->where('animals.id', $decodedId)
->whereHas('health_items', function ($query) {
$query->whereColumn('date_end', 'events.end');
});
})
Thanks to whereColumn, I compare my data health_items with that of the grandparent events
$query->whereColumn('date_end', 'events.end');
It works.
Only with WhereHas, I don't have the relations data in my response (it just filters out the events)
I try to do the same by adding a with it doesn't work.
Event::where('team_id', Auth::user()->currentTeam->id)
->with(['animals' => function($query) use ($decodedId) {
$query->where('animals.id', $decodedId)
->with(['health_items' => function ($query) {
$query->whereColumn('date_end', 'events.end');
}]);
}])
Returned error : Unknown column 'events.end'
Is there a way to filter the "health_items" items using a column in the events table?
Thank you
Related
so we have a page where we have to filter a list of students based on filters selected by the user in the front end.
Filters in the front end
Filter by Subjects (students who have opted for subjects)
Filter by location (students who are part of a location)
Filter by Gender (self explanatory)
Now Location & Gender are part of student table, so it is very easy to use these filters with simple query but subjects is a totally different table
Check the attached table
Query current we have
$student = Student::select('*')
->where(function ($query) use ($request) {
if (!empty($request->location)) {
$query->whereIn('location', $request->location);
} else if (!empty($request->gender)) {
$query->where('gender', $request->gender);
} else if (!empty($request->subjects)) {
// selecting students by id who enrolled for a particular subject
// end user can select multiple subjects
$query->whereIn('id', function($subjectQuery) use ($request) {
$subjectQuery->select('student_id')
->whereIn('subject_id', [$request->subjects])
->from('student_subjects')
->get();
});
})->get();
when passing {"subject": [201, 205]}
getting following error
Nested arrays may not be passed to whereIn method
But when passing {"subject": [201]}
This return empty result,
What are we doing wrong? or what we can do to improve this query?
In this case I usually use when() and whereHas() (assuming you have model StudentSubject and have the relationship). It will look like this:
$student = Student::select('*')
->when(!empty($request->location), function ($query) use($request) {
$query->whereIn('location', $request->location);
})
->when(!empty($request->gender), function ($query) use($request) {
$query->whereIn('gender', $request->gender);
})
->when(!empty($request->subjects), function ($query) use($request){
$query->whereHas('StudentSubject',function($sub) use($request) {
return $sub->whereIn('subject_id',$request->subjects);
});
})
->get();
I don't know your $request->subjects format so I assuming it's just the usual array like [1,2,3].
I'm using condition based queries but i have a problem how can i use (when) with other table/model because i have to put condition based on the other table column (branch_id).
branch_id comes from steps table.
ContactBoard::with(['steps'])
->when($request->has('branch'), function ($query) use ($request) {
$query->where('steps.branch_id', $request->query('branch'));
})
->where('id', $board_id)->get()->first();
You can make it like
$query->when($request->has('branch'), function ($q)use($request) {
return $q->with('steps',function($q){
$q->where('branch_id', $request->query('branch'));
});
});
$query = $query->get();
I have an application where I want to fetch parent records based on children conditionals. Current problem is that I have Students, where they have multiple study fields and study fields belong to one faculty. Pivot table students_study_fields has attribute study_status_id.
What I need is, for example, fetch all students and their study fields which belongs to "prf" faculty AND pivot has study_status_id = 1.
So I write a query like this.
return Student::with(['studyfields' => function ($query1) use ($studyStatusId, $facultyAbbreviation) {
$query1->whereHas('pivot', function ($query2) use ($studyStatusId, $facultyAbbreviation) {
$query2->where('study_status_id', $studyStatusId);
});
$query1->whereHas('studyprogram', function ($query4) use ($facultyAbbreviation) {
$query4->whereHas('faculty', function ($query5) use ($facultyAbbreviation) {
$query5->where('abbreviation', $facultyAbbreviation);
});
});
}])->get();
But this query fetch students witch study_status_id = 2 as well because exists record where this same study field (its code) has relation with student, where study_status_id = 1.
So I don't want to include this studyfield if somewhere exists record with status = 1 in pivot but only if has status = 1 for current row
You need to chain the queries...
return Student::with(['studyfields' => function ($query1) use ($studyStatusId, $facultyAbbreviation) {
$query1->whereHas('pivot', function ($query2) use ($studyStatusId, $facultyAbbreviation) {
$query2->where('study_status_id', $studyStatusId);
})->whereHas('studyprogram', function ($query4) use ($facultyAbbreviation) {
$query4->whereHas('faculty', function ($query5) use ($facultyAbbreviation) {
$query5->where('abbreviation', $facultyAbbreviation);
});
});
}])->get();
Otherwise it will re-start the query1 so you won't get AND kind of query, only get the second part
Side Note: However, I want to warn you that whereHas is a slow query if you have many rows as it goes through each value. I personally prefer grabbing the ids with simple ->where queries and utilise ->whereIn approach.
I found solution for my situation
$students = Student::with(['studyfields' => function ($q) use ($studyStatusId) {
$q->whereHas('pivot')->where('study_status_id', $studyStatusId);
}])
->whereHas('studyfields', function ($q) use ($facultyAbbreviation) {
$q->whereHas('studyprogram', function ($q) use ($facultyAbbreviation) {
$q->where('faculty_abbreviation', $facultyAbbreviation);
});
})
->get();
$students = $students->filter(function ($student) {
return count($student->studyfields) > 0;
})->values();
Query above fetch all students from specific faculty and if studyfields array doesn't contains specific study_status, leave empty array so later I can filter collection from empty arrays assuming that each student belongs to at least one studyfield.
I have a little problem, I have a table with Movies and another with Genres ex: Action, Adventure etc...
Table names:
movies
movie_genre
genres
I want to fetch all the Movies with the selected Genre ex: Action
$movies = Movie::with('genres')
->when($genre, function ($query) use ($genre) {
return $query->where('genres.id', $genre->id);
})
->paginate(20);
This php code doesn't work, how can I make it work?
PS: The genre is transfered from the view by $_GET['genre'] and stocked in the variable $genre.
Edit after the answer of #Shane and #Marcin NabiaĆek :
The relationship is set in the models and when I use your code directly like this:
Movie::with('genres', 'countries', 'type')
->when($type, function ($query) use ($type) {
return $query->where('medias.type_id', $type->id);
})
->whereHas('genres', function ($query) use ($genre) {
return $query->where('genres.id', $genre->id);
})
->paginate(20);
it work perfectly, but with the when() function it dosn't. I have to use the when() to make the condition work only if there is a genre selected by the user.
You should use whereHas to get all movies that are assigned to given genre:
$movies = Movie::with('genres')
->when($genre, function ($query) use ($genre) {
$query->whereHas('genres', function($q) use ($genre) {
return $query->where('id', $genre->id);
});
})->paginate(20);
In case $genre is only id and not model, you should rather use:
return $query->where('id', $genre);
and in case it's an array (user is allowed to choose multiple genres), you should use:
return $query->whereIn('id', (array) $genre);
I'm not familiar with the when function. I use whereHas:
$movies = Movie::whereHas('genres', function ($query) use ($genre) {
$query->where('id', $genre->id);
})->with('genres')->get();
Also, is $genre the model or the ID? You mentioned it was received from $_GET which would mean it would be an ID probably.
I think a better solution would be to use your relationship function in the Genre model to get them:
$movies = Genre::find($genre_id)->movies;
i am trying to query many to many relation for my get api call. i have three table as shown here but i am not using pivot table.
This is my Projects model class and this the function
public function projectRewd()
{
return $this
->belongsToMany('App\Rewards','rewards','project_id','reward_id');
}
And this is my Rewards model class and function
public function projectShip()
{
return $this->belongsToMany('App\Shipping_location','shipping_location','projects_id','rewards_id');
}
This is my api controller function
Route::get('projects/{id}', function($id) {
$proj = Projects::whereHas('projectRewd', function($q)
{
$q->where('id', $id);
});
return $proj;
});
i am using this link for api call
http://localhost:8000/api/projects/1
i want to extract rewards data and shipping_location data associate with project_id.
i am getting this error
"message": "Object of class Illuminate\\Database\\Eloquent\\Builder could not be converted to string"
i check and tried all related error from different post.
i also search and tried many technique. Cant solve my problem.
Please suggest me how to do this??
can i do this type of query in larvel without using pivot table??
You are getting Builder model because you forgot to add ->first() or ->get().
You should write:
$proj = Projects::whereHas('projectRewd', function($q){
$q->where('id', $id);
})->first();
Your closure-based controller returns your query-builder object. Not a project. You need to retrieve results from the query by fetching e.g. the first result (->first()) or all (->get()).
Route::get('projects/{id}', function($id) {
$proj = Projects::whereHas('projectRewd', function($q)
{
$q->where('id', $id);
})->first();
return $proj;
});
Referencing $id:
The reason why $id is unknown, is that the closure doesn't know about it.
You can pass it to the closure using use(...).
Route::get('projects/{id}', function($id) {
$proj = Projects::whereHas('projectRewd', function($q) use ($id)
{
...
Further:
Your whereHas query looks incorrect to me:
$q->where('id', $id);
Apparently $id is the project id. But the 'id' column in projectRewd is the primary key of projectRewd (unless you have modified the defaults).
I assume you want to query all projects that have at least one projectRewd:
Route::get('projects/{id}', function($id) {
$proj = Projects::has('projectRewd')->first();
return $proj;
});
And if you want to eager load the joined tables:
Route::get('projects/{id}', function($id) {
$proj = Projects::with('projectRewd. projectShips')->has('projectRewd')->first();
return $proj;
});