define () vs const

Довольно простой вопрос: на PHP, когда вы используете

define('FOO', 1); 

и когда вы используете

 const FOO = 1; 

Каковы основные различия между этими двумя?

Related of "define () vs const"

Начиная с PHP 5.3 существует два способа определения констант : либо использование ключевого слова const либо использование функции define() :

 const FOO = 'BAR'; define('FOO', 'BAR'); 

Основное различие между этими двумя способами заключается в том, что const определяет константы во время компиляции, тогда как define определяет их во время выполнения. Это приводит к большинству недостатков const . Некоторые недостатки const :

  • const не может использоваться для условного определения констант. Чтобы определить глобальную константу, ее необходимо использовать в самой внешней области:

     if (...) { const FOO = 'BAR'; // invalid } // but if (...) { define('FOO', 'BAR'); // valid } 

    Зачем вам это делать? Одно общее приложение – проверить, определена ли константа:

     if (!defined('FOO')) { define('FOO', 'BAR'); } 
  • const принимает статический скаляр (число, строка или другую константу, такую ​​как true , false , null , __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 s всегда чувствительны к регистру, тогда как define() позволяет вам определять нечувствительные к регистру константы, передавая true в качестве третьего аргумента:

     define('FOO', 'BAR', true); echo FOO; // BAR echo foo; // BAR 

Итак, это была плохая сторона вещей. Теперь давайте рассмотрим причину, по которой я лично всегда использую 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 также могут быть массивами, в то время как 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() .

    Хорошо известно, что PHP define() s медленны при использовании большого числа констант. Люди даже придумали такие вещи, как apc_load_constants() и hidef чтобы обойти это.

    const определение констант примерно в два раза быстрее (на машинах разработки с XDebug включен еще больше). Время поиска с другой стороны не изменяется (поскольку оба константных типа используют одну и ту же таблицу поиска): Demo .

Наконец, обратите внимание, что const может также использоваться в классе или интерфейсе для определения константы класса или константы интерфейса. define не может использоваться для этой цели:

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

Резюме

Если вам не нужно какое-либо условное или экспрессивное определение, используйте const s вместо define() s – просто для удобства чтения!

До PHP 5.3, const не может использоваться в глобальной области. Вы можете использовать это только из класса. Это следует использовать, если вы хотите установить какой-либо константный параметр или параметр, относящийся к этому классу. Или, может быть, вы хотите создать какой-то переименование.

define может использоваться с той же целью, но его можно использовать только в глобальной области. Его следует использовать только для глобальных настроек, которые влияют на все приложение.

Примером хорошего использования const является избавление от магических чисел. Взгляните на константы PDO . Когда вам нужно указать тип выборки, вы должны ввести PDO::FETCH_ASSOC , например. Если consts не были использованы, вы набрали бы что-то вроде 35 (или независимо от FETCH_ASSOC какой FETCH_ASSOC определен как). Это не имеет смысла для читателя.

Примером хорошего использования define может быть определение корневого пути вашего приложения или номера версии библиотеки.

Я знаю, что это уже ответили, но ни один из текущих ответов не упоминает об именах и о том, как это влияет на константы и определяет.

Начиная с PHP 5.3, consts и определяет аналогичные в большинстве случаев. Тем не менее, существуют некоторые важные отличия:

  • Константы не могут быть определены из выражения. 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 . Теперь вы сможете определить consts в терминах выражений, если эти выражения состоят из других констант или литералов. Это означает, что на 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 RND = mt_rand(); const CONSTVAR = $var; 

все равно будет.

Я считаю, что с PHP 5.3 вы можете использовать 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; ?> 

define i использовать для глобальных констант.

const используется для констант класса.

Вы не можете define в define класса, а с помощью const вы можете. Само собой разумеется, вы не можете использовать const вне класса

Кроме того, с const он фактически становится членом класса с define , он будет перенесен в глобальную область.

Ответ 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 бесполезным сбивающим с толку, так как идея const на десятках других языков заключается в том, что она всегда одинакова везде, где вы находитесь в вашем коде, и PHP на самом деле не гарантирует этого.

Большинство из этих ответов неверны или всего лишь наполовину рассказывают.

  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 

Да, const определяются во время компиляции, и поскольку никическим состояниям нельзя назначить выражение, как define (). Но и const нельзя объявить условно (по той же причине). то есть. Ты не сможешь это сделать:

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

Если вы можете с помощью define (). Таким образом, это не сводится к личным предпочтениям, есть правильный и неправильный способ использования обоих.

Как в сторону … Я хотел бы увидеть какой-то класс const, которому может быть присвоено выражение, своего рода define (), который может быть выделен для классов?

Чтобы добавить ответ NikiC. const можно использовать в классах следующим образом:

 class Foo { const BAR = 1; public function myMethod() { return self::BAR; } } 

Вы не можете сделать это с помощью define() .

Никто ничего не говорит о php-doc, но для меня это также очень важный аргумент в пользу предпочтения const :

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