WHAT'S NEW?
Loading...

”恋に落ちる”どころか”結婚したくなる言語PHP"の配列について

すっかり忘れてた。
PHP Advent Calendar 2013だった。
今日は俺の担当だ。

というわけで、PHPの配列に関していろいろどうでもいい話をしようと思う。

まず俺がPHPを始めたのは2000年くらい。当時はバージョンが3だった。
PHPの名前もまだ、『PHP: Hypertext Preprocessor』の頭文字ではなく、『Personal Home Page』の略だった時代ね。そう、PHPはホームページやWebアプリ唯一専用のスクリプト言語だったんだよね。

当時はまだCGIが全盛期でPerlが主役だった時代。どの書店にいっても、ホームページコーナーにはCGIセクションがあり、そこにはPerl、CGIの2文字を冠した書籍しか見つけられなかったくらい。


しかしPerlはあくまでフォーマット言語。それにCGIというゲートウェイを通してしまうと、内部エラーが正しくブラウザに表示されないといういろいろな欠点を抱えていたんだよね。これはCGIであればPythonとかでも同じなんで、別にPerlが悪いわけじゃないんだけどさ。

で、PHPですよ。ずっとPerlやってたのに何でPHPに乗り換えたのかときかれたら、俺はまっさきに『配列』と答えるね。

うん、配列よ。
PHPの配列が如何に魅力的かを書いてみたい。

■配列に対して神経質すぎるほど気配を感じている


そもそもPHPには配列に関する関数がやたらに多く存在するんだ。

http://www.php.net/manual/ja/book.array.php

ココを見て貰えれば一目瞭然。こんなに沢山の配列をチョメチョメボテグリできるのって、なんで?と思うけど、実はPHPは配列をいじってこそのスクリプト言語なんだよね。

具体的な内部実装は別のブログでもやってるけど、簡単にいうと、PHPでは色々凝ったことするより、素直に配列をジャンジャンバリバリつかったほうが最終的な実行コストが安いってこと。だからC++とかJavaやってる人とは『え?』って思うかもしれないけど、兎に角PHPの醍醐味は配列と言ってもいいだろう。

PHPでの代表的なフレームワークでも、『おいおい、それじゃぁまるで、おまえの女房の長ったらしい中身のない話を玄関先で聞かされているようじゃないか!』ってなくらいに配列の階層が深かったりする。

CakePHPでモデルのバインドをする場合なんかだと、こんな風に書くことが多い。
$this->Profile->bindModel(array(
  'belongsTo' => array(
    'User' => array(
      'className' => 'User',
      'foreignKey' => 'user_id',
    )
  )
));
それでこの設定で得られる配列がこんなんだったりする。
Array
(
    [0] => Array
        (
            [User] => Array
                (
                    [id] => 1
                    [name] => 裏口男
                    [email] => backdoorman@ske69.jp
                    [created] => 2008-02-13 18:34:55
                    [modified] =>
                )
            [Profile] => Array
                (
                    [id] => 1
                    [user_id] => 1
                    [birthday] => 1980-01-02
                    [created] => 2008-02-13 18:34:55
                    [modified] =>
                )
        )
    [1] => Array
        (
            [User] => Array
                (
                    [id] => 2
                    [name] => シリアーナ
                    [email] => assshole@akb69.xxx
                    [created] => 2008-02-13 18:34:56
                    [modified] =>
                )
            [Profile] => Array
                (
                    [id] => 2
                    [user_id] => 2
                    [birthday] => 1982-03-05
                    [created] => 2008-02-13 18:34:55
                    [modified] =>
                )
        )
    [2] => Array
        (
            [User] => Array
                (
                    [id] => 3
                    [name] => 私はポール
                    [email] => penisest@nmb69.com
                    [created] => 2008-02-13 18:34:57
                    [modified] =>
                )
            [Profile] => Array
                (
                    [id] => 3
                    [user_id] => 3
                    [birthday] => 1980-06-14
                    [created] => 2008-02-13 18:34:55
                    [modified] =>
                )
        )
)
会社で絞られて家に帰ったらまた女房子どもからピーピーガーガー言われるくらいに前途多難で複雑で如何わしいだろ?と。
でもこれがPHPの醍醐味なんだ。

