define () vs. const

658

Wann verwenden Sie in PHP?

define('FOO', 1);

und wann benutzt du

const FOO = 1;

?

Was sind die Hauptunterschiede zwischen diesen beiden?

Danjarvis
quelle
4
Informationen zur Leistung (Zeitverschwendung bei der Mikrooptimierung wie ich) finden Sie in dieser Antwort : Sie constist zweimal schneller als define. Informationen zum Laden der Seite und zur Speichernutzung: Siehe diese Frage und diesen Artikel ... Weitere Informationen zum Opcode-Cache finden Sie hier .
Peter Krauss
2
Schauen Sie sich nicht nur die aktuell akzeptierte Antwort an, sondern werfen Sie einen Blick auf stackoverflow.com/a/3193704/1412157, da dies die akzeptierte Antwort sein sollte
LucaM
1
Ich habe gerade die Benachrichtigung für Ihren Kommentar gesehen. Ich habe die akzeptierte Antwort aktualisiert.
Danjarvis

Antworten:

1037

Ab PHP 5.3 gibt es zwei Möglichkeiten , Konstanten zu definieren : Entweder mit dem constSchlüsselwort oder mit der define()Funktion:

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

Der grundlegende Unterschied zwischen diesen beiden Methoden besteht darin, dass constKonstanten zur Kompilierungszeit definiert werden, während definesie zur Laufzeit definiert werden. Dies führt zu den meisten constNachteilen. Einige Nachteile von constsind:

  • constkann nicht verwendet werden, um Konstanten bedingt zu definieren. Um eine globale Konstante zu definieren, muss sie im äußersten Bereich verwendet werden:

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

    Warum willst du das überhaupt tun? Eine häufige Anwendung besteht darin, zu überprüfen, ob die Konstante bereits definiert ist:

    if (!defined('FOO')) {
        define('FOO', 'BAR');
    }
  • constnimmt einen statischen skalar (Zahl, eine Zeichenfolge oder eine andere Konstante wie true, false, null, __FILE__), während define()nimmt jeden Ausdruck. Seit PHP 5.6 sind auch konstante Ausdrücke zulässig const:

    const BIT_5 = 1 << 5;    // Valid since PHP 5.6 and invalid previously
    define('BIT_5', 1 << 5); // Always valid
  • constnimmt einen einfachen konstanten Namen an, während define()jeder Ausdruck als Name akzeptiert wird. Dies ermöglicht Folgendes:

    for ($i = 0; $i < 32; ++$i) {
        define('BIT_' . $i, 1 << $i);
    }
  • consts unterscheiden immer zwischen Groß- und Kleinschreibung, während define()Sie Konstanten ohne trueBerücksichtigung der Groß- und Kleinschreibung definieren können, indem Sie als drittes Argument übergeben (Hinweis: Das Definieren von Konstanten ohne Berücksichtigung der Groß- und Kleinschreibung ist ab PHP 7.3.0 veraltet.):

    define('FOO', 'BAR', true);
    echo FOO; // BAR
    echo foo; // BAR

Das war also die schlechte Seite der Dinge. Schauen wir uns nun den Grund an, warum ich persönlich immer benutze, es constsei denn, eine der oben genannten Situationen tritt auf:

  • constliest einfach schöner. Es ist ein Sprachkonstrukt anstelle einer Funktion und stimmt auch mit der Definition von Konstanten in Klassen überein.
  • constAls Sprachkonstrukt kann es durch automatisierte Werkzeuge statisch analysiert werden.
  • constdefiniert eine Konstante im aktuellen Namespace, während define()der vollständige Namespace-Name übergeben werden muss:

    namespace A\B\C;
    // To define the constant A\B\C\FOO:
    const FOO = 'BAR';
    define('A\B\C\FOO', 'BAR');
  • Da PHP 5.6- constKonstanten auch Arrays sein können, werden Arrays define()noch nicht unterstützt. In PHP 7 werden jedoch Arrays für beide Fälle unterstützt.

    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

