Php Laravel:按属性从集合中获取对象
在Laravel中,如果执行查询:Php Laravel:按属性从集合中获取对象,php,mysql,laravel,Php,Mysql,Laravel,在Laravel中,如果执行查询: $foods = Food::where(...)->get(); …然后,$foods是Food模型对象的一个集合。(基本上是一系列模型。) 但是,此数组的键仅为: [0, 1, 2, 3, ...] …因此,如果我想更改,Food对象的id为24,我不能这样做: $desired_object = $foods->get(24); $desired_object->color = 'Green'; $desired_object-&g
$foods = Food::where(...)->get();
…然后,$foods
是Food
模型对象的一个集合。(基本上是一系列模型。)
但是,此数组的键仅为:
[0, 1, 2, 3, ...]
…因此,如果我想更改,Food
对象的id
为24,我不能这样做:
$desired_object = $foods->get(24);
$desired_object->color = 'Green';
$desired_object->save();
…因为这只会更改数组中的第25个元素,而不是id为24的元素
如何通过任何属性/列(例如但不限于id/颜色/年龄等)从集合中获取单个(或多个)元素?
当然,我可以这样做:
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();
…但是,那太恶心了
当然,我可以做到:
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
集合中已经有了所需的对象时,它会执行额外的不必要的查询
提前感谢您的指导
编辑:
明确地说,您可以在不生成另一个查询的情况下对一个集合调用->find()
,但它只接受一个主ID。例如:
$foods = Food::all();
$desired_food = $foods->find(21); // Grab the food with an ID of 21
但是,仍然没有干净(非循环、非查询)的方法通过集合中的属性获取元素,如下所示:
$foods = Food::all();
$green_foods = $foods->where('color', 'green'); // This won't work. :(
您可以这样使用:
$desired_object = $food->filter(function($item) {
return $item->id == 24;
})->first();
过滤器
也将返回一个集合
,但由于您知道只有一个集合,因此可以首先调用该集合
你再也不需要过滤器了(也许永远都不需要,我不知道这已经快4年了)。您只需使用:
我必须指出,kalley的回答中有一个很小但绝对严重的错误。我挣扎了几个小时才意识到: 在函数内部,您返回的是一个比较,因此类似这样的内容更为正确:
$desired_object = $food->filter(function($item) {
return ($item->id **==** 24);
})->first();
因为我不需要循环整个集合,所以我认为最好有这样的helper函数
/**
* Check if there is a item in a collection by given key and value
* @param Illuminate\Support\Collection $collection collection in which search is to be made
* @param string $key name of key to be checked
* @param string $value value of key to be checkied
* @return boolean|object false if not found, object if it is found
*/
function findInCollection(Illuminate\Support\Collection $collection, $key, $value) {
foreach ($collection as $item) {
if (isset($item->$key) && $item->$key == $value) {
return $item;
}
}
return FALSE;
}
可以采用查找值()的优雅解决方案:
$desired_object_key = $food->array_search(24, $food->lists('id'));
if ($desired_object_key !== false) {
$desired_object = $food[$desired_object_key];
}
使用内置的收集方法contain和find,它们将按主ID(而不是数组键)进行搜索。例如:
if ($model->collection->contains($primaryId)) {
var_dump($model->collection->find($primaryId);
}
contains()实际上只是调用find()并检查null,因此可以将其缩短为:
if ($myModel = $model->collection->find($primaryId)) {
var_dump($myModel);
}
Laravel提供了一个名为
keyBy
的方法,该方法允许在模型中根据给定的键设置键
$collection=$collection->keyBy('id')代码>
将返回集合,但键是来自任何模型的id
属性的值
然后你可以说:
$desired_food=$foods->get(21);//抓取ID为21的食物
而且它可以抓取正确的项目,而不需要使用筛选函数。我知道这个问题最初是在Laravel 5.0发布之前提出的,但从Laravel 5.0开始,集合为此支持where()
方法
对于Laravel 5.0、5.1和5.2,集合
上的where()
方法只能进行相等比较。此外,默认情况下,它执行严格的等于比较(==
)。要进行松散比较(=
),可以传递false
作为第三个参数,或者使用whereLoose()
方法
从Laravel 5.3开始,扩展了where()
方法,使其更像查询生成器的where()
方法,该方法接受运算符作为第二个参数。与查询生成器一样,如果未提供任何值,则运算符将默认为等于比较。默认比较也从严格默认切换为宽松默认。因此,如果希望进行严格比较,可以使用whereStrict()
,或者只使用==
作为where()
的运算符
因此,从Laravel 5.0开始,问题中的最后一个代码示例将完全按照预期工作:
$foods = Food::all();
$green_foods = $foods->where('color', 'green'); // This will work. :)
// This will only work in Laravel 5.3+
$cheap_foods = $foods->where('price', '<', 5);
// Assuming "quantity" is an integer...
// This will not match any records in 5.0, 5.1, 5.2 due to the default strict comparison.
// This will match records just fine in 5.3+ due to the default loose comparison.
$dozen_foods = $foods->where('quantity', '12');
$foods=Food::all();
$green_foods=$foods->where('color','green');//这将起作用。:)
//这仅适用于Laravel 5.3+
$cheap_foods=$foods->where('price','如上所述,当您使用where子句时,还需要使用get或first方法来获得结果
/**
*Get all food
*
*/
$foods = Food::all();
/**
*Get green food
*
*/
$green_foods = Food::where('color', 'green')->get();
从Laravel 5.5开始,您可以使用
就你而言:
$green_foods = $foods->firstWhere('color', 'green');
如果您在Laravel中有一对多关系,您可以简单地编写以下内容。
(例如,您有汽车制造商和车型)
/**初始化数组*/
$data=[];
/**摘录集*/
foreach(Model::all()作为$Model){
/**初始化关系模型数组*/
$relationObjects=[];
/**迭代并生成关联数组*/
foreach($model->relationObjects作为$relObject){
$relationObjects[]=$relObject->name;//名称或任何您想要的属性
}
/**将“relationObjects”推送到共同响应的“modelName”键*/
$data[$model->name][]=$relationObjects;
}
$data
的格式如下:
[
“保时捷”:[
[
“卡宴”,
“911 GT3”
]
],
“福特”:[
[
“野马”
]
],
]
嘿,谢谢!我想我可以接受。在我看来,这通常是一个“雄辩”的框架,但它仍然非常冗长,哈哈。但到目前为止,它仍然比其他替代方案干净得多,所以我接受它。正如@squartastic在另一个答案中指出的,在你的闭包中,你是在进行分配,而不是比较(也就是说,您应该==而不是=)实际上甚至不需要调用filter()->first()
您可以从Laravel集合文档中调用first(函数(…)
。collect([1,2,3,4])->first(函数($value,$key){