Home > Software engineering >  Laravel latest not working (not appearing in my SQL query)
Laravel latest not working (not appearing in my SQL query)

Time:12-12

So I have a Student model with this function:

public function latestStatus()
    {
        return $this->hasOne(StatusStudent::class)->latest();
    }

then I just do a query with this latestStatus()

$query = Student::findOrFail(1);
            $query = $query->whereHas('latestStatus', function($query) use ($statusuri) {
                $query->where('status_id', 1);
            });
            dd($query->toSql());

and the toSql() function returns:

"select * from `students` where exists (select * from `status_student` where `students`.`id` = `status_student`.`student_id` and `status_id` = ?)

as if latest() is ignored.

Why doesn't latest() add anything to the query?

Thanks.

Edit:

I tried adding selectRaw for example:

public function latestStatus()
    {
        return $this->hasOne(StatusStudent::class)->selectRaw('MAX(status_student.id)');
    }

and still nothing appears in my query.

CodePudding user response:

If you dig deeper to the whereHas() relationship. It calls the has() method then if you look for the has() method you will see the getRelationWithoutConstraints() method, means that it will call the relationship but it will remove all the constraints attach to it and will only call the base query instance :

public function latestStatus()
{
    return $this->hasOne(StatusStudent::class)->latest(); // the latest() will be removed in the query if you call the `latestStatus` using the `whereHas() or has()`
}

so if you use the whereHas() like the way you use it :

"select * from `students` where exists (select * from `status_student` where `students`.`id` = `status_student`.`student_id` and `status_id` = ?)

it will return the query with out the latest().

Instead of doing it like that you can do it like :

Student Model

public function status() : HasOne
{
    return $this->hasOne(StatusStudent::class);
}

Controller

$student = Student::findOrFail(1);

$student->whereHas('status', function($query) {
    $query->where('status_id', 1)
        ->latest();
})

But since the relationship is define as one-to-one :

$student = Student::findOrFail(1);

$student->load('status');

or

$student = Student::findOrFail(1)->status()->get();

Maybe you want to get the latest of all the status.

StudentStatus::query()->latest()->get();

CodePudding user response:

As stated in a comment by @matticustard,

findOrFail() returns a model, not a query builder.

Instead of findOrFail(1) use where('id', 1)

  • Related