Schließlich ist zu beachten , dass constauch innerhalb einer Klasse oder Schnittstelle verwendet werden kann , eine definieren Klasse konstant oder Schnittstelle konstant. definekann nicht für diesen Zweck verwendet werden:

class Foo {
    const BAR = 2; // Valid
}
// But
class Baz {
    define('QUX', 2); // Invalid
}

Zusammenfassung

Wenn Sie keine bedingte oder expressive Definition benötigen, verwenden Sie consts anstelle von define()s - einfach aus Gründen der Lesbarkeit!

NikiC
quelle
1
Wie ich mit PHP 5.6 weiß, haben Sie die Möglichkeit, einfache skalare Ausdrücke auch mit dem constSprachkonstrukt zu verwenden - siehe wiki.php.net/rfc/const_scalar_exprs
mabe.berlin
6
Ein weiterer Vorteil der Verwendung constist das Fehlen von Anführungszeichen. Dies bedeutet, dass die Formatierung dort erfolgt, wo sie in Ihrer IDE verwendet wird.
Rybo111
3
Dies sollte in den PHP-Dokumenten enthalten sein. Es ist die beste Erklärung, die ich gesehen habe, insbesondere der Teil, den die meisten Leute vergessen (Kompilieren vs. Laufzeit).
James
4
define('a', $_GET['param']);, const b = a;funktioniert einwandfrei und erhält den Wert, solange er const c = $_GET['param'];ungültig ist. Ist constwirklich Kompilierzeit? Ich glaube kaum ... (getestet auf PHP 7.0.7)
mcserep
1
wiki.php.net/rfc/case_insensitive_constant_deprecationIn PHP 8.0: Entfernen Sie die Möglichkeit , Groß- und Kleinschreibung Konstanten deklarieren. “ für alle anderen hier in die Zukunft in Bezug auf Groß- und Kleinschreibung zu wagen
Scuzzy
196

Bis PHP 5.3 constkonnte nicht im globalen Bereich verwendet werden. Sie können dies nur innerhalb einer Klasse verwenden. Dies sollte verwendet werden, wenn Sie eine konstante Option oder Einstellung für diese Klasse festlegen möchten. Oder vielleicht möchten Sie eine Art Aufzählung erstellen.

definekann für den gleichen Zweck verwendet werden, kann jedoch nur im globalen Bereich verwendet werden. Es sollte nur für globale Einstellungen verwendet werden, die sich auf die gesamte Anwendung auswirken.

Ein Beispiel für eine gute constVerwendung ist das Entfernen magischer Zahlen. Schauen Sie sich die Konstanten der gU an . Wenn Sie einen Abruftyp angeben müssen, geben Sie PDO::FETCH_ASSOCbeispielsweise ein. Wenn consts nicht verwendet würden, würden Sie am Ende etwas wie 35(oder was auch immer FETCH_ASSOCals definiert ist) eingeben . Dies macht für den Leser keinen Sinn.

Ein Beispiel für eine gute defineVerwendung ist möglicherweise die Angabe des Stammpfads Ihrer Anwendung oder der Versionsnummer einer Bibliothek.

Ryeguy
quelle
12
Es könnte erwähnenswert sein, die Verwendung constmit Namespaces zu erwähnen .
salathe
31
Es sollte auch beachtet werden, dass PHP5.3 const im globalen Bereich sehr häufig verwenden kann.
Gordon
5.2 kann auch. Das Schöne an consts vs. defined ist, dass Sie ihnen den Klassennamen voranstellen müssen. Wenn Sie sie verwenden, wird der Code lesbarer und schöner. Und das ist ein Bonus für mich.
Lucifurious
1
@ryeguy aber was ist nach PHP 5.3, wo const global wie define verwendet werden kann?
Andho
1
@andho, kreide einen anderen zum PHP-Tanz von One-Step-Forward, One-Step-Backward, Dance von "Verbesserungen". Er. :)
Prof. Falken Vertrag verletzt
37

