如何将 Eloquent where() 应用于 hasMany() 关系中的子项

问题描述 投票:0回答:1

我想得到这个非常简单、常见的

SELECT
语句的结果:

SELECT * FROM parent
  JOIN child ON parent.id = child.parent_id
  WHERE child.column = 1;

对于非 SQL 流利者,这将返回所有父行和子行的所有列,其中名为

column
的子列包含值 1。

使用下面的 Laravel 模型,正确的 Eloquent 方法是什么?

<?php
class TheParent extends Model {
    public function child(): HasMany {
        return $this->hasMany(Child::class);
    }
}

class Child extends Model {
    public function parent(): BelongsTo {
        return $this->belongsTo(TheParent::class);
    }
}

// Fails.  Returns empty set.
$data = TheParent::getModel()
    ->child()
    ->where('column', 1)
    ->get();    // returns empty set

// Fails:  Returns correct data FOR JUST ONE parent Model if and only if a
// child meets the conditions. But find() is not usable for my purpose.
$data = TheParent::find(1)
    ->child()
    ->where('column', 1)
    ->get();

// Fails:  Only returns the parent data and cannot reference the child.
$data = TheParent::whereHas(
    'child',
    function ($query) {
        $query->where('column', 1);
    }
)->get();
php laravel eloquent
1个回答
3
投票

您已接近上次尝试;您的回调会过滤返回的

Parent
实例,但不会过滤附加的
Child
实例。尝试这样的事情:

$data = TheParent::whereHas('child', fn($q) => $q->where('column', 1))
    ->with(['child' => fn($q) => $q->where('column', 1)])
    ->get();

必须对

whereHas
with
方法重复回调...

  • TheParent::with('child')
    返回所有父母和所有孩子
  • TheParent::with(['child' => 'some condition'])
    返回所有带有一些孩子的父母
  • TheParent::whereHas('child', 'some condition')
    返回一些父母和所有孩子
  • TheParent::whereHas('child', 'some condition')->with(['child' => 'some condition'])
    返回一些父母和一些孩子。

从 Laravel 9.0 开始,如果

with()
whereHas()
使用相同的过滤器,则可以通过调用 withWhereHas()
简化
代码:

$data = TheParent::withWhereHas('child', fn($q) => $q->where('column', 1))->get();
© www.soinside.com 2019 - 2024. All rights reserved.