Len*_*eng 77 php mysql laravel
在Laravel中,如果我执行查询:
$foods = Food::where(...)->get();
Run Code Online (Sandbox Code Playgroud)
......然后$foods
是照亮收集的Food
模型对象.(基本上是一系列模型.)
但是,这个数组的键只是:
[0, 1, 2, 3, ...]
Run Code Online (Sandbox Code Playgroud)
...所以如果我想改变Food
一个id
24 的对象,我不能这样做:
$desired_object = $foods->get(24);
$desired_object->color = 'Green';
$desired_object->save();
Run Code Online (Sandbox Code Playgroud)
...因为这只会改变数组中的第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();
Run Code Online (Sandbox Code Playgroud)
......但是,这只是粗暴的.
当然,我可以这样做:
$desired_object = Food::find(24);
$desired_object->color = 'Green';
$desired_object->save();
Run Code Online (Sandbox Code Playgroud)
...但是这更加严重,因为当我已经在$foods
集合中拥有所需的对象时,它会执行额外的不必要的查询.
提前感谢任何指导.
编辑:
为了清楚起见,您可以调用->find()
Illuminate Collection而不会生成另一个查询,但它只接受主ID.例如:
$foods = Food::all();
$desired_food = $foods->find(21); // Grab the food with an ID of 21
Run Code Online (Sandbox Code Playgroud)
但是,仍然没有干净(非循环,非查询)方法来从Collection中抓取元素,如下所示:
$foods = Food::all();
$green_foods = $foods->where('color', 'green'); // This won't work. :(
Run Code Online (Sandbox Code Playgroud)
kal*_*ley 105
您可以这样使用filter
:
$desired_object = $food->filter(function($item) {
return $item->id == 24;
})->first();
Run Code Online (Sandbox Code Playgroud)
filter
也将返回一个Collection
,但既然你知道只有一个,你可以打电话first
给那个Collection
.
您不再需要过滤器(或者可能永远不需要过滤器,我不知道这已经快4年了).你可以使用first
:
$desired_object = $food->first(function($item) {
return $item->id == 24;
});
Run Code Online (Sandbox Code Playgroud)
Mak*_*iak 100
Laravel提供了一种方法keyBy
,允许通过模型中的给定键来设置键.
$collection = $collection->keyBy('id');
将返回集合,但键是id
任何模型的属性值.
然后你可以说:
$desired_food = $foods->get(21); // Grab the food with an ID of 21
它会抓住正确的项目,而不会使用过滤功能.
从Laravel 5.5开始,您可以使用firstWhere()
在您的情况下:
$green_foods = $foods->firstWhere('color', 'green');
Run Code Online (Sandbox Code Playgroud)
由于我不需要循环整个集合,我认为最好有这样的辅助函数
/**
* 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;
}
Run Code Online (Sandbox Code Playgroud)
使用内置的集合方法contains和find,它将按主要ID(而不是数组键)进行搜索.例:
if ($model->collection->contains($primaryId)) {
var_dump($model->collection->find($primaryId);
}
Run Code Online (Sandbox Code Playgroud)
contains()实际上只调用find()并检查null,因此可以将其缩短为:
if ($myModel = $model->collection->find($primaryId)) {
var_dump($myModel);
}
Run Code Online (Sandbox Code Playgroud)
我知道这个问题最初是在Laravel 5.0发布之前提出的,但是从Laravel 5.0开始,Collections就支持这个where()
方法.
对于Laravel 5.0,5.1和5.2,该where()
方法Collection
只会进行等于比较.此外,它===
默认情况下严格等于compare().要进行宽松的比较(==
),您可以传递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');
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
109875 次 |
最近记录: |