programing tip

Laravel : 속성 별 컬렉션에서 객체 가져 오기

itbloger 2020. 10. 28. 07:48
반응형

Laravel : 속성 별 컬렉션에서 객체 가져 오기


Laravel에서 쿼리를 수행하면 :

$foods = Food::where(...)->get();

... 모델 객체 $foodsIlluminate 컬렉션 입니다 Food. (본질적으로 모델의 배열입니다.)

그러나이 배열의 키는 다음과 같습니다.

[0, 1, 2, 3, ...]

... 24의 값을 Food가진 객체 를 변경하려면 id이 작업을 수행 할 수 없습니다.

$desired_object = $foods->get(24);
$desired_object->color = 'Green';
$desired_object->save();

... 이는 id24 의 요소가 아닌 배열의 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');

기본 제공되는 컬렉션 메서드 containsfind를 사용하면 배열 키 대신 기본 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

반응형