Довольно простой вопрос: в 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
будучи языковой конструкцией, может быть статически проанализирован с помощью автоматизированного инструментария.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
}
Резюме
Если вам не нужен какой-либо тип условного или экспрессивного определения, используйте const
с вместо define()
с — просто ради читабельности!
До PHP 5.3, const
не может быть использован в глобальном масштабе. Вы можете использовать это только внутри класса. Это следует использовать, когда вы хотите установить какой-то постоянный параметр или параметр, относящийся к этому классу. Или, может быть, вы хотите создать какое-то перечисление.
define
может использоваться для той же цели, но может использоваться только в глобальной области. Его следует использовать только для глобальных настроек, которые влияют на все приложение.
Пример хорошего const
использование состоит в том, чтобы избавиться от магических чисел. Взгляни на Константы PDO. Когда вам нужно указать тип выборки, вы должны набрать PDO::FETCH_ASSOC
, например. Если бы не использовались const, вы бы в итоге набрали что-то вроде 35
(или что угодно FETCH_ASSOC
определяется как). Это не имеет смысла для читателя.
Пример хорошего define
Использование может указывать корневой путь вашего приложения или номер версии библиотеки.
Я знаю, что на этот вопрос уже дан ответ, но ни один из текущих ответов не содержит упоминаний о пространстве имен и о том, как оно влияет на константы и определения.
Начиная с 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]
,
=== ОБНОВЛЕНИЕ ===
Предстоящий 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 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
я использую для глобальных констант.
const
я использую для констант класса.
Ты не можешь 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 (), который можно выделить в классы?