Laravel : 속성 별 컬렉션에서 객체 가져 오기
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
필터 기능을 사용하지 않고도 올바른 항목을 잡을 수 있습니다.
전체 컬렉션을 반복 할 필요가 없기 때문에 이와 같은 도우미 기능을 갖는 것이 더 좋다고 생각합니다.
/**
* 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;
}
Laravel 5.5에서와 같이 firstWhere ()를 사용할 수 있습니다.
당신의 경우 :
$green_foods = $foods->firstWhere('color', 'green');
기본 제공되는 컬렉션 메서드 contains 및 find를 사용하면 배열 키 대신 기본 ID로 검색합니다. 예:
if ($model->collection->contains($primaryId)) {
var_dump($model->collection->find($primaryId);
}
contains() actually just calls find() and checks for null, so you could shorten it down to:
if ($myModel = $model->collection->find($primaryId)) {
var_dump($myModel);
}
I know this question was originally asked before Laravel 5.0 was released, but as of Laravel 5.0, Collections support the where()
method for this purpose.
For Laravel 5.0, 5.1, and 5.2, the where()
method on the Collection
will only do an equals comparison. Also, it does a strict equals comparison (===
) by default. To do a loose comparison (==
), you can either pass false
as the third parameter or use the whereLoose()
method.
As of Laravel 5.3, the where()
method was expanded to work more like the where()
method for the query builder, which accepts an operator as the second parameter. Also like the query builder, the operator will default to an equals comparison if none is supplied. The default comparison was also switched from strict by default to loose by default. So, if you'd like a strict comparison, you can use whereStrict()
, or just use ===
as the operator for where()
.
Therefore, as of Laravel 5.0, the last code example in the question will work exactly as intended:
$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');
I have to point out that there is a small but absolutely CRITICAL error in kalley's answer. I struggled with this for several hours before realizing:
Inside the function, what you are returning is a comparison, and thus something like this would be more correct:
$desired_object = $food->filter(function($item) {
return ($item->id **==** 24);
})->first();
Elegant solution for finding a value (http://betamode.de/2013/10/17/laravel-4-eloquent-check-if-there-is-a-model-with-certain-key-value-pair-in-a-collection/) can be adapted:
$desired_object_key = $food->array_search(24, $food->lists('id'));
if ($desired_object_key !== false) {
$desired_object = $food[$desired_object_key];
}
As the question above when you are using the where clause you also need to use the get Or first method to get the result.
/**
*Get all food
*
*/
$foods = Food::all();
/**
*Get green food
*
*/
$green_foods = Food::where('color', 'green')->get();
참고URL : https://stackoverflow.com/questions/20931020/laravel-get-object-from-collection-by-attribute
'programing tip' 카테고리의 다른 글
자바 스크립트에서 xml 엔티티를 이스케이프하는 방법은 무엇입니까? (0) | 2020.10.28 |
---|---|
Pandas 데이터 프레임에서 모두 0이있는 행 삭제 (0) | 2020.10.28 |
Gradle 다운로드시 Ionic 빌드 Android 오류 (0) | 2020.10.28 |
단위 테스트를 병렬이 아닌 직렬로 실행 (0) | 2020.10.28 |
jQuery를 사용하여 선택한 확인란의 값을 가져옵니다. (0) | 2020.10.28 |