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

How to apply Eloquent where() to child in hasMany() relationship

我想获得这个非常简单、常见的 SELECT 语句的结果:

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

对于非SQL流利者,此returns所有父行和子行的所有列,其中名为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();

您最后一次尝试接近成功;您的回调过滤返回的 Parent 个实例,但不过滤附加的 Child 个实例。尝试这样的事情:

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

必须为 whereHaswith 方法重复回调...

  • TheParent::with('child') returns 全部 parents 全部 children
  • TheParent::with(['child' => 'some condition']) returns 所有 parents 和一些 children
  • TheParent::whereHas('child', 'some condition') returns 一些 parents 全部 children
  • TheParent::whereHas('child', 'some condition')->with(['child' => 'some condition']) returns 一些 parents 一些 children.