Ich weiß, dass dies bereits beantwortet wurde, aber in keiner der aktuellen Antworten wird der Namespace und die Auswirkungen auf Konstanten und Definitionen erwähnt.

Ab PHP 5.3 sind Konstanten und Definitionen in den meisten Punkten ähnlich. Es gibt jedoch noch einige wichtige Unterschiede:

  • Konstanten können nicht aus einem Ausdruck definiert werden. const FOO = 4 * 3;funktioniert nicht, aber define('CONST', 4 * 3);funktioniert.
  • Der übergebene Name definemuss den Namespace enthalten, der in diesem Namespace definiert werden soll.

Der folgende Code sollte die Unterschiede veranschaulichen.

namespace foo 
{
    const BAR = 1;
    define('BAZ', 2);
    define(__NAMESPACE__ . '\\BAZ', 3);
}

namespace {
    var_dump(get_defined_constants(true));
}

Der Inhalt des Benutzer-Subarrays wird sein ['foo\\BAR' => 1, 'BAZ' => 2, 'foo\\BAZ' => 3].

=== UPDATE ===

Das kommende PHP 5.6 wird etwas mehr Flexibilität mit ermöglichen const. Sie können nun Konstanten als Ausdrücke definieren, vorausgesetzt, diese Ausdrücke bestehen aus anderen Konstanten oder Literalen. Dies bedeutet, dass ab 5.6 Folgendes gültig sein sollte:

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;

Sie können jedoch immer noch keine Konstanten in Bezug auf Variablen oder Funktionsrückgaben definieren

const RND = mt_rand();
const CONSTVAR = $var;

wird noch raus sein.

GordonM
quelle
8
Ich konnte nicht widerstehen zu fragen: Haben Sie bewusst FORTY_TWOals 54 definiert ?
Punchlinern
9
"Sechs mal neun? Zweiundvierzig? Ich habe immer gesagt, dass mit dem Universum etwas grundlegend nicht stimmt." Schauen Sie sich die Werke von Douglas Adams an, wenn Sie eine vollständige Erklärung benötigen.
GordonM
2
Oh. Mir war bewusst, dass 42 die Antwort auf das Leben, das Universum und alles ist, aber ich hatte die Sechs um neun Teile verpasst. Danke für die Erklärung!
Punchlinern
22

Ich glaube, dass Sie ab PHP 5.3 auch constaußerhalb von Klassen verwenden können, wie hier im zweiten Beispiel gezeigt:

http://www.php.net/manual/en/language.constants.syntax.php

<?php
// Works as of PHP 5.3.0
const CONSTANT = 'Hello World';

echo CONSTANT;
?>
Mattle
quelle
20

define Ich benutze für globale Konstanten.

const Ich benutze für Klassenkonstanten.

Sie können nicht definein den Klassenbereich und mit constIhnen können. Es ist unnötig zu erwähnen, dass Sie keinen constexternen Klassenbereich verwenden können.

Außerdem wird constes tatsächlich ein Mitglied der Klasse, und mit definewird es in den globalen Bereich verschoben.

Jacob Relkin
quelle
8
Wie in anderen Antworten erwähnt, kann const außerhalb von Klassen in PHP 5.3+
MrWhite
Nur das Schlüsselwort const kann verwendet werden, um eine Konstante mit Namespace zu erstellen, nicht nur Klassen
Alireza Rahmani Khalili
16

Die Antwort von NikiC ist die beste, aber lassen Sie mich eine nicht offensichtliche Einschränkung hinzufügen, wenn Sie Namespaces verwenden, damit Sie nicht mit unerwartetem Verhalten erwischt werden. Beachten Sie, dass sich Definitionen immer im globalen Namespace befinden, es sei denn, Sie fügen den Namespace explizit als Teil des Definitionsbezeichners hinzu. Was daran nicht offensichtlich ist, ist, dass der Namespace-Bezeichner den globalen Bezeichner übertrifft. Damit :

<?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);  
}
?>

produziert:

