Web

Что лучше использовать define() или const?

В PHP, когда вы используете:

define('FOO', 1);

 или когда вы используете:

const FOO = 1;

 каковы основные различия между этими двумя вариантами?

 

Ответ 1

Начиная с версии PHP 5.3, существует два способа определения констант: либо с помощью ключевого слова const, либо с помощью функции define():

const FOO = 'BAR';

define('FOO', 'BAR');

 Фундаментальное различие между этими двумя способами заключается в том, что const определяет константы во время компиляции, в то время как define определяет их во время выполнения. Это является причиной большинства недостатков const. Некоторые недостатки const следующие:

  1. const нельзя использовать для условного определения констант. Чтобы определить глобальную константу, она должна быть использована в самой внешней области видимости:

if (...) {

     const FOO = 'BAR';    // Не допустимо

 }

 // но

 if (...) {

     define('FOO', 'BAR'); // Допустимо

 }

  1. Зачем вообще это нужно? Одно из распространенных применений проверка того, определена ли уже константа:

if (!defined('FOO')) {

     define('FOO', 'BAR');

 }

  1. const принимает статический скаляр (число, строку или другую константу типа true, false, null, __FILE__), тогда как define() принимает любое выражение. Начиная с PHP 5.6, константные выражения допускаются и в const:

const BIT_5 = 1 << 5;    // Действителен с версии PHP 5.6 и недействителен ранее

define('BIT_5', 1 << 5); // Всегда допустимо

  1. const принимает обычное имя константы, в то время как define() принимает любое выражение в качестве имени. Это позволяет делать такие вещи, как:

for ($i = 0; $i < 32; ++$i) {

     define('BIT_' . $i, 1 << $i);

}

  1. const всегда чувствительна к регистру, тогда как define() позволяет вам определять константы без учета регистра, передавая true в качестве третьего аргумента (примечание: определение констант без учета регистра устарело, начиная с PHP 7.3.0, и удалено в PHP 8.0.0):

define('FOO', 'BAR', true);

 echo FOO; // BAR

 echo foo; // BAR

 Итак, это была плохая сторона дела. Теперь давайте рассмотрим причину, по которой лично я всегда использую const, если только не возникает одна из описанных выше ситуаций:

  1. const просто читается приятнее. Это языковая конструкция вместо функции, а также соответствует тому, как вы определяете константы в классах.

  2. const, будучи языковой конструкцией, может быть статически проанализирована автоматизированными инструментами.

  3. const определяет константу в текущем пространстве имен, в то время как define() должно быть передано полное имя пространства имен:

namespace A\B\C;

 // Определить константу A\B\C\FOO:

 const FOO = 'BAR';

 define('A\B\C\FOO', 'BAR');

  1. Начиная с PHP 5.6, константы const также могут быть массивами, в то время как define() пока не поддерживает массивы. Однако в PHP 7 массивы будут поддерживаться в обоих случаях.

const FOO = [1, 2, 3];    // Допустимо в PHP 5.6

define('FOO', [1, 2, 3]); // Не допустимо в PHP 5.6, но стало доступно в PHP 7.0

 Наконец, обратите внимание, что const может также использоваться внутри класса или интерфейса для определения константы класса или константы интерфейса. define не может использоваться для этой цели:

class Foo {

    const BAR = 2; // Допустимо

}

// Но

class Baz {

    define('QUX', 2); // Не допустимо

}

 Резюме:

 Если вам не требуется какой-либо тип условного или специального определения, используйте const вместо define() — просто для удобства чтения!

 

Ответ 2

