skip to Main Content

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.

2

Answers


  1. As stated in a comment by @matticustard,

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

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

    Login or Signup to reply.
  2. 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();
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search