What kind of bar is a cheers bar? 
What kind of bar is a wonka bar?
willy wonka 
three cheers

Was für mich die ganze Konstanten-Vorstellung unnötig verwirrend macht, da die Idee einer Konstante in Dutzenden anderer Sprachen ist, dass sie immer gleich ist, wo immer Sie sich in Ihrem Code befinden, und PHP garantiert das nicht wirklich.

slartibartfast
quelle
1
Ja, aber BARund \foo\BARsind einfach nicht die gleichen Konstanten. Ich bin damit einverstanden, dass es wirklich verwirrend ist, aber wenn Sie auch Dinge wie die Namespace-Logik auf diese Weise als konsistent betrachten, und das weder constnochdefine() wie ein C- Makro ( #define), dann kann PHP eine Entschuldigung haben.
Gr.
1
Der Begriff const ist genau so, wie er sich verhalten sollte - Sie befinden sich in einem Namespace! Sie möchten es ohne den Namespace-Bezeichner und erstellen es dann außerhalb des Namespace. Dadurch wird es auch mit der in einer Klasse definierten Konstante konsistent, selbst wenn eine andere Syntax verwendet wird. Ja, define ist auch auf andere Weise konsistent.
Gerard ONeill
12

Die meisten dieser Antworten sind falsch oder erzählen nur die halbe Geschichte.

  1. Sie können Ihre Konstanten mithilfe von Namespaces erweitern.
  2. Sie können das Schlüsselwort "const" außerhalb von Klassendefinitionen verwenden. Genau wie in Klassen müssen die mit dem Schlüsselwort "const" zugewiesenen Werte jedoch konstante Ausdrücke sein.

Zum Beispiel:

const AWESOME = 'Bob'; // Valid

Schlechtes Beispiel:

const AWESOME = whatIsMyName(); // Invalid (Function call)
const WEAKNESS = 4+5+6; // Invalid (Arithmetic) 
const FOO = BAR . OF . SOAP; // Invalid (Concatenation)

Um variable Konstanten zu erstellen, verwenden Sie define () wie folgt:

define('AWESOME', whatIsMyName()); // Valid
define('WEAKNESS', 4 + 5 + 6); // Valid
define('FOO', BAR . OF . SOAP); // Valid
AwesomeBobX64
quelle
1
PHP> = 5.6 Einige Änderungen wurden im Zend Engine Compiler vorgenommen und const wird jetzt auf andere Weise behandelt.
Ankit Vishwakarma
6

Ja, const werden zur Kompilierungszeit definiert und da Nikic-Zuständen kein Ausdruck zugewiesen werden kann, wie dies bei define () der Fall ist. Aber auch consts können nicht bedingt deklariert werden (aus dem gleichen Grund). dh. Du kannst das nicht machen:

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

Während Sie mit einem define () könnten. Es kommt also nicht wirklich auf die persönlichen Vorlieben an, es gibt einen richtigen und einen falschen Weg, beide zu verwenden.

Nebenbei ... Ich würde gerne eine Art Klassenkonstante sehen, der ein Ausdruck zugewiesen werden kann, eine Art define (), die für Klassen isoliert werden kann.

Herr weiß
quelle
5

Um die Antwort von NikiC hinzuzufügen. constkann innerhalb von Klassen auf folgende Weise verwendet werden:

class Foo {
    const BAR = 1;

    public function myMethod() {
        return self::BAR;
    }
}

Sie können dies nicht mit tun define().

Marcus Lind
quelle
4

Niemand sagt etwas über PHP-Doc, aber für mich ist das auch ein sehr wichtiges Argument für die Präferenz von const:

/**
 * My foo-bar const
 * @var string
 */
const FOO = 'BAR';
Николай Лубышев
quelle
0

Mit der Definition der Schlüsselwortkonstante erhalten Sie die Möglichkeit, die Groß- und Kleinschreibung nicht zu berücksichtigen, mit dem Schlüsselwort const jedoch nicht.

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
GaziAnis
quelle