W PHP, kiedy używasz
define('FOO', 1);
i kiedy używasz
const FOO = 1;
?
Jakie są główne różnice między tymi dwoma?
W PHP, kiedy używasz
define('FOO', 1);
i kiedy używasz
const FOO = 1;
?
Jakie są główne różnice między tymi dwoma?
Odpowiedzi:
W PHP 5.3 istnieją dwa sposoby definiowania stałych : albo za pomocą const
słowa kluczowego, albo za pomocą define()
funkcji:
const FOO = 'BAR';
define('FOO', 'BAR');
Podstawowa różnica między tymi dwoma sposobami polega na tym, że const
definiuje stałe w czasie kompilacji, a define
definiuje je w czasie wykonywania. To powoduje większość const
wad. Niektóre wady const
:
const
nie można używać do warunkowego definiowania stałych. Aby zdefiniować stałą globalną, należy jej użyć w najbardziej zewnętrznym zakresie:
if (...) {
const FOO = 'BAR'; // Invalid
}
// but
if (...) {
define('FOO', 'BAR'); // Valid
}
Dlaczego i tak chcesz to zrobić? Jedną z typowych aplikacji jest sprawdzenie, czy stała jest już zdefiniowana:
if (!defined('FOO')) {
define('FOO', 'BAR');
}
const
Przyjmuje skalarne statycznego (liczba znaków lub innych stałej jak true
, false
, null
, __FILE__
), przy czym define()
bierze żadnej wypowiedzi. Ponieważ dozwolone są również wyrażenia stałe 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
przyjmuje zwykłą stałą nazwę, ale define()
akceptuje każde wyrażenie jako nazwę. Pozwala to robić takie rzeczy:
for ($i = 0; $i < 32; ++$i) {
define('BIT_' . $i, 1 << $i);
}
const
s zawsze rozróżniają małe i wielkie litery, podczas gdy define()
pozwala ci definiować stałe bez rozróżniania wielkości liter, przekazując true
jako trzeci argument (Uwaga: definiowanie stałych bez rozróżniania wielkości liter jest przestarzałe od PHP 7.3.0.):
define('FOO', 'BAR', true);
echo FOO; // BAR
echo foo; // BAR
To była zła strona. Spójrzmy teraz na powód, dla którego osobiście zawsze używam, const
chyba że wystąpi jedna z powyższych sytuacji:
const
po prostu ładniej czyta. Jest to konstrukcja języka zamiast funkcji, a także jest spójna z tym, jak definiujesz stałe w klasach.const
, będący konstrukcją językową, może być analizowany statycznie za pomocą zautomatyzowanych narzędzi.const
definiuje stałą w bieżącej przestrzeni nazw, natomiast define()
należy przekazać pełną nazwę przestrzeni nazw:
namespace A\B\C;
// To define the constant A\B\C\FOO:
const FOO = 'BAR';
define('A\B\C\FOO', 'BAR');
Ponieważ const
stałe PHP 5.6 mogą być również tablicami, a jednocześnie define()
nie obsługują tablic. Jednak tablice będą obsługiwane dla obu przypadków w 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
Na koniec zauważ, że const
można go również użyć w klasie lub interfejsie do zdefiniowania stałej klasy lub stałej interfejsu. define
nie można użyć do tego celu:
class Foo {
const BAR = 2; // Valid
}
// But
class Baz {
define('QUX', 2); // Invalid
}
Podsumowanie
O ile nie potrzebujesz żadnej definicji warunkowej lub wyrażeniowej, użyj const
s zamiast define()
s - po prostu ze względu na czytelność!
const
konstrukcją języka - patrz wiki.php.net/rfc/const_scalar_exprs
const
jest brak cudzysłowów, co oznacza, że jest sformatowany tak samo, jak jest używany w twoim IDE.
define('a', $_GET['param']);
, const b = a;
działa idealnie i otrzymuje wartość, gdy const c = $_GET['param'];
jest niepoprawna. Czy const
naprawdę jest czas kompilacji? Raczej nie sądzę ... (testowane na PHP 7.0.7)
Do PHP 5.3 const
nie można było używać go w zakresie globalnym. Możesz użyć tego tylko z klasy. Należy tego użyć, gdy chcesz ustawić jakąś stałą opcję lub ustawienie, które dotyczy tej klasy. A może chcesz stworzyć jakiś wyliczenie.
define
można użyć do tego samego celu, ale można go użyć tylko w zakresie globalnym. Należy go używać tylko do ustawień globalnych, które wpływają na całą aplikację.
Przykładem dobrego const
użycia jest pozbycie się magicznych liczb. Spójrz na stałe PDO . Gdy musisz określić typ pobierania, wpisz PDO::FETCH_ASSOC
na przykład. Gdyby consts nie były używane, skończyłbyś pisaniem czegoś takiego 35
(lub cokolwiek FETCH_ASSOC
zdefiniowanego jako). To nie ma sensu dla czytelnika.
Przykładem dobrego define
użycia może być określenie ścieżki katalogu głównego aplikacji lub numeru wersji biblioteki.
const
z przestrzeniami nazw.
Wiem, że już na nie odpowiedziano, ale żadna z obecnych odpowiedzi nie wspomina o przestrzeni nazw i jej wpływie na stałe i definicje.
Począwszy od PHP 5.3, consts i definicje są podobne pod wieloma względami. Wciąż jednak istnieją pewne ważne różnice:
const FOO = 4 * 3;
nie działa, ale define('CONST', 4 * 3);
działa. define
musi zawierać przestrzeń nazw, która ma zostać zdefiniowana w tej przestrzeni nazw.Poniższy kod powinien zilustrować różnice.
namespace foo
{
const BAR = 1;
define('BAZ', 2);
define(__NAMESPACE__ . '\\BAZ', 3);
}
namespace {
var_dump(get_defined_constants(true));
}
Zawartość pod-macierzy użytkownika będzie ['foo\\BAR' => 1, 'BAZ' => 2, 'foo\\BAZ' => 3]
.
=== AKTUALIZACJA ===
Nadchodzący PHP 5.6 pozwoli na nieco większą elastyczność const
. Będziesz teraz mógł definiować stałe w kategoriach wyrażeń, pod warunkiem, że wyrażenia te składają się z innych stałych lub literałów. Oznacza to, że następujące informacje powinny obowiązywać od 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;
Jednak nadal nie będziesz w stanie zdefiniować stałych w kategoriach zmiennych lub zwrotów funkcji, więc
const RND = mt_rand();
const CONSTVAR = $var;
nadal będzie niedostępny.
FORTY_TWO
jako 54?
Wierzę, że od PHP 5.3 możesz używać const
poza klasami, jak pokazano tutaj w drugim przykładzie:
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
Używam dla stałych globalnych.
const
Używam dla stałych klas.
Nie możesz define
wchodzić w zakres zajęć, a wraz z const
tobą możesz. Nie trzeba dodawać, że nie można używać const
poza zakresem klasy.
Ponadto, z const
, faktycznie staje się członkiem klasy, a z define
, zostanie przesunięty do zasięgu globalnego.
Odpowiedź NikiC jest najlepsza, ale pozwól mi dodać nieoczywiste zastrzeżenie podczas korzystania z przestrzeni nazw, abyś nie złapał się na nieoczekiwanym zachowaniu. Należy pamiętać, że definicje są zawsze w globalnej przestrzeni nazw, chyba że jawnie dodasz przestrzeń nazw jako część identyfikatora definicji. Nie jest w tym oczywiste, że identyfikator przestrzeni nazw przebija identyfikator globalny. Więc :
<?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);
}
?>
produkuje:
What kind of bar is a cheers bar?
What kind of bar is a wonka bar?
willy wonka
three cheers
Co dla mnie sprawia, że całe pojęcie const jest niepotrzebnie mylące, ponieważ idea const w kilkudziesięciu innych językach jest taka, że zawsze jest taka sama, gdziekolwiek jesteś w kodzie, a PHP tak naprawdę tego nie gwarantuje.
BAR
i \foo\BAR
to tylko nie te same stałe. Zgadzam się, że to naprawdę mylące, ale jeśli weźmiesz również pod uwagę, że logika przestrzeni nazw jest spójna w ten sposób, i że ani const
ani nie define()
jest jak makro C ( #define
), to PHP może mieć jakąś wymówkę.
Większość tych odpowiedzi jest błędna lub mówi tylko połowę historii.
Na przykład:
const AWESOME = 'Bob'; // Valid
Zły przykład:
const AWESOME = whatIsMyName(); // Invalid (Function call)
const WEAKNESS = 4+5+6; // Invalid (Arithmetic)
const FOO = BAR . OF . SOAP; // Invalid (Concatenation)
Aby utworzyć stałe zmiennych, użyj funkcji replace () w następujący sposób:
define('AWESOME', whatIsMyName()); // Valid
define('WEAKNESS', 4 + 5 + 6); // Valid
define('FOO', BAR . OF . SOAP); // Valid
Tak, const są definiowane w czasie kompilacji, a ponieważ stanom nikic nie można przypisać wyrażenia, tak jak można zdefiniować (). Ale również stałych nie można warunkowo zadeklarować (z tego samego powodu). to znaczy. Nie możesz tego zrobić:
if (/* some condition */) {
const WHIZZ = true; // CANNOT DO THIS!
}
Podczas gdy można to zrobić za pomocą definicji (). Tak więc tak naprawdę nie sprowadza się to do osobistych preferencji, istnieje poprawny i niewłaściwy sposób korzystania z obu.
Na marginesie ... Chciałbym zobaczyć jakąś klasę const, której można przypisać wyrażenie, rodzaj definicji (), którą można odizolować od klas?
Aby dodać odpowiedź NikiC. const
mogą być używane w ramach klas w następujący sposób:
class Foo {
const BAR = 1;
public function myMethod() {
return self::BAR;
}
}
Nie możesz tego zrobić za pomocą define()
.
Nikt nie mówi nic o php-doc, ale dla mnie jest to również bardzo znaczący argument za preferencją const
:
/**
* My foo-bar const
* @var string
*/
const FOO = 'BAR';
Dzięki funkcji definiowania stałej słowa kluczowego uzyskasz możliwość rozróżniania wielkości liter, ale ze słowem kluczowym const nie.
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
jest dwa razy szybsza niżdefine
. Informacje o czasie ładowania strony i zużyciu pamięci: zobacz to pytanie i ten artykuł ... Zobacz także coś o pamięci podręcznej opcode tutaj .