725

PHPでは、次の2つの方法で定数を宣言できます。

  1. キーワードdefine付き

    define('FOO', 1);
    
  2. constキーワードを使用する

    const FOO = 1;
    

  • これら2つの主な違いは何ですか?
  • いつ、なぜ一方を使用する必要があり、いつもう一方を使用する必要がありますか?
4

9 に答える 9

1136

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の定数式も使用できるため、次のようになります。falsenull__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);
     }
    
  • constsは常に大文字と小文字を区別しますが、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()

于 2010-07-07T09:59:41.980 に答える
197

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

define同じ目的で使用できますが、グローバルスコープでのみ使用できます。これは、アプリケーション全体に影響を与えるグローバル設定にのみ使用する必要があります。

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

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

于 2010-03-15T14:26:56.463 に答える
38

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

PHP 5.3 以降、const と define はほとんどの点で似ています。ただし、いくつかの重要な違いがあります。

  • const を式から定義することはできません。 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;

まだ出ます。

于 2011-09-26T12:20:22.980 に答える
23

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

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

defineクラススコープに入ることができません、そしてconstあなたと一緒にできます。言うまでもなく、constクラススコープ外では使用できません。

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

于 2010-03-15T14:24:49.417 に答える
22

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;
?>
于 2010-06-30T01:16:29.077 に答える
19

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

于 2012-05-17T20:21:15.040 に答える
13

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

  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
于 2013-02-07T09:49:19.150 に答える
6

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

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

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

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

于 2010-07-07T22:40:56.090 に答える