В PHP, когда вы используете
define('FOO', 1);
и когда вы используете
const FOO = 1;
?
Каковы основные различия между этими двумя?
В 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 and 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
в качестве третьего аргумента (Примечание: определение нечувствительных к регистру констант не рекомендуется с PHP 7.3.0.):
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 and valid in PHP 7.0
Наконец, обратите внимание, что const
также можно использовать внутри класса или интерфейса для определения константы класса или константы интерфейса. define
не может быть использован для этой цели:
class Foo {
const BAR = 2; // Valid
}
// But
class Baz {
define('QUX', 2); // Invalid
}
Резюме
Если вам не нужен какой-либо тип условного или экспрессивного определения, используйте const
s вместо define()
s - просто для удобства чтения!
const
языковой конструкцией - см. Wiki.php.net/rfc/const_scalar_exprs
const
является отсутствие кавычек, что означает, что он отформатирован так же, как и в вашей IDE.
define('a', $_GET['param']);
, const b = a;
работает отлично и получает значение, пока const c = $_GET['param'];
недействительно. Действительно const
ли время компиляции? Я так не думаю ... (проверено на PHP 7.0.7)
До PHP 5.3 const
не могли использоваться в глобальном масштабе. Вы можете использовать это только внутри класса. Это следует использовать, когда вы хотите установить какую-то постоянную опцию или параметр, относящийся к этому классу. Или, может быть, вы хотите создать какое-то перечисление.
define
может использоваться для той же цели, но может использоваться только в глобальной области видимости. Его следует использовать только для глобальных настроек, которые влияют на все приложение.
Примером хорошего const
использования является избавление от магических чисел. Посмотрите на константы PDO . Когда вам нужно указать тип выборки, вы должны напечатать PDO::FETCH_ASSOC
, например. Если бы conts не использовались, вы бы в конечном итоге набрали что-то вроде 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]
.
=== ОБНОВЛЕНИЕ ===
Предстоящий 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;
все еще будет вне.
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
, это будет перемещено в глобальную область.
Ответ 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 может быть какое-то оправдание.
Большинство из этих ответов неверны или рассказывают только половину истории.
Например:
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 (), который можно выделить в классы?
Добавить ответ Никии. 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';
С помощью определения ключевого слова константы вы получите возможность учета регистра без учета регистра, а с помощью константного ключевого слова - нет.
define("FOO", 1, true);
echo foo; //1
echo "<br/>";
echo FOO; //1
echo "<br/>";
class A {
const FOO = 1;
}
echo A::FOO; //valid
echo "<br/>";
//but
class B {
define FOO = 1; //syntax error, unexpected 'define'
}
echo B::FOO; //invalid
const
в два раза быстрее, чемdefine
. О времени загрузки страницы и использовании памяти: см. Этот вопрос и эту статью ... Смотрите также кое-что о кеше кода операции здесь .