Laravel Eloquent - where relationship field does not equal

蹲街弑〆低调 提交于 2020-06-17 23:06:44

问题


I thought this would be fairly simple but it's not playing ball currently.

I have 2 tables for this question, 'applications' & 'application_call_logs'.

This query needs to return all from the applications table where the latest call log doesn't have a status of X.

Here's the current query:

$query = Application::query();

$query->where(function($query) {
    $query->whereDoesntHave('call_logs');
    $query->orWhereHas('latest_call_log', function($q) {
        $q->where('status', '!=', 'not interested');
    });
});

return $query->get();

This should return all rows that either have no call logs, or where the latest call log doesn't have the status field equaling a specific string.

This here:

$q->where('status', '!=', 'not interested');

Seems to have no affect if the call_logs has more than 1 row, even though I'm querying the latest relationship. I've also verified the latest is returning the correct latest record.

The two relationships in the Application model are:

public function call_logs()
{
    return $this->hasMany('App\ApplicationCallLog', 'lead_id', 'id');
}

public function latest_call_log()
{
    return $this->hasOne('App\ApplicationCallLog', 'lead_id', 'id')->latest();
}

Checked the SQL generated:

select * from `applications` where (not exists (select * from `lead_call_logs` where `applications`.`id` = `lead_call_logs`.`lead_id`) or exists (select * from `lead_call_logs` where `applications`.`id` = `lead_call_logs`.`lead_id` and `status` != ?))

回答1:


there is a solution around should be good for this situation:

i think that this line has the week point of the code:

return $this->hasOne('App\ApplicationCallLog', 'lead_id', 'id')->latest();

this should be hasMany, but you use hasOne to limit the result to one.

and if you tried:

 return $this->hasMany('App\ApplicationCallLog', 'lead_id', 'id')->latest()->limit(1);

it simply won't work, because the result will be limited to ApplicationCallLog for all of the results ....

will, there is a package staudenmeir/eloquent-eager-limit that is made especially for this situations:

composer require staudenmeir/eloquent-eager-limit:"^1.0"

class Application extends Model
{
use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
public function latest_call_log()
{
    return $this->hasMany('App\ApplicationCallLog', 'lead_id', 'id')->latest()
->limit(1);
}

}

class ApplicationCallLog extends Model
{
use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
}

using this package will limit ApplicationCallLog for every result in your query not one for all of the result, and that will have the same effect for hasOne ....

with this minor enhancement, i think:

$q->where('status', '!=', 'not interested');

will work ...

more about eloquent-eager-limit package in:

https://github.com/staudenmeir/eloquent-eager-limit



来源:https://stackoverflow.com/questions/62196091/laravel-eloquent-where-relationship-field-does-not-equal

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!