define () vs const
очень простой вопрос: в PHP, когда вы используете
define('FOO', 1);
и когда вы используете
const FOO = 1;
каковы основные различия между этими двумя?
10 ответов
начиная с 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
s вместо define()
s - просто ради читабельности!
до PHP 5.3,const
не удалось использовать в глобальной области. Вы можете использовать это только из класса. Это должно использоваться, когда вы хотите установить какой-то постоянный параметр или параметр, относящийся к этому классу. Или, может быть, вы хотите создать какое-то перечисление.
define
может использоваться для той же цели, но может использоваться только в глобальной области. Он должен использоваться только для глобальных параметров, которые влияют на все приложение.
пример хороший const
использование, чтобы избавиться от магических чисел. Взгляните на константы PDO. Когда вам нужно указать тип выборки, вы должны ввести PDO::FETCH_ASSOC
, например. Если бы запоры не использовались, вы бы в конечном итоге набрали что-то вроде 35
(или FETCH_ASSOC
определяется как). Это не имеет смысла для читателя.
пример define
использование, возможно, указывает корневой путь вашего приложения или номер версии библиотеки.
Я знаю, что это уже ответ, но ни один из текущих ответов не упоминает пространство имен и как оно влияет на константы и определяет.
начиная с PHP 5.3, const и defines аналогичны в большинстве случаев. Однако есть еще некоторые важные отличия:
- 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]
.
= = = UPDATE ===
предстоящий PHP 5.6 позволит немного больше гибкости с const
. Теперь вы сможете определить const в терминах выражений, при условии, что эти выражения состоят из других 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;
все еще будет.
Я считаю, что с 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
, Он будет выдвинут на глобальный уровень.
ответ Никича-лучший, но позвольте мне добавить неочевидное предостережение при использовании пространств имен, чтобы вас не поймали с неожиданным поведением. Дело в том, чтобы помнить, что определяетвсегда в глобальном пространстве имен, если вы явно не добавляете пространство имен как часть идентификатора define. Что не очевидно, так это то, что идентификатор пространства имен превосходит глобальный идентификатор. Итак:
<?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" вне определений классов. Однако, как и в классы значения, назначенные с помощью ключевого слова "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 определяются во время компиляции, и поскольку состояния nikic не могут быть назначены выражению, как define (). Но и const не может быть условно объявлен (по той же причине). то есть. Вы не можете этого сделать:
if (/* some condition */) {
const WHIZZ = true; // CANNOT DO THIS!
}
тогда как вы могли бы с define (). Таким образом, это не сводится к личным предпочтениям, есть правильный и неправильный способ использовать оба.
в сторону... Я хотел бы видеть какой-то класс const, которому можно назначить выражение, своего рода define (), который можно изолировать от классов?
чтобы добавить ответ Никича. 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';