web-dev-qa-db-ja.com

define()vs const

かなり簡単な質問:PHPでは、いつ使うのですか

define('FOO', 1);

そしていつ使用しますか

const FOO = 1;

両者の主な違いは何ですか?

617
danjarvis

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は静的スカラー(数値、ストリング、またはtruefalsenull__FILE__などの定数)を受け入れますが、define()は任意の式を取ります。 PHP 5.6定数式はconstでも使用できます。

    const BIT_5 = 1 << 5;    // valid since PHP 5.6, invalid previously
    define('BIT_5', 1 << 5); // always valid
    
  • constはプレーンな定数名を取りますが、define()は任意の式を名前として受け入れます。これにより、次のようなことが可能になります。

    for ($i = 0; $i < 32; ++$i) {
        define('BIT_' . $i, 1 << $i);
    }
    
  • constは常に大文字と小文字を区別しますが、define()では3つ目の引数としてtrueを渡すことで大文字と小文字を区別しない定数を定義できます。

    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, valid in PHP 7.0
    

最後に、constはクラスまたはインターフェース内で クラス定数 またはインターフェース定数を定義するためにも使用できることに注意してください。 defineはこの目的には使用できません。

class Foo {
    const BAR = 2; // valid
}
// but
class Baz {
    define('QUX', 2); // invalid
}

まとめ

何らかの種類の条件付き定義や式定義が必要な場合を除き、define()sの代わりにconstsを使用してください - 単に読みやすくするためです。

981
NikiC

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

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

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

defineの適切な使用例は、アプリケーションのルートパスまたはライブラリのバージョン番号を指定することです。

194
ryeguy

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

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]になります。

=== UPDATE ===

今後の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;

まだ出ます。

35
GordonM

PHP 5.3以降、2番目の例に示すように、クラスの外でconstを使用できるようになります。

http://www.php.net/manual/en/language.constants.syntax.php

<?php
// Works as of PHP 5.3.0
const CONSTANT = 'Hello World';

echo CONSTANT;
?>
22
mattle

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

const私はクラス定数に使用します。

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

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

18
Jacob Relkin

NikiCの答えが最も良いのですが、名前空間を使うときには明白でない警告を付け加えておきましょう。覚えておくべきことは、define名前空間をdefine識別子の一部として明示的に追加しない限り、defineはグローバル名前空間の always にあるということです。それについて明白ではないのは、名前空間付き識別子がグローバル識別子よりも優れているということです。そう :

<?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はそれを保証するものではありません。

14
slartibartfast

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

  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
12
AwesomeBobX64

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

class Foo {
    const BAR = 1;

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

define()ではこれができません。

5
Marcus Lind

はい、constはコンパイル時に定義され、ニック状態には式を代入できません(define()の場合と同様)。しかし、constも条件付きで宣言することはできません(同じ理由で)。すなわち。これはできません。

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

あなたがdefine()でできるのに対して。それで、それは実際に個人的な好みに帰着しません、両方を使う正しいと間違った方法があります。

余談ですが、私は式を代入することができるある種のクラスconst、クラスに分離することができる一種のdefine()を見たいですか?

5
MrWhite

誰もphp-docについて何も言っていませんが、私にとっては、これもconstを優先するための非常に重要な議論です。

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

キーワード定数を定義すると、大文字と小文字を区別することができます。
鈍感ですが、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
1
GaziAnis