PHP 5.4から配列定義は超簡単に、そして落とし穴も

Computer, Development 11月 23, 2011 #PHP
(Last Updated On: )

PHP 5.4 Advent Calender 2011用のエントリです。(まだ空きがあるので是非どうぞ)

このエントリを書いているのは11/23です。初めの方から重いネタだと後の方が苦労する(?)ので軽い話です。

PHP 5.3までの動作

現時点ではPHP Manualの配列のページには記載されていませんが、配列の定義が簡略化されます。まず現状の配列の定義方法は

<?php
$a = array('foo'=>123, 'bar'=>456, 789);
var_dump($a);

こんな感じですね。これを実行すると

$ ../php-src-5.4/php arr.php 
 array(3) {
 ["foo"]=>
 int(123)
 ["bar"]=>
 int(456)
 [0]=>
 int(789)
 }

このような出力になります。array()と定義するのは面倒だ、との声は昔からあったのですが遂に[]で配列が定義できるようになりました。

 

PHP 5.4以降の動作

PHP 5.4以降はこう書けるようになります。

<?php
$a = ['foo'=>123, 'bar'=>456, 789];
var_dump($a);

こんな風に配列を定義するならarray()でも構わないのですが、関数のパラメータなどに配列を直接渡す場合は今ひとつしっくりこない形になります。例えば、pg_query_params()関数はクエリのパラメータを配列で渡すのですが今まではこうなります。

$res = pg_query_params($db, ‘SELECT * FROM tbl
WHERE age >= $1 and gender = $2’, array(20, ‘m’));

これを

$res = pg_query_params($db, ‘SELECT * FROM tbl
WHERE age >= $1 and gender = $2’, [20, ‘m’]);

と書けるようになります。

細かい仕様変更ですが「なぜ配列定義が[]でできないの?」という声はずっと以前からありました。しかし、「PHPはPeople Hate Perlの略だ」と言われる所以からか「同じ事をするために複数の構文は要らない」とのポリシーで実装されませんでした。

「記号のような構文も要らない」とのポリシーで”<?=”と同じ動作する”<?php=”は実装されていません。これは私もパッチ付きで提案しました。1行パッチなのでたいした物ではないですが、”<?=”があるのに”<?php=”が無いのはおかしい、と思う人は他にもいて何度も提案されました。結局、5.4でも採用されていませんが、代わりに”<?=”が何時でも使えるようになりました。これでテンプレートなどの中で気軽に”<?=”が使えます。

話があさっての方向に行ってしまいましたが配列の落とし穴も紹介します。

PHP 5.4の配列オペレータ[]は文字列のオフセットにアクセスする方法として統一的に動作するようになりました。一時期は文字列オフセットには{}を使うべき、という頃もあったのですが[]でアクセスする方法が標準になります。この変更で従来とは異なる動作になってしまう場合があります。

<?php
$s = 'abc';

if (isset($s[0][0])) {
 echo 'Value is set!';
} else {
 echo 'Value is NOT set!';
}

PHP 5.4の場合

Value is set!

PHP 5.3の場合

Value is NOT set!

と逆の結果になります。これはPHP 5.4からは$s[0]は文字列の一文字目”a”となり$s[0]の”a”の更に一文字目の$a[0][0]も”a”になるからです。配列オペレータで文字列にアクセスした場合の動作に整合性を持たせた結果こうなりました。

先ほどの例では分りづらいですが配列の中の要素の更にその中の要素が空であるかチェックするようなコードが動作しなくなります。PEARライブラリの中では結構これが多用(?)されているらしくPEARの中の人がクレームをつけていました。詳しくは次のバグレポートを見てください。このブログのエントリを書いている今、議論が行われているので何か変更があるかも知れません。

https://bugs.php.net/bug.php?id=60362

言語として整合性が取れたことは良いことですが、思わぬところに落とし穴もあるので注意が必要です。

参考

追記

どうもNoticeエラーが出るようになりそうです!エラーがないと分りづらいのである方が良いと思います。

 

ちなみにPROVE for PHPがPHP 5.4に対応すれば、仕様変更がアプリケーションに影響するか、どこで違いが発生したのか即座にわかります。このエントリが公開される頃には、、、まだ公開できていないと思いますが、PHP 5.4リリースを機会に是非PROVEを試してみてください。

投稿者: yohgaki

コメントは受け付けていません。