まだPHPの配列の仕様をよく理解されていない方へ

PHPを使いもせずDISってる君達へ - Qiita」という記事がありました。

概ね正確な内容ですが、まだ根本的にPHPの配列の仕様がわかっていないような記述が一部に見受けられました。端的なものが以下です。

今まで話したようにPHPには配列型と辞書型は曖昧なものです。

およそプログラミング言語の実装において型が曖昧ということはありえません。内部的には型は厳密です。でなければ実装できません。

ただし、自動的に型が変わることがあり、ユーザの理解が曖昧だと、言語の仕様も曖昧に感じるということです。

ということで、PHPの配列についてよく理解していないPHPユーザもまだいるでしょうから、仕様について少し記事を書くことにします。

PHPの配列とは?

PHPの配列について知っておくべきことは以下ではないかと思います。

  • PHPの配列はarray型の1つしかない
  • PHPの配列は順番を保持している
  • 配列のキーの型は整数と文字列しかなく、両者は区別される
  • 配列のキーには暗黙の型変換が起こる!

配列のキーの暗黙の型変換

さて、問題です。以下の結果は?

<?php

$a = [
    '1' => 'one',
];

$b = [
    1 => 'one',
];

var_dump($a === $b);

答えはtrueです。

何故なら、$aのキー'1'は、整数にキャストされるからです。

$aをダンプして見ると、以下のように、ちゃんと整数になっています(1の前後には"はありません)。

array(1) {
  [1]=>
  string(3) "one"
}

他にもfloat、bool、nullの値をキーに指定した場合、暗黙の型変換が起こりますが、ユースケースは少ないのではないかと思います。気になる人は PHPマニュアル を参照してください。

まだ、信じていない人がいるかも知れませんので、似たような問題をもう一つ。以下の結果は?

<?php

$a = [
    '1' => 'string',
    1   => 'int',
];

var_dump($a);

これは、どちらのキーも同じ整数の1なので、後に記述されている要素で上書きされます。

array(1) {
  [1]=>
  string(3) "int"
}

さて、次の問題です。以下の結果は?

<?php

$a = [ "*" => "asterisk",  "@" => "atmark" ];
$b = [ "20" => "twenty",  "30" => "thirty" ];
$c = array_merge($a, $b);

var_dump($c);

これは以下のようになります。array_merge()では、キーが整数の要素は0から振り直されます。

array(4) {
  ["*"]=>
  string(8) "asterisk"
  ["@"]=>
  string(6) "atmark"
  [0]=>
  string(6) "twenty"
  [1]=>
  string(6) "thirty"
}

整数のキーと文字列のキーは扱いが異なることがわかります。

整合性について

直接関係ないですが、以下のラスマスさんの言葉は、なかなか興味深いものです。

私たちがPHPの整合性のなさを直さないと言ってよく非難する人がいますが,PHPはそもそもそれが問題になるようなものではないのです。PHPは結局,ライブラリやその他基盤となっているテクノロジーへのショートカットにすぎません。それなのに,どうして誰もがPHPレベルでの整合性を求めるのか,私には分かりません。整合性をとるのはフレームワークの役割です。
http://gihyo.jp/news/report/2015/12/1401?page=4 より。

この考えに従えば、PHPの関数の引数の順番や(プログラマのバックグランドによっては)わかりにくい仕様などはマニュアルを読めばいいだけの本当にどうでもよいことです。

ユーザが実際に使うのはフレームワーク(Packagistで提供されるようなパッケージも含んでそう呼んでいると思われます)です。何故、さっさとそういうパッケージを書かないのか?ということになります。

このラスマスさんの考えに賛同するかどうかはともかく、実際にPHPでの開発はフレームワーク上でOOPで行われているものが大部分であり、PHPの内部関数を直接扱う機会はどんどん減っていることは事実です。

参考

Date: 2015/12/22

Tags: php