У 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');
Оскільки const
константи PHP 5.6 також можуть бути масивами, поки 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
, наприклад. Якщо конкурси не використовувались, ви, в кінцевому підсумку, введете щось на зразок 35
(або все FETCH_ASSOC
, що визначено як). Це не має сенсу для читача.
Прикладом хорошого define
використання може бути вказівка кореневого шляху вашої програми або номер версії бібліотеки.
const
просторів імен.
Я знаю, що на це вже відповіли, але жодна з нинішніх відповідей не згадує проміжок часу і те, як це впливає на константи та визначає.
За станом на PHP 5.3, consts та визначає здебільшого подібні. Однак є деякі важливі відмінності:
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
. Тепер ви зможете визначити consts у виразах, за умови, що ці вирази складаються з інших 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;
Ви все одно не зможете визначити consts з точки зору змінних або функцій повернень, хоча, так
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)
Для створення змінних констант використовуйте def () так:
define('AWESOME', whatIsMyName()); // Valid
define('WEAKNESS', 4 + 5 + 6); // Valid
define('FOO', BAR . OF . SOAP); // Valid
Так, const визначається під час компіляції, і як nikic станам не можна призначити вираз, як може визначити (). Але також const's не можна умовно оголосити (з тієї ж причини). тобто. Ви не можете цього зробити:
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
const
два рази швидше, ніжdefine
. Про час завантаження сторінки та використання пам’яті: див. Це запитання та цю статтю ... Дивіться також щось про кеш опкоду тут .