【问题标题】:tables joining with pivot table in laravel在 laravel 中加入数据透视表的表格
【发布时间】:2020-06-14 22:29:16
【问题描述】:

我正在使用 laravel 5.8,我有四个表:

客户:id|name|code

任务:id|名称

client_task: id|client_id|task_id

月:id|client_id|task_id|exec_date

clientstasks 是多对多关系,client_task 是数据透视表

这个想法是我想像这样在html中创建一个表格

-------------------------------------------
|#|client name|task 1|task 2|task 3|task 4|
-------------------------------------------
|1| client 1  |  ☐   |  ☐   |  /// |  /// |
-------------------------------------------
|2| client 2  | ///  |  ☐   |   ☐  |  ☑   |
-------------------------------------------
|3| client 3  |  ☐   |  ☑   |   ☑  |  /// |
-------------------------------------------

每个月我都会收到所有客户和所有任务,如果客户有任务,我会显示一个复选框,否则我会显示一个空的 td,如果我为特定客户完成一项任务,我会检查此任务并插入client_idtask_id 和当前日期 exec_datemonthlies 表中。

我正确的查询:

$clients = DB::table('monthlies as m')
        ->rightJoin('client_task as clta', function ($join){
            $join->on('clta.client_id', '=', 'm.client_id')
                ->on('clta.task_id', '=', 'm.task_id')
                ->rightJoin('clients as cl', function ($join){
                    $join->on('clta.client_id', '=', 'cl.id')->where('cl.category',1);
                })
                ->Join('category_task as cata', function ($join){
                    $join->on('clta.task_id', '=', 'cata.task_id')
                        ->Join('categories as ca2', 'cata.category_id', '=', 'ca2.id')->where('ca2.type', 1)
                        ->rightJoin('tasks as ta', 'cata.task_id', '=', 'ta.id')->where('ta.period', 1);
                });

        })

        ->select('m.*', 'cl.id as client_id', 'cl.name as client_name', 'cl.code as client_code', 'cl.legal_form as client_legal_form', 'ta.id as task_id', 'ta.name as task_name', 'ta.type as task_type', 'ta.period as task_period')
        ->get();

使用此代码,我只能在 client_task 表中获得客户端/任务

问题是我想显示所有客户端或任务,即使客户端没有附加任务,反之亦然(client_task 数据透视表中不存在)。

【问题讨论】:

  • 我很好奇,您为什么要使用查询生成器编写“原始”SQL 查询?如果您的关系设置正确,您可以简单地执行Client::with('tasks')->get(),然后遍历生成的Eloquent\Collection。 Laravel 将为您完成所有这些繁重的工作;)
  • 我有很多客户端和很多任务,我想获取所有客户端 + 所有任务 + 检查二进制(客户端任务)是否存在,如果不存在,我将在“数据表”中显示一个空的“td” ',如果存在,我检查此二进制文件是否存在于monthlies 表中,如果存在,则它将显示为“已检查 + 禁用”复选框,如果不存在,则表示我没有为该客户端完成此任务,我将显示一个简单的复选框,所以我想在一个查询中得到所有这些
  • 我仍然强烈建议使用Eloquent 来执行此操作,我会尝试发布涵盖此问题的答案,但可能需要我一分钟!
  • 好的,非常感谢

标签: mysql laravel


【解决方案1】:

好的,这可能需要你对你的人际关系做出一些改变,但我认为你会看到好处!


数据透视表属性和模型

如果您的client_taskmonthlies 表之间的唯一区别是exec_date,为什么不将这两个表合并为client_task

您可以像这样将数据透视表属性添加到您的关系中:

Client.php

public function tasks()
{
    return $this->belongsToMany(Task::class, 'client_task',`client_id`,'task_id')->withPivot(['exec_date']);
}

现在,当您获得 ClientTask 时,您可以使用 pivot 属性 ($task->pivot->exec_date) 获得 exec_date。

您甚至可以制作专用的Pivot 模型,如文档here 中所示


关系存在

您可以使用whereHas() 函数确定Client 是否具有给定的Task

Client::whereHas('tasks', function (Builder $query) use ($task) {
    $query->where('id', $task->id);
})->get();

文档可以在here找到


模板

大部分用于控制表格的代码将使用简单的模板逻辑在刀片视图中完成:

@foreach ($clients as $client)
    <tr>
    @foreach ($tasks as $task)
        <td>
            @if ($client->tasks->contains($task)) 
                 @if ($client->tasks->where('id', $task->id)->first()->pivot->exec_date)
                     ... checked checkbox ...
                 @else
                     ... unchecked checkbox ...
                 @endif
            @else
                ...
            @endif
        </td>
    @endforeach
    </tr>
@endforeach

【讨论】:

  • 太棒了!!非常感谢您的详细回答,即使我发现自己有两个查询,但没关系,它完成了工作
  • 没有问题,很高兴我能帮上忙!附带说明一下,不要觉得您绝对需要在一个查询中完成所有操作。有时,一个大型查询实际上比几个较小的查询花费更长的时间,但这需要根据具体情况进行查看;)
猜你喜欢
  • 2016-12-26
  • 2018-04-10
  • 1970-01-01
  • 2014-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-19
相关资源
最近更新 更多