До версии PHP 5.3 const нельзя было использовать в глобальной области видимости. Его можно было использовать только внутри класса. Это следует использовать, когда вы хотите установить какую-то константную опцию или параметр, относящийся к данному классу. Или, может быть, вы хотите создать какое-то перечисление. define можно использовать для той же цели, но только в глобальной области видимости. Его следует использовать только для глобальных настроек, которые влияют на все приложение. Примером хорошего использования const является избавление от «магических» чисел. Взгляните на константы PDO. Когда вам нужно указать тип выборки, вы набираете, например, PDO::FETCH_ASSOC. Если бы константы не использовались, то в итоге вы бы набрали что-то вроде «35» (или любое другое значение FETCH_ASSOC). Это не имеет смысла для читателя. Примером хорошего использования define может быть указание корневого пути вашего приложения или номера версии библиотеки.

 

Ответ 3

Я знаю, что на этот вопрос уже отвечали, но ни в одном из текущих ответов нет упоминания о пространстве имен и о том, как оно влияет на константы и определения. Начиная с PHP 5.3, константы и определения в большинстве своем похожи. Тем не менее есть несколько важных различий:

  1. Константы не могут быть определены из выражения. const FOO = 4 * 3; не работает, но define('CONST', 4 * 3); работает.

  2. Имя, передаваемое в 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. Теперь вы сможете определять const в выражениях, при условии, что эти выражения состоят из других const или литералов. Это означает, что в версии 5.6 работают следующие выражения:

const FOOBAR = 'foo ' . 'bar';

const FORTY_TWO = 6 * 9; const ULTIMATE_ANSWER = 'The ultimate answer to life, the universe and everything is ' . FORTY_TWO;

 

Однако вы все равно не сможете определить const в терминах переменных или возвратов функций, поэтому:

const RND = mt_rand();

const CONSTVAR = $var;

все равно не будет работать.

 

Ответ 4

Предыдущий ответ является лучшим, но позвольте мне добавить неочевидную оговорку при использовании пространств имен, чтобы вы не столкнулись с неожиданным поведением. Необходимо помнить, что определяемые объекты всегда находятся в глобальном пространстве имен, если только вы явно не добавите пространство имен как часть идентификатора определяемого объекта. Что не очевидно, так это то, что идентификатор пространства имен имеет приоритет над глобальным идентификатором. Поэтому:

<?php

namespace foo {

  // Примечание: при ссылке в этом файле или пространстве имен const маскирует определяемую версию.

  // это может быть не то, что вы хотите/ожидаете

  const BAR = 'cheers';

  define('BAR', 'wonka');

  printf("What kind of bar is a %s bar?\n", BAR);

  // Чтобы добраться до определения в глобальном пространстве имен, необходимо явно сослаться на него  printf("What kind of bar is a %s bar?\n", \BAR);

}

 

namespace foo2 {

  // Но теперь в другом пространстве имен (например, по умолчанию) тот же синтаксис вызывает 

  // определенную версию!

  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 этого не гарантирует.

 

Ответ 5

Да, const определяются во время компиляции и не могут быть присвоены выражению, как это может сделать define(). Но также const не может быть условно объявлен (по той же причине). т. е. вы не можете сделать этого:

if (/* некоторое условие */) {

  const WHIZZ = true;  // не работает

}

 В то же время вы могли бы использовать define(). Таким образом, это не сводится к личным предпочтениям, есть правильный и неправильный способы использования обоих.

 

Ответ 6

При использовании константы define keyword вы получите возможность нечувствительности к регистру, а при использовании const keyword нет.

define("FOO", 1, true);

echo foo; //1

echo "<br/>";

echo FOO; //1

echo "<br/>";

 

class A {

  const FOO = 1;

}

 

echo A::FOO; //допустимо

echo "<br/>";

 

//но

 

class B {

  define FOO = 1; // синтаксическая ошибка, не определенный 'define'

}

echo B::FOO; // не допустимо

 

Схожие статьи

Web

Применение выражения eval в php

Web

Как заставить PHP перестать заменять символы «.» в массивах $_GET или $_POST

Web

Как я могу хранить и извлекать изображения из базы данных MySQL с помощью PHP

Что такое Reddit и как им пользоваться: описание сайта и регистрация
Web

Что такое Reddit и как им пользоваться: описание сайта и регистрация