You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel项目中使用模型自定义方法筛选集合报错咨询

解决Laravel中Collection::isAvailable不存在的错误

错误原因分析

你遇到的BadMethodCallException问题,根源出在groupBy('categorie.denumire')这个操作上:
当你调用get()后得到的是Eloquent\Collection,每个元素都是单个Produs模型实例;但执行groupBy后,返回的集合结构变成了嵌套集合——外层集合的键是分类名称,对应的值是该分类下所有Produs模型组成的子集合。

所以当你后续调用filter时,$produs参数指向的是子集合对象,而不是单个Produs模型,集合类自然没有你在模型里定义的isAvailable()方法,因此报错。


解决方案

根据你的需求,分两种场景给出处理方式:

场景1:先筛选可用产品,再按分类分组(推荐,性能更优)

如果你的目标是先找出所有符合条件的可用产品,再按分类整理,建议调整操作顺序,先筛选可用产品再分组:

// 先获取集合,筛选可用产品,再做过滤和分组
$models = Produs::with('categorie', 'poza', 'element_extra.extras')
    ->get()
    ->where('id_stare', 1)
    ->filter(function ($produs) {
        return $produs->isAvailable();
    })
    ->where('categorie.id_restaurant', $idRestaurant)
    ->groupBy('categorie.denumire');

$produse = $models->values();
进阶优化:数据库层面筛选(更高效)

上面的方式是在内存中筛选,如果你想进一步提升性能,建议把isAvailable()的逻辑迁移到数据库查询阶段,用查询作用域实现:

在Produs模型中添加查询作用域:

class Produs extends Model {
    protected $table = "elemente";
    public $timestamps = false;

    // 定义查询作用域,把isAvailable的逻辑转为数据库查询条件
    public function scopeAvailable($query)
    {
        // 替换成你isAvailable方法里的实际判断逻辑
        // 比如原逻辑是检查库存大于0,就写:
        return $query->where('stoc', '>', 0);
    }

    public function isAvailable(){
        // ... 原有的判断逻辑
    }
}

然后控制器中直接调用作用域,在数据库层面完成筛选:

$models = Produs::with('categorie', 'poza', 'element_extra.extras')
    ->where('id_stare', 1)
    // 用whereHas过滤关联分类的条件
    ->whereHas('categorie', function ($query) use ($idRestaurant) {
        $query->where('id_restaurant', $idRestaurant);
    })
    ->available() // 调用自定义作用域筛选可用产品
    ->get()
    ->groupBy('categorie.denumire');

$produse = $models->values();

场景2:先分组,再筛选每个分组内的可用产品

如果必须先按分类分组,再筛选每个分组里的可用产品,需要用map遍历每个分组,在分组内部执行筛选:

$models = Produs::with('categorie', 'poza', 'element_extra.extras')
    ->get()
    ->where('id_stare', 1)
    ->where('categorie.id_restaurant', $idRestaurant)
    ->groupBy('categorie.denumire');

// 遍历每个分类分组,筛选出组内可用的产品,并移除空分组
$produse = $models->map(function ($categoryProducts) {
    // 筛选当前分类下的可用产品
    return $categoryProducts->filter(function ($produs) {
        return $produs->isAvailable();
    })->values();
})
// 过滤掉没有可用产品的空分组
->filter(function ($filteredProducts) {
    return $filteredProducts->isNotEmpty();
})
->values();

内容的提问来源于stack exchange,提问作者Chirica Andrei

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 09:38:15