Довольно простой вопрос: на PHP, когда вы используете
define('FOO', 1);
и когда вы используете
const FOO = 1;
Каковы основные различия между этими двумя?
Начиная с 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 на самом деле не гарантирует этого.
Большинство из этих ответов неверны или всего лишь наполовину рассказывают.
Например:
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';