Laravel에서 쿼리를 수행하면 :
$foods = Food::where(...)->get();
… 모델 객체 $foods
의 Illuminate 컬렉션 입니다 Food
. (본질적으로 모델의 배열입니다.)
그러나이 배열의 키는 다음과 같습니다.
[0, 1, 2, 3, ...]
… 24의 값을 Food
가진 객체 를 변경하려면 id
이 작업을 수행 할 수 없습니다.
$desired_object = $foods->get(24);
$desired_object->color = 'Green';
$desired_object->save();
… 이는 id
24 의 요소가 아닌 배열의 25 번째 요소 만 변경하기 때문 입니다.
모든 속성 / 열 (예 : 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();
…하지만 컬렉션에 원하는 개체가 이미있을 때 불필요한 추가 쿼리를 수행하기 때문에 훨씬 더 복잡 합니다 $foods
.
모든 안내에 미리 감사드립니다.
편집하다:
명확하게 말하면 다른 쿼리를 생성하지 않고 Illuminate 컬렉션을 호출 할 수->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. :(
답변
다음 filter
과 같이 사용할 수 있습니다 .
$desired_object = $food->filter(function($item) {
return $item->id == 24;
})->first();
filter
또한 반환됩니다 Collection
,하지만 당신은 하나가 될 것입니다 알고 있기 때문에, 당신은 호출 할 수 있습니다 first
그것에 Collection
.
더 이상 필터가 필요하지 않습니다 (또는 아마도 이것이 거의 4 년이 된 것인지 모르겠습니다). 다음을 사용할 수 있습니다 first
.
$desired_object = $food->first(function($item) {
return $item->id == 24;
});
답변
라 라벨은 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');
답변
전체 컬렉션을 반복 할 필요가 없기 때문에 이와 같은 도우미 기능을 갖는 것이 더 좋다고 생각합니다.
/**
* 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;
}
답변
기본 제공되는 컬렉션 메서드 contains 및 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 5.0이 출시되기 전에 요청되었지만 Laravel 5.0부터 Collections where()
는이 목적을위한 방법을 지원합니다 .
Laravel 5.0, 5.1 및 5.2의 경우의 where()
메서드 Collection
는 같음 비교 만 수행합니다. 또한 ===
기본적으로 엄격한 같음 비교 ( )를 수행합니다. 느슨한 비교 ( ==
) 를 수행하려면 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');
답변
나는 kalley의 대답에 작지만 절대적으로 중요한 오류가 있음을 지적해야합니다. 나는 깨닫기 전에 몇 시간 동안 이것으로 어려움을 겪었습니다.
함수 내에서 반환하는 것은 비교이므로 다음과 같은 것이 더 정확할 것입니다.
$desired_object = $food->filter(function($item) {
return ($item->id **==** 24);
})->first();