Di Laravel, jika saya melakukan kueri:
$foods = Food::where(...)->get();
... kemudian $foods
adalah Koleksi Illuminate dari Food
obyek model. (Pada dasarnya serangkaian model.)
Namun, kunci dari array ini hanyalah:
[0, 1, 2, 3, ...]
... jadi jika saya ingin mengubah, katakanlah, Food
objek dengan id
24, saya tidak bisa melakukan ini:
$desired_object = $foods->get(24);
$desired_object->color = 'Green';
$desired_object->save();
... karena ini hanya akan mengubah elemen ke-25 dalam larik, bukan elemen dengan id
24.
Bagaimana cara mendapatkan satu (atau beberapa) elemen dari koleksi berdasarkan atribut / kolom APA SAJA (seperti, tetapi tidak terbatas pada, id / color / age / etc.)?
Tentu saja, saya bisa melakukan ini:
foreach ($foods as $food) {
if ($food->id == 24) {
$desired_object = $food;
break;
}
}
$desired_object->color = 'Green';
$desired_object->save();
... tapi, itu menjijikkan.
Dan, tentu saja, saya bisa melakukan ini:
$desired_object = Food::find(24);
$desired_object->color = 'Green';
$desired_object->save();
... tapi itu bahkan lebih menjijikkan , karena melakukan kueri tambahan yang tidak perlu ketika saya sudah memiliki objek yang diinginkan dalam $foods
koleksi.
Terima kasih sebelumnya atas panduan apa pun.
EDIT:
Untuk memperjelas, Anda dapat memanggil ->find()
Koleksi Iluminasi tanpa memunculkan kueri lain, tetapi hanya menerima ID utama. Contohnya:
$foods = Food::all();
$desired_food = $foods->find(21); // Grab the food with an ID of 21
Namun, masih belum ada cara yang bersih (non-perulangan, non-kueri) untuk mengambil elemen dengan atribut dari Koleksi, seperti ini:
$foods = Food::all();
$green_foods = $foods->where('color', 'green'); // This won't work. :(
filter()->first()
Anda bisa meneleponfirst(function(...))
collect([1, 2, 3, 4])->first(function ($value, $key) { return $value == 2; });
$desired_object = $food->where('id', 24)->first();
Laravel menyediakan metode yang disebut
keyBy
yang memungkinkan untuk mengatur kunci dengan kunci yang diberikan dalam model.$collection = $collection->keyBy('id');
akan mengembalikan koleksi tetapi dengan kunci menjadi nilai
id
atribut dari model apa pun.Kemudian Anda bisa mengatakan:
$desired_food = $foods->get(21); // Grab the food with an ID of 21
dan itu akan mengambil item yang benar tanpa kekacauan menggunakan fungsi filter.
sumber
$exceptions->keyBy(function ($exception) { return $exception->category_id . ' ' . $exception->manufacturer_id;
dan digunakan->get($category->id . ' ' . $manufacturer->id)
setelahnya!keyBy
mengembalikan koleksi baru dari yang saya ingat, meskipun tidak yakin, Anda dapat memeriksanyaIlluminate/Support/Collection
untuk menemukannya. (Tidak bekerja di Laravel untuk beberapa waktu sehingga seseorang dapat mengoreksi saya).Mulai dari Laravel 5.5 Anda dapat menggunakan firstWhere ()
Dalam kasus Anda:
$green_foods = $foods->firstWhere('color', 'green');
sumber
Karena saya tidak perlu mengulang seluruh koleksi, saya pikir lebih baik memiliki fungsi pembantu seperti ini
/** * 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; }
sumber
Gunakan metode koleksi bawaan berisi dan temukan , yang akan mencari berdasarkan id utama (bukan kunci array). Contoh:
if ($model->collection->contains($primaryId)) { var_dump($model->collection->find($primaryId); }
contains () sebenarnya hanya memanggil find () dan memeriksa null, sehingga Anda dapat mempersingkatnya menjadi:
if ($myModel = $model->collection->find($primaryId)) { var_dump($myModel); }
sumber
Saya tahu pertanyaan ini awalnya ditanyakan sebelum Laravel 5.0 dirilis, tetapi pada Laravel 5.0, Koleksi mendukung
where()
metode untuk tujuan ini.Untuk Laravel 5.0, 5.1, dan 5.2,
where()
metode diCollection
hanya akan melakukan perbandingan yang sama. Selain itu, ia melakukan perbandingan yang sama ketat (===
) secara default. Untuk melakukan perbandingan longgar (==
), Anda dapat meneruskanfalse
sebagai parameter ketiga atau menggunakanwhereLoose()
metode.Pada Laravel 5.3,
where()
metode ini diperluas agar berfungsi lebih sepertiwhere()
metode untuk pembuat kueri, yang menerima operator sebagai parameter kedua. Juga seperti pembuat kueri, operator akan secara default menggunakan perbandingan yang sama jika tidak ada yang disediakan. Perbandingan default juga diubah dari ketat secara default menjadi longgar secara default. Jadi, jika Anda ingin perbandingan yang ketat, Anda dapat menggunakanwhereStrict()
, atau hanya menggunakan===
sebagai operatorwhere()
.Oleh karena itu, pada Laravel 5.0, contoh kode terakhir dalam pertanyaan akan bekerja persis seperti yang diinginkan:
$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');
sumber
Saya harus menunjukkan bahwa ada kesalahan kecil tapi sangat KRITIS dalam jawaban kalley. Saya berjuang dengan ini selama beberapa jam sebelum menyadari:
Di dalam fungsi, apa yang Anda kembalikan adalah perbandingan, dan dengan demikian sesuatu seperti ini akan lebih tepat:
$desired_object = $food->filter(function($item) { return ($item->id **==** 24); })->first();
sumber
foreach()
contoh saya dari segi kinerja, karena hanya melakukan jenis perulangan yang sama ... pada kenyataannya,foreach()
contoh saya berkinerja lebih baik karena rusak saat menemukan model yang benar. Juga ...{Collection}->find(24)
akan mengambil kunci utama, yang menjadikannya pilihan terbaik di sini. Filter yang diusulkan Kalley sebenarnya identik dengan$desired_object = $foods->find(24);
.**==**
operator, apa fungsinya?Solusi elegan untuk menemukan nilai ( http://betamode.de/2013/10/17/laravel-4-eloquent-check-if-there-is-a-model-with-certain-key-value-pair-in -a-collection / ) dapat diadaptasi:
$desired_object_key = $food->array_search(24, $food->lists('id')); if ($desired_object_key !== false) { $desired_object = $food[$desired_object_key]; }
sumber
Seperti pertanyaan di atas saat Anda menggunakan klausa where Anda juga perlu menggunakan metode get Or first untuk mendapatkan hasilnya.
/** *Get all food * */ $foods = Food::all(); /** *Get green food * */ $green_foods = Food::where('color', 'green')->get();
sumber