Laravel pluck — コレクション/Eloquentで指定キーの値だけを抜き出す

未分類
  • カテゴリ: collection
  • 掲載バージョン: Laravel 12・PHP 8.4
  • 名前空間 / FQCN / コマンド: Illuminate\Support\Collection::pluck
  • 関連: mapWithKeys, keyBy, values, data_get, Eloquent Builder::pluck
  • 変更履歴: Laravel 12.x(12.20.0系): $value / $keyClosure を渡せるように拡張 (Laravel News)

要点(TL;DR)

  • 配列/モデル配列の「特定カラム(キー)」だけを抜き出して 新しいCollection を作る
  • 最低限の使い方:$names = $users->pluck('name');
  • よくある罠
    • $key を指定して キーが重複すると後勝ち(最後の要素で上書き) (Laravel)
    • ネストは ドット記法(例: speakers.first_day) (Laravel)
    • そもそも $value / $key が存在しないと null が混ざりやすい(後段で filter() などが必要)

概要

pluck は、コレクション各要素(配列/オブジェクト)から、指定したキーの値だけを抽出して新しいコレクションを作ります。フォームの選択肢(id => name)や、ログ/DTOの一部フィールドだけ欲しい時に最短で書けます。ネストはドット記法にも対応します。 (Laravel)

「Laravel pluck」で調べる場合、多くは Illuminate\Support\Collection::pluck() ではなく Eloquentモデル / クエリビルダの pluck()(DBから直接1〜2カラムだけ取り出すメソッド)を探しています。両者はメソッド名も引数も同じですが、動く場所とSQLへの影響が異なるため、この記事では両方を扱います。

構文 / シグネチャ

use Illuminate\Support\Collection;

/**
 * @param  string|array|\Closure  $value  // 取得する値(キー or ネスト指定 or 変換Closure)
 * @param  string|array|\Closure|null  $key // 結果のキー(任意)
 * @return \Illuminate\Support\Collection
 */
$plucked = $collection->pluck($value, $key = null);
  • 引数
引数必須既定値説明
$valuestring | array(Laravel 12.xで Closure も可)取り出す値のキー。ネストはドット記法(例: a.b) (Laravel)
$keystring | array | null(Laravel 12.xで Closure も可)null結果コレクションのキーに使う値のキー(重複時は後勝ち) (Laravel)
  • 戻り値Collection(抽出結果の新しいコレクション)
  • 例外/副作用:基本なし(元コレクションは変更しない/非破壊)

使用例

最小例

use Illuminate\Support\Collection;

$collection = collect([
    ['product_id' => 'prod-100', 'name' => 'Desk'],
    ['product_id' => 'prod-200', 'name' => 'Chair'],
]);

$names = $collection->pluck('name');

dump($names->all()); // ['Desk', 'Chair']

(公式例と同等) (Laravel)

実務例(select用の id => label を作る)

use App\Models\User;

$items = User::query()
    ->where('active', true)
    ->get(['id', 'name']) // ここは明示しておくと意図が伝わりやすい
    ->pluck('name', 'id'); // [id => name] の Collection

// Bladeなら: @foreach($items as $id => $name) ...

もし「結果を配列で欲しい」なら ->all()、連番キーにしたいなら ->values() を併用します。

Eloquent(クエリビルダ)の pluck — DBから直接抽出する

Eloquentモデルやクエリビルダにも同名の pluck() があります。こちらは get() で全カラムを取得してから絞り込むのではなく、SELECT文の段階で指定カラムだけを取得するため、レコード数が多いテーブルほどDB負荷とメモリ消費を抑えられます。

use App\Models\User;

// SELECT `name` FROM `users` 相当(全カラムを取得しない)
$names = User::pluck('name');

// SELECT `id`, `email` FROM `users` 相当。[id => email] の連想配列
$emails = User::pluck('email', 'id');

フォームの選択肢を作る(Bladeで <select> を組み立てる例)

// Controller側
$users = User::pluck('name', 'id'); // [id => name]

// Blade側
<select name="user_id">
    @foreach ($users as $id => $name)
        <option value="{{ $id }}">{{ $name }}</option>
    @endforeach
