【问题标题】:Laravel - Accessing model value inside Query BuilderLaravel - 在查询生成器中访问模型值
【发布时间】:2019-02-22 13:58:21
【问题描述】:

我有五个表:requesters、document types、protocols、flows 和 documents。

关系

  • 请求者有许多文档类型。
  • 请求者有很多协议。
  • 协议有很多流程。
  • Flow 有很多文档。
  • 文档类型有很多文档。

问题

选择所有 protocols 具有第一个 flow(假设序列 = 1)且 documents 具有所有 文档类型 em> 表示协议请求者。

换句话说,选择没有挂起的协议,这意味着在第一流中具有文档的协议具有协议请求者所需的所有文档类型。

解决方案

我最终得到了一个实际上不起作用的解决方案,因为我无法访问协议whereHas Closure 中的 requester_id 值:

// All document types id's group by requester id's.
$documentTypesByRequester = DocumentType::all()
  ->groupBy('requester_id')
  ->map(function ($documentTypes, $requesterId) {
      return $documentTypes->pluck('id')
             ->toArray();
  })->toArray();
// Defined statically to reduce the complexity of question.
// $documentTypesByRequester = [
//    1 => [1, 2, 3],
//    2 => [4, 5]
// ];
// Here I have to select all protocols that have flows with
// documents having all document types of protocol requester.
$protocols = Protocol::whereHas('flows', function ($flows) use ($documentTypesByRequester) {
    // 
    // *---------------------------------------
    // * THIS DOESN'T WORK BUT IS WHAT I NEED!
    // *---------------------------------------
    // 
    // Access the requester id for current protocol.
    $requesterId = $flows->first()
        ->protocol
        ->requester_id;
    $documentTypesId = $documentTypesByRequester[$requesterId];

    return $flows->where('sequence', 1)
        ->whereHas('documents', function ($documents) use ($documentTypesId) {
            return $documents->whereIn('document_type_id', $documentTypesId);
        }, '=', count($documentTypesId));
})->get();

有一些方法可以访问这个 whereHas 闭包内的模型值,还是存在另一种方法来帮助我解决这个查询?

【问题讨论】:

  • 嘿,你能不能也分享一下你没有静态设置documentTypesByRequester的代码?我想试试这个查询,但是对于静态数据,它有点棘手,而且我可能会不必要地过度复杂化。
  • @AndriusRimkus 不是秘密。更新的问题。
  • 你能发布你的迁移和关系吗?
  • 一个流可以有多个相同类型的文档(每个请求者)吗?
  • @JonasStaudenmeir 是的!

标签: php mysql laravel eloquent


【解决方案1】:

试试这个:

$documentTypes = DocumentType::whereColumn('requester_id', 'protocol.requester_id');
$protocols = Protocol::whereHas('flows', function ($query) use ($documentTypes) {
    $query->where('sequence', 1)
        ->whereHas('documents', function ($query) use ($documentTypes) {
            $query->select(DB::raw('count(distinct document_type_id)'))
                ->whereIn('document_type_id', (clone $documentTypes)->select('id'));
        }, '=', DB::raw('('.(clone $documentTypes)->selectRaw('count(*)')->toSql().')'));
})->get();

【讨论】:

  • 绝招!但这不起作用,因为行 DB::raw('('.(clone $documentTypes)->selectRaw('count(*)')->toSql().')') 转换为 sql 字符串而不是 number 这就是参数所期望的...
  • 你试过查询了吗?
  • 看 Laravel API:whereHas(string $relation, Closure $callback, string $operator = '>=', int $count = 1)
  • 您仍然可以传递原始表达式。将->get() 替换为->toSql() 并查看结果。
  • 之前没有办法执行这个select,把他的返回值传给整型参数吗?
猜你喜欢
  • 2017-12-04
  • 2018-05-16
  • 2018-11-16
  • 1970-01-01
  • 2015-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多