laravel 中的嵌套关​​系 whereHas

Nested relation whereHas in laravel

我想问一些在 laravel 中使用 whereHas 查询的嵌套关系,首先我会先解释模型,然后再进入我的主要案例。

这是我的模型:

StockIn.php

class StockIn extends Model {
    protected $primaryKey = "id_stock_in";

    /* this only column that I wanna show, and skip the else column */
    protected $fillable = ['stock_in_id_type'];

    public function type_of_items() {
        return $this->belongsTo('App\TypeOfitem', 'stock_in_id_type');
    }
}

TypeOfItem.php

class TypeOfItem extends Model {
    protected $primaryKey = "id_type_item";

    /* this only column that I wanna show, and skip the else column */
    protected $fillable = ['type_id_item'];

    public function items() {
       return $this->belongsTo('App\Item', 'type_id_item');
    }

    public function stock_ins() {
       return $this->hasMany('App\StockIn');
    }
}

Item.php

class Item extends Model {
    protected $primaryKey = "id_item";

    /* this only column that I wanna show, and skip the else column */
    protected $fillable = ['item_id_common_unit'];

    public function common_units() {
       return $this->belongsTo('App\CommonUnit', 'item_id_common_unit');
    }

    public function type_of_items() {
       return $this->hasMany('App\TypeOfItem');
    }
}

CommonUnit.php

class CommonUnit extends Model {
    protected $primaryKey = "id_common_unit";

    /* this only column that I wanna show, and skip the else column */
    protected $fillable = [/* describe column */];

    public function items() {
       return $this->hasMany('App\Item');
    }
}

我已经描述了我所有的模型,你可以看到所有 table (child) 都与每个 parent 有一些关系,例如:

stockIn -> typeOfItem (relation between child and parent)

typeOfItem -> Item (relation between child and parent)

Item -> CommonUnit (relation between child and parent)

所以问题是当我搜索 child 或 parent 中的所有数据时如何查询以获取嵌套关系中的数据?我已经查询了结果和我的预期不一样或者是null,可以这么说。

StockInController

$getData = StockIn::with(['type_of_items' => function ($query) {
            $query->select('id_type_item', 'type_id_item', 'code_type_of_item', 'type_of_item')
            ->with(['items' => function ($query) {
                $query->select('id_item', 'item_id_common_unit', 'name_item')
                ->with(['common_units' => function ($query) {
                    $query->select('id_common_unit', 'name_unit');
                }]);
            }]);
        }])
        ->with(['stock_out_left_join' => function ($query) {
            $query->select('id_stock_out', 'stock_out_id_stock_in');
        }])
        ->whereHas('type_of_items', function ($query) use ($search) {
            $query->where('code_type_of_item', 'like', "%{$search}%");
        })
        ->whereHas('type_of_items.items', function ($query) use ($search) {
            $query->orWhere('name_item', 'like', "%{$search}%");
        })
        ->whereHas('type_of_items.items.common_units', function ($query) use ($search) {
            $query->orWhere('name_unit', 'like', "%{$search}%");
        })
        ->orWhere('created_by', 'like', "%{$search}%")
        ->orWhere('edited_by', 'like', "%{$search}%")
        ->get()
        ->toArray();

哦,是的,我将在下面发送查询的示例数据:

但是当我使用某些关键字进行搜索时不起作用,例如当我输入“适配器”时,结果为空或我的数据中没有任何显示,那么我必须做什么?谢谢

好吧我想了一会儿我的问题终于得到了答案。好的分享给大家,我会稍微解释一下答案。

所以查询我在控制器上写的内容,我改成这样:

$getData = StockIn::with(['type_of_items' => function ($type_of_item) {
            $type_of_item->select('id_type_item', 'type_id_item', 'code_type_of_item', 'type_of_item')
            ->with(['items' => function ($item) {
                $item->select('id_item', 'item_id_common_unit', 'name_item')
                ->with(['common_units' => function ($common_unit) {
                    $common_unit->select('id_common_unit', 'name_unit');
                }]);
            }]);
        }])
        ->with(['stock_out_left_join' => function ($stock_out_left_join) {
            $stock_out_left_join->select('id_stock_out', 'stock_out_id_stock_in');
        }])
        ->whereHas('type_of_items', function ($type_of_items_search) use ($search) {
            $type_of_items_search->where('code_type_of_item', 'like', "%{$search}%")
                ->orWhere('type_of_item', 'like', "%{$search}%");
        })
        ->orWhereHas('type_of_items.items', function ($items_search) use ($search) {
            $items_search->where('name_item', 'like', "%{$search}%");
        })
        ->orWhereHas('type_of_items.items.common_units', function ($common_units_search) use ($search) {
            $common_units_search->where('name_unit', 'like', "%{$search}%");
        })
        ->orWhere('created_by', 'like', "%{$search}%")
        ->orWhere('edited_by', 'like', "%{$search}%")
        ->get()
        ->toArray();

如您所见,我的新查询在每个 with 函数中都有一个新参数,我用不同的名称命名所有参数,而不是 query 之前的名字,所以问题是每个 with 函数中的模糊参数,因为此查询基于 nested relation 所以我必须使参数名称彼此不同。或者你想让它们一个一个地拆分而不使用嵌套的 with 函数你也可以使用这个查询,我在下面放了这个:

$getData = StockIn::with(['type_of_items' => function ($query) {
            $query->select('id_type_item', 'type_id_item', 'code_type_of_item', 'type_of_item');
        }])
        ->with(['type_of_items.items' => function ($query) {
            $query->select('id_item', 'item_id_common_unit', 'name_item');
        }])
        ->with(['type_of_items.items.common_units' => function ($query) {
            $query->select('id_common_unit', 'name_unit');
        }])
        ->with(['stock_out_left_join' => function ($query) {
            $query->select('id_stock_out', 'stock_out_id_stock_in');
        }])
        ->whereHas('type_of_items', function ($query) use ($search) {
            $query->where('code_type_of_item', 'like', "%{$search}%")
                ->orWhere('type_of_item', 'like', "%{$search}%");
        })
        ->orWhereHas('type_of_items.items', function ($query) use ($search) {
            $query->where('name_item', 'like', "%{$search}%");
        })
        ->orWhereHas('type_of_items.items.common_units', function ($query) use ($search) {
            $query->where('name_unit', 'like', "%{$search}%");
        })
        ->orWhere('created_by', 'like', "%{$search}%")
        ->orWhere('edited_by', 'like', "%{$search}%")
        ->get()
        ->toArray();

我已经尝试过该查询并且它也有效(在每个 with 函数中使用相同的名称参数)。