У 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 validconstприймає звичайне постійне ім'я, тоді як define()приймає будь-який вираз як ім'я. Це дозволяє робити такі дії:
for ($i = 0; $i < 32; ++$i) {
define('BIT_' . $i, 1 << $i);
}consts завжди чутливі до регістру, тоді як 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
}
Підсумок
Якщо вам не потрібен будь-який тип умовного або виразного визначення, використовуйте consts замість 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. Про час завантаження сторінки та використання пам’яті: див. Це запитання та цю статтю ... Дивіться також щось про кеш опкоду тут .