</select>
  • 大量データを扱う場合pluck() も結果は一括でメモリに載るため、件数が非常に多いテーブルでは where() で絞り込むか、chunk やクエリビルダの lazy() / cursor() との併用を検討します。
  • N+1問題との違いpluck() はリレーション先の一覧取得(例: 全ユーザーのメールアドレス一覧)には有効ですが、$user->posts->pluck('title') のようにループ内でリレーションを都度読みに行くとN+1問題は別途発生します。事前に with() で eager loading しておく点は他のリレーション取得と同じです。

よくある落とし穴・注意

  • キー重複は後勝ちpluck('color', 'brand') のように $key を指定して重複すると最後の要素で上書きされます。 (Laravel)
  • ネストはドット記法:配列の深い場所を speakers.first_day のように取れます(data_get 相当の挙動を期待すると安全)。 (Laravel)
  • 計算量の目安:O(n)(要素を1回走査)
  • チェーン可否 / 破壊的:チェーン可、非破壊(新しいCollectionを返す)
  • LazyCollectionLazyCollection 側にも pluck 関連の実装があり、同様の抽出用途で使えます(大量データなら lazy() / cursor() と組み合わせる選択肢)。 (api.laravel.com)

代替・関連APIとの比較

  • keyBy():要素全体をキーで引き直したい(id => モデル/配列)ならこちら。
  • mapWithKeys():キーと値を自由に整形して ['k' => 'v'] を作りたい(複雑な加工)ならこちら。
  • values()pluck() 後に連番に振り直したい時(キー指定した/元キーが残った等)。
  • only():キーの値ではなく、複数カラムを保ったまま要素を絞りたいならこちら。
  • groupBy():値ごとに1件だけ残す(後勝ち)ではなく、同じキーの要素を配列としてまとめたいならこちら。
  • combine():すでに分かれているキー配列と値配列を組み合わせたいなら、pluck() より combine() が直接的。
  • Eloquentの pluck()(Builder):DBから1〜2カラムだけ取る用途なら クエリ側の pluck が高速・省メモリになりやすい(必要カラムのみ取得)。Eloquentの基本も参照。

テスト例(Pest)

it('can pluck values and key them', function () {
    $collection = collect([
        ['id' => 10, 'name' => 'Desk'],
        ['id' => 20, 'name' => 'Chair'],
    ]);

    expect($collection->pluck('name')->all())->toBe(['Desk', 'Chair']);
    expect($collection->pluck('name', 'id')->all())->toBe([10 => 'Desk', 20 => 'Chair']);
});

トラブルシュート(エラー別)

症状/エラー原因対処
pluck したら null だらけ指定キーが存在しない / ネスト指定が間違いキー名を確認。ネストはドット記法にする。必要なら filter() で除去
$key 指定したら件数が減ったキー重複で上書き(後勝ち) (Laravel)キーがユニークになるよう見直す or groupBy() 等へ設計変更
取りたいのが「2列」以上pluck は基本1列(+キー列)map->only([...]) / select / DTO化などに切り替える

参考リンク

  • Laravel 12.x Collections — pluck() (Laravel)
  • Laravel News — pluckがClosure対応(2025-09-22) (Laravel News)
  • LaravelVersions(12.x変更一覧に pluck Closure 対応が記載) (Laravel Versions)
レン (Wren)

こんにちは。レンです。

Laravelのコードの森に住んでいる、小さな案内役です。
ルーティングの枝やクラスの影を歩きながら、コードの流れや仕組みを眺めています。

このサイトでは、Laravelの基本から実装のコツまで、開発で役立つポイントを静かに整理しています。
難しいことを増やすのではなく、コードの見通しが少し良くなるヒントを届けるのが役目です。

「この処理はどこに書くのがいいのか」
「Laravelではどう考えると整理できるのか」

そんな疑問に、小さなメモを残すような気持ちで記事を書いています。

コードを書いている途中で迷ったとき、
このサイトが少し立ち止まって整理できる場所になればうれしいです。

レン (Wren)をフォローする