define () vs const

Dość proste pytanie: w PHP, kiedy używasz

define('FOO', 1);

A kiedy używasz

const FOO = 1;

Jakie są główne różnice między tymi dwoma?

Author: Skelly1983, 2010-03-15

10 answers

Od wersji PHP 5.3 istnieją dwa sposoby definiowania stałych : używając słowa kluczowego const lub używając define() funkcja:

const FOO = 'BAR';
define('FOO', 'BAR');

Zasadnicza różnica między tymi dwoma sposobami polega na tym, że const definiuje stałe w czasie kompilacji, podczas gdy define definiuje je w czasie wykonywania. Powoduje to większość wad const. Niektóre wady const to:

  • const nie można użyć do warunkowego definiowania stałych. Aby zdefiniować stałą globalną, to należy stosować w zakresie najbardziej oddalonym:

    if (...) {
        const FOO = 'BAR';    // invalid
    }
    // but
    if (...) {
        define('FOO', 'BAR'); // valid
    }
    

    Po co miałbyś to robić? Jedną z powszechnych aplikacji jest sprawdzenie, czy stała jest już zdefiniowana:

    if (!defined('FOO')) {
        define('FOO', 'BAR');
    }
    
  • const przyjmuje Skalar statyczny (liczba, łańcuch lub inna stała jak true, false, null, __FILE__), natomiast define() przyjmuje Dowolne wyrażenie. Od PHP 5.6 wyrażenia stałe są dozwolone również w const:

    const BIT_5 = 1 << 5;    // valid since PHP 5.6, invalid previously
    define('BIT_5', 1 << 5); // always valid
    
  • const przyjmuje zwykłą stałą nazwę, podczas gdy define() przyjmuje Dowolne wyrażenie jako nazwę. To pozwala robić takie rzeczy:

    for ($i = 0; $i < 32; ++$i) {
        define('BIT_' . $i, 1 << $i);
    }
    
  • consts są zawsze wrażliwe na wielkość liter, podczas gdy define() pozwala zdefiniować stałe niewrażliwe na wielkość liter, przekazując true jako trzeci argument:

    define('FOO', 'BAR', true);
    echo FOO; // BAR
    echo foo; // BAR
    
Więc to była zła strona rzeczy. Teraz spójrzmy na powód, dla którego osobiście zawsze używam const, chyba że wystąpi jedna z powyższych sytuacji: {]}
  • Po prostu czyta się ładniej. Jest konstrukcją języka zamiast funkcja, a także jest zgodna ze sposobem definiowania stałych w klasach.
  • const, będąc konstrukcją języka, można statycznie analizować za pomocą zautomatyzowanych narzędzi.
  • const definiuje stałą w bieżącej przestrzeni nazw, podczas gdy define() musi być przekazana pełna nazwa przestrzeni nazw:

    namespace A\B\C;
    // To define the constant A\B\C\FOO:
    const FOO = 'BAR';
    define('A\B\C\FOO', 'BAR');
    
  • Ponieważ PHP 5.6 const stałe mogą być również tablicami, podczas gdy define() nie obsługuje jeszcze tablic. Jednak tablice będą obsługiwane w obu przypadkach w 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
    

Wreszcie, zauważ, że const może być również używany w klasie lub interfejsie do zdefiniowania stałej klasy lub stałej interfejsu. define nie może być użyty w tym celu:

class Foo {
    const BAR = 2; // valid
}
// but
class Baz {
    define('QUX', 2); // invalid
}

Podsumowanie

Jeśli nie potrzebujesz jakiejkolwiek definicji warunkowej lub wyrazowej, użyj const s zamiast define()s - po prostu dla czytelności!

 928
Author: NikiC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-18 16:11:40

Do PHP 5.3, const nie może być używany w globalnym zasięgu. Możesz tego używać tylko z klasy. To powinno być używane, gdy chcesz ustawić jakąś stałą opcję lub ustawienie, które odnosi się do tej klasy. A może chcesz stworzyć jakiś enum.

define może być używany do tego samego celu, ale może być używany tylko w zakresie globalnym. Powinien być używany tylko dla ustawień globalnych, które wpływają na całą aplikację.

Przykładem dobrego const użycia jest uzyskanie pozbądź się magicznych liczb. Spójrz na stałe PDO. Jeśli chcesz określić typ pobierania, wpisz na przykład PDO::FETCH_ASSOC. Gdyby const nie był używany, skończyłbyś pisząc coś w stylu 35 (lub cokolwiek FETCH_ASSOC jest zdefiniowane jako). To nie ma sensu dla czytelnika.

