ORMのコレクションを扱っていると、稀に複合的な条件でソートしたい場合があります。
調べてみると楽勝で実装できましたので、ご紹介いたします。

確認した環境

  • PHP 7
  • Laravel 5.3

並び替えをするコレクション

$entities = collect([
  ['id' => 1, 'name' => 'item1', 'price' => 117, 'modified' => 1479370620],
  ['id' => 2, 'name' => 'item2', 'price' => 118, 'modified' => 1479370627],
  ['id' => 3, 'name' => 'item3', 'price' => 117, 'modified' => 1479370617],
]);

単一キーでのソート

ID昇順でソートする

sortBy()を利用します。

$ascSorted = $entities->sortBy('id');

ID降順でソートする

sortByDesc()を利用します。

$descSorted = $entities->sortByDesc('id');

複合キーでのソート

キーが1種類の場合はsortByを利用しますが、複合条件の場合はsortを利用しクロージャの中でスコアを評価します。

昇順でソートする場合、返り値は次のルールで決定します。

    1. 等価の場合 0を返す
    1. (first < second) の場合 -1を返す
    1. (first > second) の場合 1を返す

降順の場合、上記の2と3の返り値が入れ替わりますよ。


[price昇順 > id降順]するサンプルを掲載します。

$sortedEntities = $entities->sort(function($first, $second) {
     if ($first->price == $second->price) {
        return $first->id < $second->id ? 1 : -1 ;
     }
    return $first->price < $second->price ? -1 : 1 ;
  });
  // 引数が配列の場合は $first['id'] のように値を取り出してね

上記をdd()した結果がこちらです。

art-laravel-multisort-dd

コードについて、priceが等価である場合、第2ソートであるIDを評価する感じです。
どちらを-1にするのか迷ってしまいますが、ロジックは簡単ですね。

おわりに

面倒でわかりにくいphp標準関数のarray_multisort()はもう使わなくていいんです。

参考にしたstackoverflowでは、汎用的な関数が実装されておりますので、ぜひご覧になってください。
下記にリンクを掲載します。

この記事はtomita@atuwebがお届けしました。

参考

Laravel 日本語ドキュメント
Laravel 5.3 コレクション
https://readouble.com/laravel/5.3/ja/collections.html

stackoverflow
php – What is the syntax for sorting an Eloquent collection by multiple columns?
http://stackoverflow.com/questions/25451019/what-is-the-syntax-for-sorting-an-eloquent-collection-by-multiple-columns



Laravel: Up and Running: a Framework for Building Modern Php Apps 2016/11/28発売予定 (英語)

スポンサーリンク
ad_336
ad_336
  • このエントリーをはてなブックマークに追加
  • Evernoteに保存Evernoteに保存
スポンサーリンク
ad_336
コメントの入力は終了しました。