В 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
всегда чувствительны к регистру, тогда как 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 and 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
, например. Если consts не были использованы, вы в конечном итоге набрали бы что-то вроде 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]
.
=== 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
я использую для глобальных констант.
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
Да, константы определены во время компиляции, и поскольку никическим состояниям нельзя назначить выражение, как 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';
С помощью определения ключевого слова константа вы получите все возможности
нечувствителен, но с ключевым словом const вы этого не сделали.
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