PHP 5.4 の配列Tips

PHP5.4 Advent Calendar 2011 4日目です。3日目@ooharabucyouさんでした。

2日目@yohgakiさんの記事で紹介されたように、PHP 5.4から [] で配列を定義できるようになります。大変めでたいですね。

この記事ではその他の配列まわりの変更を紹介したいと思います。


Array Dereferencingの採用

RFC: Function Array Dereferencing が取り込まれました。

これまでは配列を返す関数の返り値の一部だけが欲しいときでも、その値を一度変数に格納してから $foo[0] や $bar['baz'] としてアクセスする必要がありました。

Array Dereferencingによって、関数呼び出しの後ろに [] 演算子で配列の要素に直接アクセスできるようになります。

サンプル1

function foo($value)
{
    return [0 => 'bar', 'baz' => $value];
}

$obj = new stdClass;
$obj->qux = 'quux';
var_dump(foo($obj)[0]);
var_dump(foo($obj)['baz']->qux);
var_dump(explode(' ', 'The quick brown fox jumps over the lazy dog')[3]);

出力

string(3) "bar"
string(4) "quux"
string(3) "fox"

array_combine()が空の配列を受け付けるようになった

Changed array_combine() to return empty array instead of FALSE when both parameter arrays are empty. FR #34857

リンク先にあるコメントのように、何らかの解析結果から連想配列を作成したいといったケースで、リストが空かどうかのチェックをする必要がなくなります。


(クラス,メソッド)または(オブジェクト,メソッド)のペアからなる配列変数の後ろに()を付けて呼び出せるようになった

Added indirect method call through array. FR #47160

is_callable()に与えてtrueを返す変数は全て後ろに()を付けて呼び出せるようになったとも言えます。

これによって、コールバック関数を受ける関数をスマートに書けたりします。

サンプル2 冗長な記述

function hoge($callback, $arg1, $arg2)
{
    if (is_array($callback)) {
        list($object_or_classname, $method) = $callback;
        if (is_object($object_or_classname)) {
            return $object_or_classname->$method($arg1, $arg2);
        } else {
            return $object_or_classname::$method($arg1, $arg2);
        }
    }
    return $callback($arg1, $arg2);
}

サンプル3 call_user_func()

function hoge($callback, $arg1, $arg2)
{
    return call_user_func($callback, $arg1, $arg2);
}

サンプル4 コードが明瞭に

function hoge($callback, $arg1, $arg2)
{
    return $callback($arg1, $arg2);
}

配列をソートする関数のオプションに SORT_NATURAL と SORT_FLAG_CASE が加わった

Added support for SORT_NATURAL and SORT_FLAG_CASE in array sort functions (sort, rsort, ksort, krsort, asort, arsort and array_multisort). FR#55158

array_multisort()でもnatsort()natcasesort()相当の比較をしたいということで実装されました。

まずは特にフラグをつけずにarray_multisortにかけてみましょう。

サンプル5

$jojo = ['Jonathan', 'Joseph', 'Jotaro', 'Josuke', 'Jorno', 'Jolyne', 'Joshu'];
$php = ['PHP 5.3.7', 'PHP 5.2.7', 'PHP 5.2.17', 'PHP 5.3.9alpha1', 'PHP 5.4.0RC2', 'PHP 5.3.9RC2', 'PHP 5.4.0beta1'];

array_multisort($php, $jojo);
print_r(array_combine($jojo, $php));

出力

Array
(
    [Jotaro] => PHP 5.2.17
    [Joseph] => PHP 5.2.7
    [Jonathan] => PHP 5.3.7
    [Jolyne] => PHP 5.3.9RC2
    [Josuke] => PHP 5.3.9alpha1
    [Jorno] => PHP 5.4.0RC2
    [Joshu] => PHP 5.4.0beta1
)

普通に$phpを文字列として比較した結果が返ってきていますね。

次にSORT_NATURALをセットしてみましょう。

サンプル6

array_multisort($php, SORT_NATURAL, $jojo);
print_r(array_combine($jojo, $php));

出力

Array
(
    [Joseph] => PHP 5.2.7
    [Jotaro] => PHP 5.2.17
    [Jonathan] => PHP 5.3.7
    [Jolyne] => PHP 5.3.9RC2
    [Josuke] => PHP 5.3.9alpha1
    [Jorno] => PHP 5.4.0RC2
    [Joshu] => PHP 5.4.0beta1
)

数字が人にとって自然な順にソートされました。

さらにSORT_FLAG_CASEも加えてみましょう。

サンプル7

array_multisort($php, SORT_NATURAL | SORT_FLAG_CASE, $jojo);
print_r(array_combine($jojo, $php));

出力

Array
(
    [Joseph] => PHP 5.2.7
    [Jotaro] => PHP 5.2.17
    [Jonathan] => PHP 5.3.7
    [Josuke] => PHP 5.3.9alpha1
    [Jolyne] => PHP 5.3.9RC2
    [Joshu] => PHP 5.4.0beta1
    [Jorno] => PHP 5.4.0RC2
)

大文字/小文字を無視してソートされていますね。 この例だとuasort($ary, 'version_compare')でもいいじゃないかというツッコミは却下します。


まとめ

ここで紹介した新機能はPHPプログラムをシンプルに記述する上でちょっと役に立つと思います。

必ずしも短く書けるといいということではありませんが、プログラムの意図をより明確にできるのは良いことですね。

明日は@chobi_eさんです。

まだ枠はありますので、参加者も絶賛募集中です!