使用 Eloquent 在 Laravel 中使用 where 子句访问嵌套的相关对象

Posted

技术标签:

【中文标题】使用 Eloquent 在 Laravel 中使用 where 子句访问嵌套的相关对象【英文标题】:Access nested related objects with where clause in Laravel using Eloquent 【发布时间】:2020-05-29 13:44:12 【问题描述】:

我正在尝试获取与特定客户端关联的任务列表,但任务与客户端之间没有直接关系。我还需要根据任务状态和项目状态过滤这些任务。

这是我的模型:

class Client extends Model

    // Fields ['id']
    public function projects()
    
        return $this->hasMany('App\Project');
    


class Project extends Model

    // Fields ['id', 'client_id', 'status']
    public function client()
    
        return $this->belongsTo('App\Client');
    
    public function tasks()
    
        return $this->hasMany('App\Task');
    

class Task extends Model

    // Fields ['id', 'project_id', 'status']
    public function project()
    
        return $this->belongsTo('App\Project');
    

在我的控制器中,我可以从请求中直接访问Client $client

目标是返回状态为“打开”的任务列表,这些任务是客户拥有的项目的子项。

基本上,我想写这样的东西:

$client->projects->where('status', 'active')->tasks->where('status', 'open');

我想取回我从这个查询中得到的结果:

SELECT * FROM tasks AS t 
    WHERE t.status='open' 
    AND t.project_id IN (
        SELECT id FROM projects AS p 
            WHERE p.status='active' 
            AND p.client_id=1
    );

我已经能够使用 Laravel 的查询生成器解决它,但我想要一个直接使用 Eloquent 的 ORM 的解决方案。

DB::table('tasks')
    ->join('projects', function($join) use ($client) 
        $join->on('projects.id', '=', 'tasks.project_id')
            ->where('projects.client_id', '=', $client->id);
    )->select('tasks.*')->get();

这似乎是一个常见问题的变体,但我无法使用此处发布的其他答案来解决它。

相关问题:

laravel orm : where condition on table -> related table -> related table

Laravel nested relationships

【问题讨论】:

【参考方案1】:

您正在寻找的是whereHas。它可以让您查询“基于关系存在的结果”。

你可以试试这样的:

Task::where('status', 'open')
    ->whereHas('project', function ($query) use ($client) 
        $query->where('client_id', $client->id)
            ->where('status', 'active');
    )
    ->get();

hasManyThrough 也适用于这个结构:

// In Client.php
public function tasks()

    return $this->hasManyThrough(Task::class, Project::class);


$client->tasks()
    ->where('projects.status', 'active')
    ->where('tasks.status', 'open')
    ->get();

但不完全确定这是否可行。

【讨论】:

以上是关于使用 Eloquent 在 Laravel 中使用 where 子句访问嵌套的相关对象的主要内容,如果未能解决你的问题,请参考以下文章

在 Eloquent 查询/Laravel 5.2 中使用变量

Laravel:在 API 测试中使用 Eloquent 模型

如何在 Laravel 5.8 中使用 Eloquent 进行查询?

在 Laravel 中使用 Eloquent 进行更高级的数据库查询

如何使用 Eloquent 在 Laravel 中开始查询?

如何在 laravel 5 中使用 Eloquent 更新数据透视表