質問: 先日こちらのページ PHPマニュアル > 付録 > 変更履歴 を眺めていたときに、 ![イメージ説明](https://teratail-v2.storage.googleapis.com/uploads/contributed_images/c9c0497bba453137da1386d3227beea7.png) 「define() に配列を定義できるようになった」と記述されており、 define ![イメージ説明](https://teratail-v2.storage.googleapis.com/uploads/contributed_images/c3c46c3938532115ff29c4ee35f6758d.png) 実際に以下のコードで試したところ ``` 100, 'b' => 200, 'c' => 300]); var_dump(ARRAY_SAMPLE_01); var_dump(ARRAY_SAMPLE_01[0]); var_dump(ARRAY_SAMPLE_02); var_dump(ARRAY_SAMPLE_02['b']); ``` 確かに動くのですが、いったいどんな場面で使えばいいの?というのが疑問です。 そもそも定数に定義できるのはスカラー値であるというルールのもとで利用していたので、配列を定義したいと思ったことがありません。 そこで質問なのですが、 1. これまで定数に配列を定義したいと思ったことがありますか? 2. また、それはどんなケースでしたか? 3. オブジェクト定数ではなく、グローバル空間に配列を定数を定義する積極的なメリットはあるか --- ちなみにこちらのコードは、PHP5.6, PHP7 両方の環境で動作しました。 ```
回答: PHPの定数定義の方法について、変遷を調べてみました。(参考: PHP>マニュアル>言語リファレンス>定数>構文、PHP>マニュアル>関数リファレンス>その他の基本モジュール>その他>その他の関数>define) * 〜5.2 `define`: スカラー値のみ `const`: 存在しない * 5.3〜5.5 `define`: スカラー値のみ `const`: スカラー値のみ * 5.6 `define`: スカラー値のみ `const`: スカラー値(スカラー式も可)と配列 ※ リソースも可能だが非推奨 * 7.0〜 `define`: スカラー値と配列 ※ リソースも可能だが非推奨 `const`: スカラー値(スカラー式も可)と配列 ※ リソースも可能だが非推奨 `define`は関数式、`const`は代入式という書き方の違いがあります。`define`はそもそも関数として扱われるため、値の部分に任意の式を書くことができます。7.0から`define`で配列も可能にしたのは、単に`const`にあわせていったと思われます。 なお、(Cを除く)他の言語の定数は、再代入できない(言語によっては警告を出すだけや、慣習としてそうするというのもある)ただの変数として扱う場合が多いです。そのため、 1. 定義は代入式 2. 任意のデータ(オブジェクト)を扱える という場合がほとんどです。初期のPHPは関数式の`define`だけで、しかもスカラー値のみであり、他の言語とは大きくかけ離れていました。それをバージョンアップの度に徐々にあわせていったと考えられます。 では、上を踏まえて、質問の回答です。 > > 1. これまで定数に配列を定義したいと思ったことがありますか? > > > あまりPHPを書かないのでPHPでそうしたいと思ったことは無いのですが、PHP以外の言語では普通に使っています。 > > 2. また、それはどんなケースでしたか? > > > 指定フォルダ内のファイルを処理するスクリプトで、除外するファイル一覧として['System Volume Information', '$RECYCLE.BIN', 'Desktop.ini', ...]みたいなのを作った事があります。そのプログラムで変わることが無いような、サポート済み形式とか、定義済みの名前とか、そういった物の一覧を初めから用意したいときに使っています。たとえば、HTML5を処理するようなプログラムで使用できる要素名一覧を定数配列に入れておくとかです。 > > 3. オブジェクト定数ではなく、グローバル空間に配列を定数を定義する積極的なメリットはあるか > > > `const`もグローバル空間に使用できます。まずは、クラス内とクラス外という比較で言えば、 1. クラス内だと名前空間が分かれるため、名前の衝突防止等が期待できます。(大規模開発では必須) 2. クラス内だとそのクラスに関連する定数だと一目でわかります。 と言う違いがあります。クラスを意識した作りにするのであればクラス内で書くべきでしょう。ただ、オブジェクト指向を使わないようなフラットなPHPにおいて、そのためだけにクラスを作るのはあまり意味が無いと思います。 では、グローバル空間において、`const`と`define`ですが、違いは代入式と関数式というところです。 1. `const`の代入式の方が、変数の代入と書き方が同じになるため、わかりやすいような気がします。 2. `define`は関数式なので、値部分を任意の式にできます。`const`の右辺は**スカラー式しか許されていません**。 特に2.の違いが重要です。 ``` define("HOGE", array_merge([1, 2], [8, 9])); ``` と書くことができますが、 ``` const HOGE = array_merge([1, 2], [8, 9]); ``` と書くことはできません。関数等を用いて配列を作り上げたい(他にもたとえば`range(1, 10)`など)ときは`define`を使うしかないようです。