递归关系和带约束的嵌套预加载

Recursive relationship and nested eager loading with constraints

我正在尝试使用递归关系的 where 约束创建嵌套的预加载

模型和查询模拟:

模型层次结构

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;

class Hierarchy extends Model
{
    protected $table = 'hierarchy';
    protected  $primaryKey = 'id_hierarchy';

    protected $fillable = [        
        'name',
        'parent_id'
    ];

    /**
     * @return HasMany 
     * 
     * This method implement recursive relationship
     */
    public function children()
    {
        return $this->hasMany(Hierarchy::class, 'parent_id')->with('children');
    }

    /**
    * @return HasMany
    */
    public function grandchildren()
    {
        return $this->hasMany(Grandchild::class, 'id_hierarchy');        
    }
}

模特孙子

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;

class Grandchild extends Model
{
    protected $table = 'grandchildren';
    protected  $primaryKey = 'id';

    protected $fillable = [        
        'id_hierarchy',
        'id_something'
        'name'
    ];

     /**
     * @return BelongsTo
     */
    public function hierarchy()
    {
        return $this->belongsTo(Hierarchy::class, 'id_hierarchy');
    }

}

以下查询没有 return 孙辈,因为它应该是;

 public function read($id) 
{

   $data = Hierarchy::query()
           ->whereNull('parent_id')
           ->with(['children.grandchildren' => function ($query) use($id)  {
                  $query->where('id_something',  $id);
           }])
           ->get();
}

问题出在约束中,因为在下面的查询中它 return 是孙子(尽管没有过滤,因为它没有 where 条件)

$data = Hierarchy::query()
        ->whereNull('parent_id')
        ->with(['children.grandchildren'])
        ->get();

提前感谢您提出解决此问题的建议。

已编辑:

由于代码是对真实案例的模拟,我添加了'id_something'以更清楚地涉及到什么。

'id_something' 与此处未表示的另一个模型有关

假设HomeCityGrandChild的相关模型之一,关系定义为

//GrandChild.php
public function home_city()
{
    return $this->hasMany(HomeCity::class);
}

然后查询到returnGrandChild记录谁住在HomeCityid_somethinghome_city上的一列table) by $id 可以写成:

public function read($id) 
{

   $data = Hierarchy::query()
           ->whereNull('parent_id')
           ->with(['children' => function ($query) use($id)  {
               $query->with(['grandchildren' => function($query) use($id) {
                   $query->whereHas('home_city', fn($query) => $query->where('id_something',  $id);
               }]);                  
           }])
           ->get();
}