Przykładem dobrego użycia define może być podanie głównej ścieżki aplikacji lub numeru wersji biblioteki.

 193
Author: ryeguy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-11 14:13:12

Wiem, że to już jest odpowiedź, ale żadna z obecnych odpowiedzi nie wspomina o przestrzeni nazw i o tym, jak wpływa ona na stałe i definiuje.

Począwszy od PHP 5.3, const i defines są podobne pod wieloma względami. Nadal jednak istnieją pewne istotne różnice:

  • Const nie może być zdefiniowany na podstawie wyrażenia. Nie działa, ale działa.
  • Nazwa przekazywana do {[5] } musi zawierać przestrzeń nazw, która ma być zdefiniowana w tym przestrzeń 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ść tablicy użytkownika będzie ['foo\\BAR' => 1, 'BAZ' => 2, 'foo\\BAZ' => 3].

=== Aktualizacja ===

Nadchodzący PHP 5.6 pozwoli na nieco większą elastyczność z const. Teraz będziesz mógł definiować const w kategoriach wyrażeń, pod warunkiem, że wyrażenia te składają się z innych const lub literałów. Oznacza to, że od 5.6 powinny obowiązywać następujące zasady:

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;

Nadal nie będziesz w stanie aby zdefiniować const w kategoriach zmiennych lub zwrotów funkcji, więc

const RND = mt_rand();
const CONSTVAR = $var;
/ Align = "left" /
 35
Author: GordonM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-16 11:28:14

Wierzę, że począwszy od PHP 5.3, możesz używać const poza klasami, jak pokazano 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;
?>
 22
Author: mattle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-30 01:16:29

define używam stałych globalnych.

const używam stałych klas.

Nie możesz define do zakresu klasy, A Z const możesz. Nie trzeba dodawać, że nie można używać const poza zakresem klasy

Również, z const, staje się członkiem klasy, z define, zostanie zepchnięty do globalnego zasięgu.

 16
Author: Jacob Relkin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-15 14:30:52

Odpowiedź Nikicia jest najlepsza, ale pozwól, że dodam nieoczywiste zastrzeżenie podczas używania przestrzeni nazw, abyś nie został przyłapany na nieoczekiwanym zachowaniu. Należy pamiętać, że defines są Zawsze w globalnej przestrzeni nazw, chyba że jawnie dodasz przestrzeń nazw jako część identyfikatora define. Nie jest w tym oczywiste, że identyfikator przestrzeni nazw przewyższa 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ła konstelacja niepotrzebnie mylące, ponieważ idea const w dziesiątkach innych języków jest taka sama, gdziekolwiek jesteś w kodzie, a PHP tak naprawdę tego nie gwarantuje.

 12
Author: slartibartfast,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-17 20:21:15

Większość z tych odpowiedzi jest błędna lub opowiada tylko połowę historii.

  1. możesz skalować swoje stałe za pomocą przestrzeni nazw.
  2. możesz użyć słowa kluczowego "const" poza definicjami klas. Jednak tak jak w klasy wartości przypisane za pomocą słowa kluczowego "const" muszą być wyrażenia stałe.

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 zmiennej użyj define() w ten sposób:

define('AWESOME', whatIsMyName()); // Valid
define('WEAKNESS', 4 + 5 + 6); // Valid
define('FOO', BAR . OF . SOAP); // Valid
 12
Author: AwesomeBobX64,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-07 09:49:19

Tak, const są definiowane w czasie kompilacji i jako że Stany nikic nie mogą być przypisane do wyrażenia, jak można zdefiniować (). Ale również const nie może być warunkowo zadeklarowany (z tego samego powodu). ie. Nie możesz tego zrobić:

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

Natomiast można by użyć define (). Tak naprawdę nie sprowadza się to do osobistych preferencji, istnieje poprawny i niewłaściwy sposób użycia obu.

Jako bok... Chciałbym zobaczyć jakąś klasę const, która może być przypisana do wyrażenia, coś w rodzaju define() to może być odizolowane od zajęć?

 5
Author: MrWhite,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-07 22:40:56

Aby dodać odpowiedź Nikicia. const może być używany 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ć z define().

 3
Author: Marcus Lind,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-05 07:57:55

Nikt Nic nie mówi o php-doc, ale dla mnie jest to również bardzo istotny argument za preferencją const:

/**
 * My foo-bar const
 * @var string
 */
const FOO = 'BAR';
 1
Author: Николай Лубышев,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-23 09:58:25