正直言うと、こんなに配列に対して狂気と優しさを感じる言語って、他にないんじゃないかなって思ってる。

■独自の配列操作メソッドを作ろうと思ったら最初からあったりする


例えばHTMLでselectタグを使う時、選択肢となるoptionタグにはvalueアトリビュートが必要になる。そしてvalueとは別に、画面に表示されるテキストノードが必要だ。
<select name="first">
  <option value="1">Good Times Bad Times</option>
  <option value="2">Babe I'm Gonna Leave You </option>
  <option value="3">You Shook Me</option>
  <option value="4">Dazed and Confused</option>
</select>
でも受け付けるプログラム側で、『1とか2とかじゃなくて、直接文字列を投げて欲しい』なんてとがおきちゃうこともたまにある。そう、正規化されてない構造の依頼なんか沢山あるので、何でもかんでもIDやキーで管理しようとする思想はもはやレガシーと言ってもいだろう。現場ではもっと柔軟性が要求される。

で、PHPだとそんなのは楽勝だ。

こんな配列だったとすると、別に配列を作り直さないでもいい。
$options = array(
    1 => 'Good Times Bad Times',
    2 => 'Babe I\'m Gonna Leave You',
    3 => 'You Shook Me',
    4 => 'Dazed and Confused',
  );
  • 配列のキーを1から始めているのは、selectタグでは0は『未定』や『内緒』などの選択肢に使えるからだ!
  • 最後のキーバリューペアの行末にカンマが付いてるのに疑問を持つ人がPHPerでも多くいるが、この書式こそPHPの醍醐味なんだからいちいちツッコミいらんよこのインチキPHP野郎め!
普通に配列のキーをそのまま値にしてくれる関数、array_valuesを使えばいいわけだ。そうすればoptionでもテキストノードでも文字がそのまま使えるんだ。

他にも、例えば誕生日を西暦を選択させるときなんか、現在から80年前の西暦をだし、そこから現在までを1年刻みで表示させれば事足りる。現在はまだ2013年なので、80年前は1933年だ。range関数を使えばいい。
range(1933, 2013);
これで1933から2013までの80要素をもった配列が生成される。一行だ。素晴らしい。求婚したくなるわ。

当然動的に
range(
  date('Y', strToTime('-80 YEAR'),
  date('Y')
);
でもOKだ。

■どんどん便利になるハイクオリティな配列操作


配列を返す関数の場合、例えば以下のように、配列の3番目(引数で言うと2)の値を表示するには、一度変数に代入し、そこから引数を指定して値を取り出す必要があったんだよ。ここでは$tmpに一旦代入してる。
$tmp = $this->__getUserIds();
echo $tmp[2];

private function __getUserIds() {
  ......

  return $user_ids;
}
でもPHP5.4からは、以下のように、直接戻り値を引数指定することが可能になった。
echo $this->__getUserIds()[2];

private function __getUserIds() {
  ......

  return $user_ids;
}
すごくね?ぶっちゃけすごくね?

■オブジェクトもいいけど引き続き配列をジャンジャン使おうぜ


というわけで、兎に角PHPを使うユーザには是非このページを熟読してもらいたい。

http://www.php.net/manual/ja/language.types.array.php
http://www.php.net/manual/ja/ref.array.php

PHPはどんどん発展してきている。でもトレイトがどうだとか、ラムダ関数がどうだとか、そういうのもいいけど、毎日ゴージャスな料理を食べてたら飽きるだろう。

毎日食べられるのは女房の手料理だ。そういう意味でも、泥臭いアプローチではあるけど、安定してる高機能な手料理ともいえる『PHPの配列』を、引き続きどんどん使っていこうじゃないか。

PHPの配列って、処理コストが安いんだよ。