【PHP】 変数、const、defineの使い方と使い分け
PHPの変数には、明確な宣言が不要、変数名の頭に$
をつけるなど、いくつか特徴があります。
PHPでは、変数名に変数を用いるメタプログラミングも簡単に書くことができます。
変数の宣言
PHPには、これと言って変数の宣言はありません。動的型付け言語であるため、型の指定もありません。Python等と同様に、代入されると変数が自動で作成されます。
また、変数名の頭に$
を必ず付ける必要があります。
// いきなり代入で良い $s = "Hello, PHP World!"; print($s);
変数名は$
でスタートしますが、他言語と同様に数値を1つ目に持ってくることはできません。
$1stName = "hoge"; // NG $_1stName = "hoge"; // OK
変数の初期化をせずに利用した場合
一切代入をしていない変数を使用しようとした場合、型が推測され、その型のデフォルトの値が取得されます。しかし、重大なバグの元になりうるため、通常は使わないようにします。
初期化していない変数を読み取ろうとすると警告が出るため、問題に気がつくことは可能です。
$a + 10; // 数値と計算しているので初期値は0。0 + 10になる $b . "hoge"; // 文字列となら、初期値は空文字列になる $c + 1.5; // 0.0になる (0ではない) // 比較演算子を使うと、比較対象に関わらずnullになる if ($z === null) { print("\$aは初期化されていないのでnull"); }
===
は厳密等価演算子で、自動的な型変換を行わずに比較するものです。
例えば0 == false
はtrue
になりますが、0 === false
は型が異なるためfalse
になります。
定数
PHPでは、const
やdefine
を使用して定数を宣言できます。
const
PHPでは、const
を付けることで代入不可能な変数を作成できます。この時、頭に$
は不要です。
ここで、constには変数を代入できません。100
や"hoge" . "fuga"
といった変数を使わない値や式のみです。関数の戻り値やクラスのインスタンス (要はオブジェクト型) を代入などもできません。配列や連想配列は代入できます。
C++のconstexpr
違い、関数の結果をコンパイル時に決定することができないなど、機能が小さめです。
また、PHPのconstは、オブジェクトの中身の変更もできなくなります。
const a = 100; print(a); // 100 $b = 500; const bb = $b; // Constant expression contains invalid operations const c = a + 200; // 定数と値のみを使った式はOK const d = [1, 2, 3]; d[1] = 200; // Cannot use temporary expression in write context const e = ["a" => 100, "b" => 200]; e["a"] = 500; // 同上
後述するdefine
を経由すれば、関数の戻り値や変数を設定できます。が、無意味なので普通はしないと思います。
define("HOGE", (function (){ return 100; })()); // const FUGA = (function (){ return 100; })(); はNG const FUGA = HOGE; print(FUGA); // 100
$hoge = 100; define("HOGE", $hoge); // const FUGA = $hoge; はNG const FUGA = HOGE; print(FUGA); // 100
constは、トップレベルやクラス内、namespace内のみで使用できます。 (つまり、関数内やブロック内では使用不可能)
if (true) { // トップレベルでないためNG const c = 100; // syntax error, unexpected token "const" } class Hoge { const FUGA = "100"; // OK function f() { return self::FUGA; // 使うときは self::定数名 } }
constは、名前空間が適用されます。
namespace Foo; const HOGE = "hoge"; print(\Foo\HOGE); // hogeを出力
define
define
も定数を定義するものです。
define
では、define("定数名", "入れる値");
のように書きます。const
と違い、入れる値には変数や関数の戻り値なども使用できます。 ただ、関数本体やインスタンスなど、オブジェクト型の値を入れることはできません。
define("HOGE", 100); print(HOGE); $a = 200; define("FUGA", $a); print(FUGA); define("HIGE", (function() { return 300; })()); print(HIGE);
100200300
define("AA", function () {}); // Fatal error: Uncaught TypeError: define(): Argument #2 ($value) cannot be an object, ... class Hoge {} $hoge = new Hoge(); define("BB", $hoge); // ほぼ同上
define
自体はどこでも宣言できますが、どこで宣言してもグローバルになります。
namespace Fuga { include "hoge.php"; function f() { // namespace Fuga内で宣言しているが、hoge.phpのnamespace Hoge内でも使える define("FOO", 100); // hoge.phpのf()を呼び出し \Hoge\f(); } f(); }
namespace Hoge { function f() { // app.phpのnamespace Fuga内で宣言したdefineが使える print(FOO); } }
しかし、define
は実際にdefineされた後でないと使用できません。defineした後ならどこでも使えます。
function f() { define("FOO", 100); } // print(FOO); // Fatal error: Uncaught Error: Undefined constant "FOO" ... f(); print(FOO); // OK
変数、const、defineの比較
普通の変数、const、defineの動作の違いを見てみましょう。
内容 | 変数 | const | define |
再代入 | O | X | X |
代入できる値 | 何でも | 定数や、オブジェクト型でない値 | 定数や、オブジェクト型でない変数や値、関数の戻り値 |
名前空間の反映 | O | O | X |
クラスの反映 | O | O | X |
スコープの反映 | O | (トップレベル以外宣言不可能) | X |
書き換えができる変数はよく使いますが、const
とdefine
の違いを知って適切に使い分けるようにすることが重要です。基本的には名前空間やクラスが反映されるconst
を推奨します。
変数の削除
PHPでは、unset
を利用して変数を削除する (未定義の状態にする) ことができます。メモリ量が心配な場合などに使うと良いですが、基本的にはスコープで管理する、そもそものメモリ量を見直すなどをするため、変数の削除はあまり使いません。
unset
は配列や連想配列の要素削除にも用います。どちらかというと、その用途がメインです。
$a = 10; print($a); unset($a); print($a);
10 Warning: Undefined variable $a in D:\Projects\shcool\app\資料用\practice\php\app.php on line 5
変数名に変数を用いる
変数名に変数を用いるメタプログラミングは、高度なプログラムを書くときに見受けられます。PHPでは、${式}
のようにすることで、式の結果を変数名にすることができます。
$hoge = 'fuga'; $f = ${'ho' . 'ge'}; print($f . "\n"); $varname = 'hoge'; $f = ${$varname}; // $hoge の値を代入 print($f . "\n"); $varname = 'f'; ${$varname} = 'foobar'; // $f に代入 print($f . "\n");
fuga fuga foobar
${ $varname }
のように、波括弧にスペースが入っていても問題ありません。
まとめ
PHPの変数の宣言は、代入が実質的な宣言となります。動的型付け言語のため、型の指定もありません。
定数の扱いではconst
とdefine
の違いを把握し、使い分けることが重要となります。
