Laravel 7中contains方法返回null问题求助
首先得先理清你描述里的一个小矛盾:如果$food真的是空集合,那foreach循环根本不会执行,$foods应该还是空的,但你最后却得到了有数据的$foods。这里大概率是你混淆了Laravel查询构建器和集合:
如果$items是查询构建器(比如$items = Meal::query()),那么$items->where('name','sandwich')返回的还是查询构建器,不是集合。此时你如果用$food->isEmpty()判断是否为空会直接报错(因为查询构建器没有这个方法);但如果用count($food),它会执行查询并返回结果数,而遍历查询构建器的话,会重新执行查询并返回结果——所以你误以为$food是空的,实际遍历的时候拿到了数据。解决这个的办法是调用->get()把查询构建器转为集合:
$food = $items->where('name','sandwich')->get();
接下来是你最关心的核心问题:$foods->contains('meal',1)返回null。这里有几个可能的原因:
1. 你可能用错了方法
Laravel集合的contains方法只会返回布尔值true或false,从来不会返回null。如果你得到了null,大概率是不小心调用了firstWhere方法——它会返回第一个匹配的元素,没有匹配时返回null。先检查你代码里写的是不是真的是contains。
2. Laravel版本兼容性问题
如果你用的是Laravel 5.2或更早的版本,contains($key, $value)这种双参数写法只支持检查集合中对象的属性,不支持数组的键。而你push到$foods里的是$f->attributes(看起来是数组),所以这个写法不会生效。这种情况下,你需要用闭包来实现判断:
$b = $foods->contains(function ($item) { return isset($item['meal']) && $item['meal'] === 1; });
3. 元素类型或键名问题
- 如果
$f->attributes不是普通数组,而是一个对象(比如你强行访问了Eloquent模型受保护的$attributes属性,拿到了特殊对象),那你需要调整判断逻辑来检查对象属性:$b = $foods->contains(function ($item) { return isset($item->meal) && $item->meal === 1; }); - 另外,PHP数组的键名是大小写敏感的,如果你的数组键实际是
'Meal'而不是'meal',那么contains('meal',1)会返回false(注意不是null),这时候要检查键名的拼写和大小写。
总结
先确认你调用的是正确的contains方法,然后根据你的Laravel版本和$foods中元素的类型,选择对应的判断方式。另外记得把查询构建器转为集合,避免出现“空集合却能遍历出数据”的混淆情况。
内容的提问来源于stack exchange,提问作者SaroBeatbox

