Laravelでは様々な便利機能を用意してくれていますが、特にコレクションに関する習熟度は品質・生産性に大きく影響与えると思っています。
コレクションは簡単に言えば配列(連想配列含む)に対して同操作のための便利メソッドを多数提供してくれるラッパーオブジェクトです。
特にDBからの情報取得においてはモデル(Eloquent)を要素とするコレクションになるケースが多いため、コレクションを扱えることはDBを扱うための必須条件とも言えます。
コレクションには100以上のメソッドが用意されています。それ故に普段使っているのは一部の馴染みのある機能だけで、本来はコネクションのメソッドで簡単に実装できる処理を自製したり、漠然と覚えていた機能を使いたくなった段階で改めてネットで調べる必要が生じたりと、生産性・品質においてコネクションの恩恵を十分享受できていないケースも多いのではないでしょうか?(少なくとも私はそうです)。
これでは宝の持ち腐れと言うものです。
と言うことで、一度きっちりとコレクションの各機能に関して確認しておきたいと思います。
ただ、前述のように数が多く一度に整理するのは難しいため、何回かに分けて整理して行きます。
なお、対象となるLaravelのバージョンは現在のLTSである6.xです。
今回は初回と言うことで、まずはコレクションが持つメソッド全体の概要整理を行いたいと思います。
コレクションに関しては、最終的には全メソッドに関して細かな用法含めて記憶し、ネット等に頼らなくても使えるようになることを目指したいと思っていますが、その第一歩としてまずはメソッド名とざっくりとした用途を網羅的に把握しておく必要があると思います。
本記事では上記学習の資料的な位置付けとして、各メソッドを用途によって分類すると共にメソッド名と簡単な機能説明のセットを列記して行きます。前述したように目指すは「記憶」であるため、機能説明はあくまで記憶を呼び起こす程度の簡素なものにします。表現の正確性に関してはかなり怪しいものになりますが、その点はご容赦を。
また、先ほどさらっと「DBを扱う際にコレクションは必須」と言うようなことを書きましたが、モデル(Eloquent)のプロパティやメソッドおよびクエリの実行結果として取得されるコレクションは、実はオリジナルのコレクション(Illuminate\Support\Collection)ではなく、Eloquentコレクション(Illuminate\Database\Eloquent\Collection)と言うもののようです。
Eloquentコレクションも通常のコレクションを継承し機能拡張したものであるため、一般のコレクションとして整理した知識が概ねそのまま適用できます。よって、基本的には両者を区別しませんが、特に注意が必要なケースがあればその都度触れたいと思います。
なお、本記事および関連する記事においてはコレクションの元となった配列を「本体配列」と表記します。
要素の取得
配列でもそうですが、インデックスやキーによって特定の要素を取得する操作は基本中の基本です。
要素の取得に該当するメソッドを以下に列記します。
first | 最初の要素を取得(コールバックで条件指定も可能) |
firstWhere | 条件に合う最初の要素を取得 |
get | キーもしくはインデックスを指定して要素を取得 |
last | 最後の要素を取得(コールバックで条件指定も可能) |
pop | 最後の要素を取得しながらコレクションから削除 |
pull | キーを指定して要素を取得しながらコレクションから削除 |
random | ランダムに要素を取得 |
search | 指定した値を持つ要素のインデックスを取得 |
shift | 最初の要素を取得しながらコレクションから削除 |
全データ取得
個別の要素ではなくコレクションが持つ情報全体を取得したいこともあります。
単純に本体配列をそのまま配列の形で取得することもできますが、JSONエンコードされた形や文字列化して取得することも可能です。
そのようなコレクションの情報全体を所定の形式で取得するメソッドを以下に列記します。
all | 配列形式で取得(2次元以降のデータ型はそのまま) |
join | 指定したセパレータで要素を結合した文字列を取得(implodeより若干複雑な指定が可能) |
toArray | 配列形式で取得(2次元以降も変換) |
toJson | JSON形式で取得 |
サブセット取得
様々な条件に基づいてコレクションが持つ要素の一部だけを取得したいケースも結構あります。
そのような元コレクションのサブセットを取得するようなメソッドを以下に列記します。
diff | 指定したデータに含まれない要素を取得 |
diffAssoc | 指定したデータのキーと値の組み合わせが該当しない要素を取得 |
diffKeys | 指定した連想配列のキーと合致しないキーの要素を取得 |
duplicates | 重複した要素を取得 |
duplicatesStrict | duplicatesの厳密比較版 |
except | 指定したキーと合致しないキーの要素を取得 |
filter | 各要素に対してコールバックを呼び出し、戻り値がtrueの要素を取得 |
forPage | ページ単位の要素を取得 |
intersect | 指定したデータに含まれる要素を取得 |
intersectByKeys | 指定した連想配列のキーと合致するキーの要素を取得 |
nth | n番目の要素を取得 |
only | 指定したキーの要素を取得 |
partition | 指定した条件で要素を2つのコレクションに分ける |
reject | 各要素に対してコールバックを呼び出し、戻り値がfalseの要素を取得(filterの逆) |
skip | 先頭から指定の数だけ要素を除外して取得 |
slice | 指定したオフセットから指定した数だけ要素を取得 |
splice | 指定したオフセットから指定した数だけ要素を取得し、元コレクションから除外 |
take | 先頭から指定した数の要素を取得 |
unique | 重複を除外して要素を取得 |
uniqueStrict | uniqueの厳密比較版 |
where | 指定した条件に合致する要素を取得 |
whereStrict | whereの厳密比較版 |
whereBetween | 指定した2つの値の間に含まれる値を持つ要素を取得 |
whereIn | 指定した値(複数)に含まれる値を持つ要素を取得 |
whereInStrict | whereInの厳密比較版 |
whereInstanceOf | 指定したクラスの要素を取得 |
whereNotBetween | 指定した2つの値の間に含まれない値を持つ要素を取得 |
whereNotIn | 指定した値(複数)に含まれない値を持つ要素を取得 |
whereNotInStrict | whereNotInの厳密比較版 |
whereNotNull | 指定のメンバがNULL以外の要素を取得 |
whereNull | 指定のメンバがNULLの要素を取得 |
ソート
複数の要素が並んでいる構造においては、やはり並べ替え(ソート)は考えたくなります。
そのような並べ替えに関するメソッドを以下に列記します。
reverse | 並び順を反転させる |
shuffle | 並び順をシャッフルする |
sort | 昇順にソートする |
sortBy | 指定のメンバの値で昇順にソートする |
sortByDesc | 指定のメンバの値で降順にソートする |
sortKeys | キーで昇順にソートする |
sortKeysDesc | キーで降順にソートする |
values | インデックスを振り直す |
要素の追加・削除
配列に対して要素を追加・削除すると言うことも頻繁に行われる操作です。
そのような要素の追加・削除メソッドを以下に列記します。
concat | コレクションの末尾に複数要素を追加する |
forget | 指定した要素を削除する |
pad | 要素のパディング |
prepend | コレクションの先頭に1要素を追加する |
push | コレクションの末尾に1要素を追加する |
put | キーと値を追加する |
構造変換
既存コレクションをあくまで「元データ」や「材料」として、場合によってはデータを追加しながら、新たな構造を持つコレクションを生成すると言うこともよくあります。
そのような構造変換メソッドを以下に列記します。
chunk | 指定の数ごとに要素を分割する |
collapse | 多次元配列を一次元配列にする |
combine | 元コレクションの要素をキー、指定の配列の要素を値として連想配列生成 |
crossJoin | 元コレクションの要素と指定の配列の要素の全ての組み合わせの配列生成 |
flatMap | 全要素に対するコールバック関数による加工(結果は一次元配列) |
flatten | 多次元連想配列を一次元配列にする |
flip | キーと値を入れ替える |
groupBy | 指定のキーの値でグループ化 |
keyBy | 指定のキーの値で配列化(各要素は同じ値を持つ最後の要素) |
keys | キーのみを要素に持つ連想配列を取得 |
map | 全要素に対するコールバック関数による加工 |
mapInto | 全要素を特定クラスのインスタンスに変換 |
mapSpread | 二次元配列の二次元目の配列の要素を変数とするコールバック関数による加工 |
mapToGroups | groupByの機能+コールバックでの各要素に関する任意の加工 |
mapWithKeys | 全要素に対するコールバック関数による連想配列への変換 |
merge | 指定した配列をコレクションにマージ(キーが同じ場合は上書き) |
mergeRecursive | 指定した配列をコレクションにマージ(キーが同じで値が異なる要素は配列化) |
pluck | 指定したキーの値を配列化 |
replace | mergeの変化形として、キーではなくインデックスで対象要素を指定(対象指定は一次元) |
replaceRecursive | replaceの変化形として、多次元で対象指定可能 |
split | 指定した数のグループに分割 |
transform | 全要素に対するコールバック関数による加工(変更結果を自身に反映) |
union | 指定した配列をコレクションにマージ(キーが同じ場合は元の値を残す) |
zip | コレクションの各値と指定した配列内の同インデックスの値をセットとする二次元配列化 |
集計・分析
特に数値データが複数存在する状況においては、合計や平均値などを求めたいケースも多いです。
ここではそのような集計・分析メソッドを以下に列記します。
avg(average) | 平均値を取得 |
count | 要素数を取得 |
countBy | 同じ値に対するそれぞれの要素数を取得 |
max | 最大値を取得 |
median | 中央値を取得 |
min | 最小値を取得 |
mode | 最頻値を取得 |
sum | 合計値を取得 |
要素の有無
コレクションが特定の条件に該当するかどうかをチェックし、結果を真偽で返す機能も存在します。
そのようなチェックメソッドを以下に列記します。
contains(some) | 特定の条件を満たす要素が含まれているかどうかをチェック |
containsStrict | containsの厳密比較版 |
every | 全ての要素が条件を満たすかをチェック |
has | 特定のキーが含まれるかをチェック |
isEmpty | 中身が空かをチェック |
isNotEmpty | 中身が空でないかをチェック |
各要素に対する操作
単純に各要素に関してコールバックを呼び出すだけの機能も存在します。コールバックに関しては特に戻り値を期待するものでもなく単に実行するだけなので、表示を行うか、use文で配列やオブジェクトを参照渡しすることでコールバック内での処理結果をコールバック外に持ち出せるようにして使う必要があるかと思います。
そのような各要素に対してコールバックを呼び出すだけのメソッドを以下に列記します。
each | 各要素に関するコールバック実行 |
eachSpread | 各要素の値を引数とするコールバック実行 |
条件分岐
条件によってコールバックを実行するかどうかを切り替える処理も存在します。コールバックの引数はいずれも自コレクションのリファレンスであり、必要に応じて自身を加工することを目的とする機能であるように思われます。
そのような条件分岐メソッドを以下に列記します。
unless | 第一引数が偽の場合のみコールバック実行 |
whenEmpty(unlessNotEmpty) | コレクションが空の場合のみコールバック実行 |
whenNotEmpty(unlessEmpty) | コレクションが空でない場合のみコールバック実行 |
when | 第一引数が真の場合のみコールバック実行 |
コレクション生成
コレクションを使用する際にコレクションを生成する機能は基本中の基本に思えますが、実は意外に使うケースは少ないです。Laravelが提供する機能の戻り値がコレクションであり、自製処理内では同コレクションに対する操作から行うケースが大半だからです。
と言うことで使う機会は限定的かと思いますが、コレクション生成に関わるメソッドを以下に列記します。
collect | 同じ要素を持つ新しいコレクション生成 |
make | 新規コレクション生成(static) |
times | 特定の要素数の新規コレクション生成(static) |
unwrap | 可能であれば本体配列の取得(static) |
wrap | 可能であればコレクションでラップ(static) |
内容表示
ほぼデバッグ用だと思いますが、コレクションの内容を表示する機能もあります。
そのような表示メソッドを以下に列記します。
dd | コレクションの中身を表示し、処理を停止 |
dump | コレクションの中身を表示 |
その他
今まで紹介したカテゴリに含まれないような特殊なメソッドを以下に列記します。
implode | 指定したセパレータで要素を結合した文字列を取得する |
macro | 独自のCollectionメソッドを登録 |
pipe | コールバックに自身(コレクション)を渡し、処理結果を返す |
reduce | コールバックに対して前の要素の処理結果を渡し、同処理結果をさらに次の要素の処理に引き継ぐことで全要素に対して実施した処理結果を返す |
tap | メソッドチェーンの途中におけるコレクションを取得(同処理内での操作は元のコレクションには影響しない) |
総括
コレクションのメソッドに関しては一言では説明し難い物も多く、改めて見返してみても本記事だけ見て各メソッドの機能が想像できる物ではないと言うことがよく分かります。
最初に書いたように、本記事はコレクションの全メソッドが俯瞰的に確認できる程度を目指しており、あくまで機能に関する知識が(習熟度は様々なれど)事前にある人が復習や反復学習的に見ることを想定した物です。
その意味では、むしろこの程度の内容で良いかもしれません。この記事だけで用法が明確にイメージできるメソッドであれば、実際の開発でも有効に使って行けるでしょう。その判断材料にもなる内容であると前向きに捉えておきましょう。
と言うことで、次回以降で各メソッドの機能を詳しく整理して行きたいと思います。