PHPでは、次の2つの方法で定数を宣言できます。
キーワード
define
付きdefine('FOO', 1);
const
キーワードを使用するconst FOO = 1;
- これら2つの主な違いは何ですか?
- いつ、なぜ一方を使用する必要があり、いつもう一方を使用する必要がありますか?
PHP 5.3以降、定数を定義する方法は2つあります。const
キーワードを使用するか、define()
関数を使用するかのいずれかです。
const FOO = 'BAR';
define('FOO', 'BAR');
これら2つの方法の基本的な違いはconst
、コンパイル時に定数をdefine
定義するのに対し、実行時に定数を定義することです。const
これは、の不利な点のほとんどを引き起こします。のいくつかの欠点は次のconst
とおりです。
const
条件付きで定数を定義するために使用することはできません。グローバル定数を定義するには、最も外側のスコープで使用する必要があります。
if (...) {
const FOO = 'BAR'; // Invalid
}
// but
if (...) {
define('FOO', 'BAR'); // Valid
}
どうしてそんなことをしたいの?一般的なアプリケーションの1つは、定数がすでに定義されているかどうかを確認することです。
if (!defined('FOO')) {
define('FOO', 'BAR');
}
const
静的スカラー(数値、文字列、または、、、などの他の定数)を受け入れますがtrue
、任意の式を取ります。PHP 5.6の定数式も使用できるため、次のようになります。false
null
__FILE__
define()
const
const BIT_5 = 1 << 5; // Valid since PHP 5.6 and invalid previously
define('BIT_5', 1 << 5); // Always valid
const
プレーンな定数名を取りますが、名前define()
として任意の式を受け入れます。これにより、次のようなことが可能になります。
for ($i = 0; $i < 32; ++$i) {
define('BIT_' . $i, 1 << $i);
}
const
sは常に大文字と小文字を区別しますが、3番目の引数としてdefine()
渡すことで大文字と小文字を区別しない定数を定義できますtrue
(注:大文字と小文字を区別しない定数の定義はPHP 7.3.0で非推奨になり、PHP 8.0.0以降削除されました):
define('FOO', 'BAR', true);
echo FOO; // BAR
echo foo; // BAR
だから、それは物事の悪い面でした。const
次に、上記の状況のいずれかが発生しない限り、私が個人的に常に使用する理由を見てみましょう。
const
単に読みやすくなります。これは関数ではなく言語構造であり、クラスで定数を定義する方法とも一致しています。
const
、は言語構造であるため、自動化されたツールによって静的に分析できます。
const
現在の名前空間で定数を定義しdefine()
ますが、完全な名前空間名を渡す必要があります。
namespace A\B\C;
// To define the constant A\B\C\FOO:
const FOO = 'BAR';
define('A\B\C\FOO', 'BAR');
PHP 5.6const
の定数は配列にすることもできますが、define()
まだ配列をサポートしていません。ただし、PHP 7では、どちらの場合も配列がサポートされます。
const FOO = [1, 2, 3]; // Valid in PHP 5.6
define('FOO', [1, 2, 3]); // Invalid in PHP 5.6 and valid in PHP 7.0
最後に、これをクラスまたはインターフェース内で使用して、クラス定数またはインターフェース定数const
を定義することもできることに注意してください。この目的には使用できません:define
class Foo {
const BAR = 2; // Valid
}
// But
class Baz {
define('QUX', 2); // Invalid
}
概要
条件付きまたは式の定義が必要な場合を除いて、読みやすさのために、sconst
の代わりにsを使用してください。define()
PHP 5.3までconst
は、グローバルスコープで使用できませんでした。これは、クラス内からのみ使用できます。これは、ある種の定数オプションまたはそのクラスに関連する設定を設定する場合に使用する必要があります。または、ある種の列挙型を作成したい場合もあります。
define
同じ目的で使用できますが、グローバルスコープでのみ使用できます。これは、アプリケーション全体に影響を与えるグローバル設定にのみ使用する必要があります。
良い使い方の例はconst
、マジックナンバーを取り除くことです。PDOの定数を見てください。フェッチタイプを指定する必要がある場合はPDO::FETCH_ASSOC
、たとえば、と入力します。constsを使用しなかった場合は、次のように入力することになります35
(またはFETCH_ASSOC
定義されているもの)。これは読者には意味がありません。
適切な使用法の例はdefine
、アプリケーションのルートパスまたはライブラリのバージョン番号を指定することです。
これはすでに回答されていることは知っていますが、現在の回答のどれも、名前空間と、それが定数と定義にどのように影響するかについて言及していません。
PHP 5.3 以降、const と define はほとんどの点で似ています。ただし、いくつかの重要な違いがあります。
const FOO = 4 * 3;
動作しませんが、define('CONST', 4 * 3);
動作します。 define
名前には、その名前空間内で定義される名前空間が含まれている必要があります。以下のコードは違いを示しています。
namespace foo
{
const BAR = 1;
define('BAZ', 2);
define(__NAMESPACE__ . '\\BAZ', 3);
}
namespace {
var_dump(get_defined_constants(true));
}
ユーザー サブアレイの内容は になります['foo\\BAR' => 1, 'BAZ' => 2, 'foo\\BAZ' => 3]
。
===更新===
今後の PHP 5.6 では、const
. これらの式が他の定数またはリテラルで構成されている場合、式の観点から定数を定義できるようになりました。これは、5.6 の時点で以下が有効であることを意味します。
const FOOBAR = 'foo ' . 'bar';
const FORTY_TWO = 6 * 9; // For future editors: THIS IS DELIBERATE! Read the answer comments below for more details
const ULTIMATE_ANSWER = 'The ultimate answer to life, the universe and everything is ' . FORTY_TWO;
ただし、変数または関数の戻り値に関して const を定義することはまだできないため、
const RND = mt_rand();
const CONSTVAR = $var;
まだ出ます。
define
私はグローバル定数に使用します。
const
クラス定数に使用します。
define
クラススコープに入ることができません、そしてconst
あなたと一緒にできます。言うまでもなく、const
クラススコープ外では使用できません。
また、を使用するとconst
、実際にはクラスのメンバーになり、を使用するとdefine
、グローバルスコープにプッシュされます。
PHP 5.3 以降const
では、2 番目の例に示すように、クラスの外で使用できると思います。
http://www.php.net/manual/en/language.constants.syntax.php
<?php
// Works as of PHP 5.3.0
const CONSTANT = 'Hello World';
echo CONSTANT;
?>
NikiCの答えが最善ですが、名前空間を使用するときに、予期しない動作に巻き込まれないように、明白ではない警告を追加させてください。覚えておくべきことは、定義識別子の一部として名前空間を明示的に追加しない限り、定義は常にグローバル名前空間にあるということです。それについて明らかではないのは、名前空間化された識別子がグローバル識別子よりも優先されるということです。それで :
<?php
namespace foo
{
// Note: when referenced in this file or namespace, the const masks the defined version
// this may not be what you want/expect
const BAR = 'cheers';
define('BAR', 'wonka');
printf("What kind of bar is a %s bar?\n", BAR);
// To get to the define in the global namespace you need to explicitely reference it
printf("What kind of bar is a %s bar?\n", \BAR);
}
namespace foo2
{
// But now in another namespace (like in the default) the same syntax calls up the
// the defined version!
printf("Willy %s\n", BAR);
printf("three %s\n", \foo\BAR);
}
?>
生成:
What kind of bar is a cheers bar?
What kind of bar is a wonka bar?
willy wonka
three cheers
他の数十の言語でのconstの考え方は、コード内のどこにいても常に同じであり、PHPが実際にそれを保証するわけではないため、これはconstの概念全体を不必要に混乱させます。
これらの答えのほとんどは間違っているか、話の半分しか語っていません。
例えば:
const AWESOME = 'Bob'; // Valid
悪い例:
const AWESOME = whatIsMyName(); // Invalid (Function call)
const WEAKNESS = 4+5+6; // Invalid (Arithmetic)
const FOO = BAR . OF . SOAP; // Invalid (Concatenation)
変数定数を作成するには、次のように define() を使用します。
define('AWESOME', whatIsMyName()); // Valid
define('WEAKNESS', 4 + 5 + 6); // Valid
define('FOO', BAR . OF . SOAP); // Valid
はい、constはコンパイル時に定義され、define()のように、nikic状態に式を割り当てることはできません。ただし、constを条件付きで宣言することもできません(同じ理由で)。すなわち。これを行うことはできません:
if (/* some condition */) {
const WHIZZ = true; // CANNOT DO THIS!
}
これに対して、define()を使用することもできます。ですから、それは実際には個人的な好みに帰着するものではなく、両方を使用する正しい方法と間違った方法があります。
余談ですが...式を割り当てることができるある種のクラスconst、クラスに分離できる一種のdefine()を見たいですか?