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);
    }
    
  • consts всегда чувствительны к регистру, тогда как 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
}

резюме

Если вам не нужен какой-либо тип условного или экспрессивного определения, используйте consts вместо 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 на самом деле не гарантирует этого.


большинство из этих ответов неверны или говорят только половину истории.

  1. вы можете расширить свои константы, используя пространства имен.
  2. вы можете использовать ключевое слово "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';