define () против const

Довольно простой вопрос: в PHP, когда вы используете

define('FOO', 1);

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

const FOO = 1;

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

602

Решение

Начиная с 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
}

Резюме

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

+962

Другие решения

До PHP 5.3, const не может быть использован в глобальном масштабе. Вы можете использовать это только внутри класса. Это следует использовать, когда вы хотите установить какой-то постоянный параметр или параметр, относящийся к этому классу. Или, может быть, вы хотите создать какое-то перечисление.

define может использоваться для той же цели, но может использоваться только в глобальной области. Его следует использовать только для глобальных настроек, которые влияют на все приложение.

Пример хорошего const использование состоит в том, чтобы избавиться от магических чисел. Взгляни на Константы PDO. Когда вам нужно указать тип выборки, вы должны набрать PDO::FETCH_ASSOC, например. Если бы не использовались const, вы бы в итоге набрали что-то вроде 35 (или что угодно FETCH_ASSOC определяется как). Это не имеет смысла для читателя.

Пример хорошего define Использование может указывать корневой путь вашего приложения или номер версии библиотеки.

193

Я знаю, что на этот вопрос уже дан ответ, но ни один из текущих ответов не содержит упоминаний о пространстве имен и о том, как оно влияет на константы и определения.

Начиная с 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;

все еще будет вне.

35

Я считаю, что с 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;
?>
22

define я использую для глобальных констант.

const я использую для констант класса.

Ты не можешь define в класс, и с const вы можете.
Излишне говорить, что вы не можете использовать const вне области видимости

Кроме того, с const, он на самом деле становится членом класса, с define, он будет выдвинут в глобальную область.

18

Ответ 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 на самом деле не гарантирует этого.

13

Большинство из этих ответов неверны или рассказывают только половину истории.

  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
12

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

if (/* some condition */) {
const WHIZZ = true;  // CANNOT DO THIS!
}

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

В качестве отступления … Я хотел бы увидеть некоторый класс const, которому можно присвоить выражение, своего рода define (), который можно выделить в классы?

5
По вопросам рекламы [email protected]