I'm using eloquent and trying to set up what I would best describe as a dynamic relationship.
I have a Student model that can be on a Course: PhD, Master, Bachelor, Foundation or ESL and a student can have a report specific to each course, therefore I have the following eloquent models: PhdReport, MasterReport, BachelorReport, FoundationReport or EslReport.
One such relationship I require is to get the latest report for the student's current course. So if the student is on the bachelor course I want to grab the BachelorReport model where the date_to attribute is the most recent. This is my implementation on the Student model for the relationship:
public function latestReport()
{
$courseReport = ucfirst(strtolower($this->course->name)) . 'Report';
return $this->hasOne('\App\Models\\' . $courseReport)->latest('date_to');
}
This relationship works fine when I run the following code in artisan tinker:
// get a student
$student = App\Models\Student::first();
// student returned
=> <App\Models\Student #000000003dd8f51b00000000d869fe64> {
course_id: 2, /* which is the master course */
// other attributes ...
}
// get the latest report for the student's current course
$s->latestReport
// we get a MasterReport as expected
=> <App\Models\MasterReport #000000003dd8f51900000000d869fe64> {
// attributes
}
However, when I run the following code:
$students = $this->student
->where('course', 2)
->where('is_active', '1')
->with('latestReport', /* other relationships */)
->get();
It always appears to run the code for PhdReport, this is shown when I check the Laravel debugbar
select * from `phd_reports`
where `phd_reports`.`student_id` in (/* list of ids */)
order by `date_to` desc
My current idea for a workaround is to conditionally apply a relation specific to the course/report:
$students = $this->student
->where('course', 2) /* for masters */
->where('is_active', '1');
if ($course == 'master') {
$students = $students->with('latestMasterReport');
}
Any advice would be much appreciated. Thank you!