首页 > 解决方案 > Laravel Eloquent - 关系字段不等于

问题描述

我认为这会相当简单,但目前还没有打球。

对于这个问题,我有 2 个表格,“应用程序”和“应用程序调用日志”。

此查询需要从最新调用日志的状态不是 X 的应用程序表中返回所有。

这是当前的查询:

$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();

这应该返回没有呼叫日志或最新呼叫日志没有等于特定字符串的状态字段的所有行。

这里:

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

如果 call_logs 有超过 1 行,似乎没有影响,即使我正在查询最新的关系。我还验证了最新的返回正确的最新记录。

Application 模型中的两个关系是:

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();
}

检查生成的 SQL:

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` != ?))

标签: sqllaraveleloquent

解决方案


有一个解决方案应该适合这种情况:

我认为这条线有代码的周点:

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

这应该是 hasMany,但您使用 hasOne 将结果限制为一个。

如果您尝试过:

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

它根本行不通,因为所有结果的结果将仅限于 ApplicationCallLog ....

将,有一个包 staudenmeir/eloquent-eager-limit 专门针对这种情况制作:

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;
}

使用此包将限制 ApplicationCallLog 查询中的每个结果,而不是所有结果,这对 hasOne 具有相同的效果 ....

通过这个小改进,我认为:

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

将工作 ...

更多关于 eloquent-eager-limit 包的信息:

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


推荐阅读