Довольно простой вопрос: в 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
всегда чувствительны к регистру, тогда как 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 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()
s.
Хорошо известно, что PHP define()
медленны при использовании большого числа констант. Люди даже придумали такие вещи, как apc_load_constants()
и hidef
чтобы обойти это.
const
сделать определение констант примерно в два раза быстрее (на машинах разработки с XDebug включен еще больше). Время поиска с другой стороны не изменяется (поскольку оба константных типа используют одну и ту же таблицу поиска): Demo.
Наконец, обратите внимание, что const
также может использоваться в классе или интерфейсе для определения константы класса или константы интерфейса. define
не может использоваться для этой цели:
class Foo {
const BAR = 2; // valid
}
// but
class Baz {
define('QUX', 2); // invalid
}
Резюме
Если вам не нужен какой-либо условный или экспрессивный определение, используйте const
вместо define()
- просто для удобства чтения!
const
- см. Wiki.php.net/rfc/const_scalar_exprs
const
является отсутствие кавычек, что означает, что он отформатирован так же, как и в вашей IDE.
Пока PHP 5.3, const
не может использоваться в глобальной области. Вы можете использовать это только из класса. Это следует использовать, если вы хотите установить какой-либо константный параметр или параметр, относящийся к этому классу. Или, возможно, вы хотите создать какой-то перемычек.
define
может использоваться с той же целью, но его можно использовать только в глобальной области. Его следует использовать только для глобальных настроек, которые влияют на все приложение.
Примером хорошего использования const
является избавление от магических чисел. Взгляните на константы PDO. Когда вам нужно указать тип выборки, вы должны набрать PDO::FETCH_ASSOC
, например. Если consts не были использованы, вы в конечном итоге набрали бы что-то вроде 35
(или другое FETCH_ASSOC
определено как). Это не имеет смысла для читателя.
Примером хорошего использования define
может быть, указав корневой путь вашего приложения или номер версии библиотеки.
const
с пространствами имен.
Я знаю, что это уже ответили, но ни один из текущих ответов не упоминает об именах и о том, как он влияет на константы и определяет.
Как и в случае PHP 5.3, константы и определения аналогичны в большинстве случаев. Тем не менее, существуют некоторые важные отличия:
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;
по-прежнему будет отсутствовать.
FORTY_TWO
как 54?
Я считаю, что с 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
Я использую для глобальных констант.
const
Я использую для констант класса.
Вы не можете define
в поле класса, а с помощью const
можете.
Разумеется, вы не можете использовать const
область внешнего класса
Кроме того, с const
он фактически становится членом класса, с define
он будет перенесен в глобальную область.
Большинство из этих ответов неверны или только рассказывают половину истории.
Например:
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 WEAKNESS = 4+5+6;
Ответ 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 на самом деле не гарантирует этого.
BAR
и \foo\BAR
просто не совпадают. Я согласен, что это действительно сбивает с толку, но если вы также считаете, что такие вещи, как логика пространства имен, являются непротиворечивыми, и что ни const
ни define()
не похожи на макрос C ( #define
), то у PHP может быть некоторое оправдание.
Да, константы определены во время компиляции, и поскольку никическим состояниям нельзя назначить выражение, как 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()
.
const
в два раза быстрее, чемdefine
. О времени загрузки страницы и использовании памяти: см. Этот вопрос и эту статью ... Смотрите также кое-что о кеше кода операции здесь .