PHPの2次元配列を使うと、データーベースの表データと同じようにデータを持てます。その配列をソートする方法です。
『DBのSQL使えよ!』って話ですが、PHPだけでも同じようにソートできます。しかし、実用的ではありません。遊びのプログラミングに近い。
サイトにテーブル(表)を表示するとき、ソート機能が必要になることってありますよね?
ただこの場合、まず先に考えるべきなのはDBのSQLを使うことです。
(テーブル操作でDBに勝てるものはない。)
それでダメならJavaScriptを使う。
(サーバーへのアクセス負荷がない。速い。)
今回の話は3番めの候補になるPHPでやってしまう方法です。
多次元配列でよく使う - array_column()
テーブルの情報は二次元配列データです。
(たて(列)とよこ(行)の2つあるから。)
PHPの多次元配列データでは、キーになる一次元の配列を使います。array_column()は多次元配列から一次元配列を取り出す関数です。
(名前のとおりカラム(列)を取り出す。)
<?php
$table = [
[ 'No' => '1', 'name' => '太郎', 'score' => '56', 'sexuality' => '男' ],
[ 'No' => '2', 'name' => '花子', 'score' => '80', 'sexuality' => '女' ],
[ 'No' => '3', 'name' => '次郎', 'score' => '35', 'sexuality' => '男' ],
[ 'No' => '4', 'name' => 'みか', 'score' => '70', 'sexuality' => '女' ],
[ 'No' => '5', 'name' => 'ジョン', 'score' => '67', 'sexuality' => '男' ],
[ 'No' => '6', 'name' => 'ステファニー', 'score' => '96', 'sexuality' => '女' ],
];
$name = array_column( $table, 'name');
var_export( $name );
array (
0 => '太郎',
1 => '花子',
2 => '次郎',
3 => 'みか',
4 => 'ジョン',
5 => 'ステファニー',
)
多次元配列は、[]が何層あるか?で判断します。
テーブルは2層なので2次元配列です。
多次元配列のデータでなにかをするとき、けっこう使うので覚えましょう。
ひとつの項目でソート - array_multisort()
PHPの配列のソートにはarray_multisort()を使います。DBのORDER BYのように複数の条件でソートすることもできます。
まずは、ひとつの条件(列)でソートしてみましょう。
<?php
$table = [
[ 'No' => '1', 'name' => '太郎', 'score' => '56', 'sexuality' => '男' ],
[ 'No' => '2', 'name' => '花子', 'score' => '80', 'sexuality' => '女' ],
[ 'No' => '3', 'name' => '次郎', 'score' => '35', 'sexuality' => '男' ],
[ 'No' => '4', 'name' => 'みか', 'score' => '70', 'sexuality' => '女' ],
[ 'No' => '5', 'name' => 'ジョン', 'score' => '67', 'sexuality' => '男' ],
[ 'No' => '6', 'name' => 'ステファニー', 'score' => '96', 'sexuality' => '女' ],
];
$score = array_column( $table, 'score' );
array_multisort( $score, SORT_DESC, $table );
var_export( $table );
SORT_ASC | 昇順 |
SORT_DESC | 降順 |
ソート対象の列の配列をarray_column()で作って、昇順・降順を指定します。
ここではスコアの高い順にソートします。
array (
0 =>
array (
'No' => '6',
'name' => 'ステファニー',
'score' => '96',
'sexuality' => '女',
),
1 =>
array (
'No' => '2',
'name' => '花子',
'score' => '80',
'sexuality' => '女',
),
2 =>
array (
'No' => '4',
'name' => 'みか',
'score' => '70',
'sexuality' => '女',
),
3 =>
array (
'No' => '5',
'name' => 'ジョン',
'score' => '67',
'sexuality' => '男',
),
4 =>
array (
'No' => '1',
'name' => '太郎',
'score' => '56',
'sexuality' => '男',
),
5 =>
array (
'No' => '3',
'name' => '次郎',
'score' => '35',
'sexuality' => '男',
),
)
array_multisort()のややこしいところは、関数のリターンは成否(true, false)しか返しません。
パラメータで指定した$tableの値を変更します。元データを変えたくないときは別変数に入れ直してから指定しましょう。
複数の項目でソート - array_multisort()
複数のデータをソートするのはかんたんです。array_multisort()のパラメータを増やします。
性別のスコアの高い順にソートしてみましょう。
<?php
$table = [
[ 'No' => '1', 'name' => '太郎', 'score' => '56', 'sexuality' => '男' ],
[ 'No' => '2', 'name' => '花子', 'score' => '80', 'sexuality' => '女' ],
[ 'No' => '3', 'name' => '次郎', 'score' => '35', 'sexuality' => '男' ],
[ 'No' => '4', 'name' => 'みか', 'score' => '70', 'sexuality' => '女' ],
[ 'No' => '5', 'name' => 'ジョン', 'score' => '67', 'sexuality' => '男' ],
[ 'No' => '6', 'name' => 'ステファニー', 'score' => '96', 'sexuality' => '女' ],
];
$sexuality = array_column( $table, 'sexuality' );
$score = array_column( $table, 'score' );
array_multisort( $sexuality, SORT_DESC, $score, SORT_DESC, $table );
var_export( $table );
array (
0 =>
array (
'No' => '5',
'name' => 'ジョン',
'score' => '67',
'sexuality' => '男',
),
1 =>
array (
'No' => '1',
'name' => '太郎',
'score' => '56',
'sexuality' => '男',
),
2 =>
array (
'No' => '3',
'name' => '次郎',
'score' => '35',
'sexuality' => '男',
),
3 =>
array (
'No' => '6',
'name' => 'ステファニー',
'score' => '96',
'sexuality' => '女',
),
4 =>
array (
'No' => '2',
'name' => '花子',
'score' => '80',
'sexuality' => '女',
),
5 =>
array (
'No' => '4',
'name' => 'みか',
'score' => '70',
'sexuality' => '女',
),
)
データベースのORDER BYと同じことができますね?
ただしこの関数は、ORDER BYの条件の数が決まっていないときには使いづらいです。
そこでちょっと工夫します。
サンプル - フレキシブルな条件に対応する
ORDER BYの条件を柔軟に対応する関数を作りました。まずはそれを見てみましょう。
<?php
$table = [
[ 'No' => '1', 'name' => '太郎', 'score' => '56', 'sexuality' => '男' ],
[ 'No' => '2', 'name' => '花子', 'score' => '80', 'sexuality' => '女' ],
[ 'No' => '3', 'name' => '次郎', 'score' => '35', 'sexuality' => '男' ],
[ 'No' => '4', 'name' => 'みか', 'score' => '70', 'sexuality' => '女' ],
[ 'No' => '5', 'name' => 'ジョン', 'score' => '67', 'sexuality' => '男' ],
[ 'No' => '6', 'name' => 'ステファニー', 'score' => '96', 'sexuality' => '女' ],
];
$order_by = [
[ 'sexuality', SORT_DESC ],
[ 'score', SORT_DESC ],
];
function my_sort( $table, $order_by ) {
$args = [];
foreach( $order_by as $tmp ) {
$args[] = array_column( $table, $tmp[ 0 ] );
$args[] = $tmp[ 1 ];
}
$args[] = &$table;
$result = call_user_func_array('array_multisort', $args) ? $table : false ;
return $result;
}
$result = my_sort( $table, $order_by );
var_export( $result );
さっきの性別スコア・ランキングと同じことをしています。ちがいは、$order_byの配列で自由に条件をつけられることだけ。
my_sort()のポイントは、array_multisortのパラメータの数を決めないで実行するためにcall_user_func_array()を使いました。
そしてもうひとつ、結果を受け取る$tableをリファレンス渡しします(&$table)。$argsの中から$tableを抜き出すのが面倒なので。
(C系言語で言えばダブル・ポインタ。)
array (
0 =>
array (
'No' => '5',
'name' => 'ジョン',
'score' => '67',
'sexuality' => '男',
),
1 =>
array (
'No' => '1',
'name' => '太郎',
'score' => '56',
'sexuality' => '男',
),
2 =>
array (
'No' => '3',
'name' => '次郎',
'score' => '35',
'sexuality' => '男',
),
3 =>
array (
'No' => '6',
'name' => 'ステファニー',
'score' => '96',
'sexuality' => '女',
),
4 =>
array (
'No' => '2',
'name' => '花子',
'score' => '80',
'sexuality' => '女',
),
5 =>
array (
'No' => '4',
'name' => 'みか',
'score' => '70',
'sexuality' => '女',
),
)
PHPでもかんたんにできますが、僕はDBのSQLでやっちゃったほうがいいかなと思います。
検索して結果をソートとか複合的なことはSQLにかなわないので。
うーん。array_multisort()は、そこまで使う場面があるんだろうか?