在Laravel中,如果我执行查询:
$foods = Food::where(...)->get();
...则$foods
是Food
模型对象的Illuminate Collection(本质上是模型数组)。
但是,此数组的键只是:
[0, 1, 2, 3, ...]
......因此,如果我想修改id
为24的Food
对象,我不能这样做:
$desired_object = $foods->get(24);
$desired_object->color = 'Green';
$desired_object->save();
...因为这只会改变数组中的第25个元素,而不是id
为24的元素。
如何按ANY属性/列(例如但不限于id / color / age /等)从集合中获取单个(或多个)元素?
当然,我可以这样做:
foreach ($foods as $food) {
if ($food->id == 24) {
$desired_object = $food;
break;
}
}
$desired_object->color = 'Green';
$desired_object->save();
......但是,那太恶心了。
当然,我可以这样做:
$desired_object = Food::find(24);
$desired_object->color = 'Green';
$desired_object->save();
......但这 * 更恶心 *,因为当我在$foods
集合中已经有了所需对象时,它执行了一个额外的不必要的查询。
编辑:
需要说明的是,您 * 可以 * 在Illuminate Collection上调用->find()
,而无需生成另一个查询,但它 * 仅 * 接受一个主ID。
$foods = Food::all();
$desired_food = $foods->find(21); // Grab the food with an ID of 21
但是,仍然没有一种干净的(非循环、非查询)方法可以通过属性从Collection中获取元素,如下所示:
$foods = Food::all();
$green_foods = $foods->where('color', 'green'); // This won't work. :(
9条答案
按热度按时间2uluyalo1#
您可以使用
filter
,如下所示:filter
也将返回一个Collection
,但是因为您知道只有一个,所以可以在那个Collection
上调用first
。你不再需要过滤器了(也许永远不需要了,我不知道这已经有4年的历史了),你可以直接使用
first
:mwyxok5s2#
Laravel提供了一个名为
keyBy
的方法,允许通过模型中的给定键设置键。$collection = $collection->keyBy('id');
将返回集合,但键是任何模型的
id
属性的值。然后你可以说:
$desired_food = $foods->get(21); // Grab the food with an ID of 21
并且它将抓取正确的项目,而不会使用过滤器函数的混乱。
njthzxwz3#
从Laravel 5.5开始,您可以使用firstWhere()
在您的情况下:
kuarbcqp4#
使用内置的集合方法contain和find,它们将按主ID(而不是数组键)搜索。
contains()实际上只是调用find()并检查是否为null,因此可以将其缩短为:
czfnxgou5#
因为我不需要循环整个集合,所以我认为最好使用这样的helper函数
ddrv8njm6#
我知道这个问题最初是在Laravel 5.0发布之前提出的,但是从Laravel 5.0开始,集合支持
where()
方法用于此目的。对于Laravel 5.0、5.1和5.2,
Collection
上的where()
方法将只执行等于比较。此外,默认情况下,它执行严格等于比较(===
)。要执行松散比较(==
),您可以将false
作为第三个参数传递,或者使用whereLoose()
方法。从Laravel 5.3开始,
where()
方法被扩展为更像查询构建器的where()
方法,它接受一个运算符作为第二个参数。同样像查询构建器一样,如果没有提供运算符,运算符将默认为等于比较。默认比较也从默认的严格比较切换为默认的宽松比较。因此,如果您想要严格比较,可以使用whereStrict()
,或者只使用===
作为where()
的运算符。因此,从Laravel 5.0开始,问题中的最后一个代码示例将完全按预期工作:
eqfvzcg87#
可以采用用于查找值(http://betamode.de/2013/10/17/laravel-4-eloquent-check-if-there-is-a-model-with-certain-key-value-pair-in-a-collection/)的优雅解决方案:
kjthegm68#
正如上面的问题,当你使用where子句时,你也需要使用get Or first方法来得到结果。
x6492ojm9#
如果您在Laravel中有一对多关系,您可以简单地编写以下内容。
(for例如,您有一个汽车制造商和汽车型号)
$data
的格式为: