define()とconst


658

PHPでは、いつ使用しますか

define('FOO', 1);

いつ使用しますか

const FOO = 1;

これら2つの主な違いは何ですか?


4
パフォーマンス(私とミクロの最適化と時間の無駄)について、参照この回答をconst2倍の速さよりもありますdefine。ページの読み込み時間やメモリ使用量について:参照この質問この記事を ...また、オペコード・キャッシュについて何かを参照してくださいここに
Peter Krauss、2014年

2
現在受け入れられている回答だけを見るのではなく、stackoverflow.com
a / 3193704/1412157を確認

1
コメントの通知を見ました。承認された回答を更新しました。
danjarvis 2015

回答:


1039

PHP 5.3のようには二つの方法があるの定数を定義するには:使用していずれかの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(のような数値、文字列、または他の一定の静スカラーを受け入れtruefalsenull__FILE__一方、)define()任意の式をとります。PHP 5.6以降では、定数式も許可さ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);
    }
  • constsは常に大文字と小文字を区別define()しますがtrue、3番目の引数として渡すことで大文字と小文字を区別しない定数を定義できます(注:大文字と小文字を区別しない定数の定義は、PHP 7.3.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.6のconst定数は配列にもなりますが、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
}

概要

条件や式の定義が必要でない限り、単に読みやすくするために、constsではなくsを使用してdefine()ください。


1
私はPHP 5.6で知っているようにあなたもして、単純なスカラー式を使用する可能性得られますconst言語構造を-見wiki.php.net/rfc/const_scalar_exprs
mabe.berlin

6
使用するもう1つの利点constは、引用符がないことです。つまり、IDEで使用されるのと同じようにフォーマットされます。
rybo111 2015年

3
これは、PHPのドキュメントにあるはずです。これは、私が見た中で最も良い説明です。特に、ほとんどの人が忘れている部分です(コンパイルとランタイム)。
James

4
define('a', $_GET['param']);const b = a;完全に機能し、がconst c = $_GET['param'];無効である間に値を取得します。でconst、実際にコンパイル時間は?私はそうは思わない...(PHP 7.0.7でテスト済み)
mcserep

1
wiki.php.net/rfc/case_insensitive_constant_deprecation " PHP 8.0の場合:大文字と小文字を区別しない定数を宣言する可能性を取り除きます。 " 大文字と小文字の区別に関してここで冒険する他の人
Scuzzy

196

PHP 5.3までconstは、グローバルスコープでは使用できませんでした。クラス内からのみ使用できます。これは、そのクラスに関連するある種の定数オプションまたは設定を設定する場合に使用する必要があります。あるいは、ある種の列挙型を作成したいかもしれません。

define同じ目的で使用できますが、グローバルスコープでのみ使用できます。アプリケーション全体に影響するグローバル設定にのみ使用してください。

良いconst使い方の例は、マジックナンバーを取り除くことです。PDOの定数を見てください。フェッチタイプを指定する必要がある場合はPDO::FETCH_ASSOC、たとえばと入力します。constsが使用されなかった場合は、次のようなもの35(またはFETCH_ASSOC定義されているもの)を入力することになります。これは読者には意味がありません。

良いdefine使い方の例としては、アプリケーションのルートパスやライブラリのバージョン番号を指定することなどが考えられます。


12
const名前空間での使用について言及する価値があるかもしれません。
2010年

31
また、PHP5.3ではグローバルスコープでconstを非常に多く使用できることにも注意してください。
Gordon

5.2もできます。constsとdefineの優れた点は、クラス名をプレフィックスとして付ける必要があることです。それらを使用すると、コードが読みやすくなり、見栄えがよくなります。そして、それは私にとってボーナスです。
10

1
@ryeguyしかし、constをdefineのようにグローバルに使用できるPHP 5.3以降はどうですか?
andho 2012年

1
@andho、「改善」の1歩前進、1歩後退のダンスのPHPダンスに別のチョークを書きます。彼。:)
Falken教授の契約が

37

私はこれがすでに回答されていることを知っていますが、現在の回答では、名前空間とそれが定数と定義にどのように影響するかについて言及していません。

PHP 5.3以降、ほとんどの点でconstsと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ます。これらの式が他のconstまたはリテラルで構成されている場合、式の観点から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;

まだ出ます。


8
私は尋ねることに抵抗できませんでした:あなたは意識的にFORTY_TWO54と定義しましたか?
Punchlinern 2014

9
「シックス・バイ・ナイン?42?私はいつも宇宙に根本的な問題があると言っていました」完全な説明が必要な場合はダグラス・アダムスの作品をチェックしてください。
GordonM 2014

2
ああ。私は42が答えの生命、宇宙、そしてそれ以外のすべてであることを知っていました。説明ありがとう!
パンチライン14


20

define 私はグローバル定数に使用します。

const クラス定数に使用しています。

defineクラスのスコープに入れることはできませんconst。言うまでもなく、constクラスのスコープ外では使用できません。

また、を使用するとconst、実際にはクラスのメンバーになり、を使用するとdefine、グローバルスコープにプッシュされます。


8
他の回答で述べたように、constはPHP 5.3以降のクラスの外でも使用できます
MrWhite

名前空間定数の作成には、クラスだけでなくconstキーワードのみを使用できます
Alireza Rahmani Khalili

16

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の概念全体を不必要に混乱させます。


1
うん、しかし、BAR\foo\BARだけありません同じ定数。私はそれが本当に紛らわしいことに同意しますが、名前空間ロジックのようなものもこのように一貫していて、C マクロ()のようでもconstないと考える場合、PHPは何らかの言い訳を持つことができます。define()#define
Sz。

1
constの概念はまさにそれが振る舞うべき方法です-あなたは名前空間にいます!名前空間識別子なしで必要な場合は、名前空間外で作成します。これにより、異なる構文を使用していても、クラスで定義されているconstとの一貫性が保たれます。はい、定義も別の方法で一貫しています。
Gerard ONeill、2015年

12

これらの答えのほとんどは間違っているか、話の半分しか伝えていません。

  1. 名前空間を使用して、定数のスコープを設定できます。
  2. クラス定義の外で「const」キーワードを使用できます。ただし、クラスと同様に、「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

1
PHP> = 5.6 Zend Engine Compilerでいくつかの変更が行われ、現在constは別の方法で処理されています。
Ankit Vishwakarma 2016

6

はい、constはコンパイル時に定義されます。また、define()のようにnikic状態に式を割り当てることはできません。しかし、constも(同じ理由で)条件付きで宣言することはできません。すなわち。あなたはこれを行うことができません:

if (/* some condition */) {
  const WHIZZ = true;  // CANNOT DO THIS!
}

それに対して、define()を使用してできます。だから、それは本当に個人的な好みに帰着するのではなく、両方を使用する正しい方法と間違った方法があります。

余談ですが、式に割り当てることができるある種のクラスconst、クラスに分離できる一種のdefine()が欲しいですか?


5

NikiCの答えを追加します。constクラス内で次のように使用できます。

class Foo {
    const BAR = 1;

    public function myMethod() {
        return self::BAR;
    }
}

でこれを行うことはできませんdefine()


4

誰もが、PHP-docのについては何も言いませんが、私にとって、それはまたの好みのために非常に重要な引数ですconst

/**
 * My foo-bar const
 * @var string
 */
const FOO = 'BAR';

0

defineキーワード定数を使用すると、大文字と小文字を区別しない機能が提供されますが、constキーワードを使用すると使用できません。

define("FOO", 1, true);
echo foo; //1
echo "<br/>";
echo FOO; //1
echo "<br/>";

class A {
  const FOO = 1;
}

echo A::FOO; //valid
echo "<br/>";

//but

class B {
  define FOO = 1; //syntax error, unexpected 'define'
}

echo B::FOO; //invalid
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.