it-swarm.com.de

define () vs. const

Wann verwenden Sie in PHP?

define('FOO', 1);

und wann benutzt du

const FOO = 1;

?

Was sind die Hauptunterschiede zwischen diesen beiden?

634
danjarvis

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

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

Der grundlegende Unterschied zwischen diesen beiden Möglichkeiten besteht darin, dass const Konstanten zur Kompilierungszeit definiert, während define sie zur Laufzeit definiert. Dies verursacht die meisten Nachteile von const. Einige Nachteile von const sind:

  • const kann nicht zum bedingten Definieren von Konstanten verwendet werden. 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 würdest du das sowieso wollen? Eine häufige Anwendung besteht darin, zu überprüfen, ob die Konstante bereits definiert ist:

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

    const BIT_5 = 1 << 5;    // Valid since PHP 5.6 and invalid previously
    define('BIT_5', 1 << 5); // Always valid
    
  • const nimmt einen einfachen konstanten Namen an, während define() einen beliebigen Ausdruck als Namen akzeptiert. So können Sie Folgendes tun:

    for ($i = 0; $i < 32; ++$i) {
        define('BIT_' . $i, 1 << $i);
    }
    
  • consts unterscheidet immer zwischen Groß- und Kleinschreibung, während define() das Definieren von Konstanten ohne Berücksichtigung der Groß- und Kleinschreibung ermöglicht, indem true als drittes Argument übergeben wird:

    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 const verwende, es sei denn, eine der oben genannten Situationen tritt auf:

  • const liest sich einfach schöner. Es ist ein Sprachkonstrukt anstelle einer Funktion und entspricht auch der Definition von Konstanten in Klassen.
  • const, ein Sprachkonstrukt, kann durch automatisierte Werkzeuge statisch analysiert werden.
  • const definiert 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 const Konstanten auch Arrays sein können, unterstützt define() noch keine Arrays. Arrays werden jedoch in beiden Fällen in PHP 7 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
    

Beachten Sie schließlich, dass const auch innerhalb einer Klasse oder Schnittstelle verwendet werden kann, um eine Klassenkonstante oder eine Schnittstellenkonstante zu definieren. define kann nicht für diesen Zweck verwendet werden:

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

Zusammenfassung

Verwenden Sie consts anstelle von define()s, es sei denn, Sie benötigen eine bedingte oder expressionale Definition - einfach aus Gründen der Lesbarkeit!

1007
NikiC

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

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

Ein Beispiel für eine gute const Verwendung ist es, magische Zahlen loszuwerden. Schauen Sie sich PDOs Konstanten an. Wenn Sie einen Abruftyp angeben müssen, geben Sie beispielsweise PDO::FETCH_ASSOC ein. Wenn keine Konstanten verwendet würden, würden Sie am Ende so etwas wie 35 eingeben (oder wie auch immer FETCH_ASSOC definiert ist). Dies ergibt für den Leser keinen Sinn.

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

196
ryeguy

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

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

  • Consts können nicht aus einem Ausdruck definiert werden. const FOO = 4 * 3; funktioniert nicht, define('CONST', 4 * 3); jedoch.
  • Der an define übergebene Name muss 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 ist ['foo\\BAR' => 1, 'BAZ' => 2, 'foo\\BAZ' => 3].

=== UPDATE ===

Das kommende PHP 5.6 wird ein bisschen mehr Flexibilität mit const ermöglichen. Sie können nun Konstanten in Form von Ausdrücken definieren, sofern diese Ausdrücke aus anderen Konstanten oder Literalen bestehen. Dies bedeutet, dass ab 5.6 Folgendes gelten 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 werden aber immer noch nicht in der Lage sein, Konstanten in Form von Variablen oder Funktionsrückgaben zu definieren

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

wird noch raus sein.

37
GordonM

Ich glaube, dass Sie ab PHP 5.3 const auß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;
?>
22
mattle

define Ich verwende für globale Konstanten.

const Ich verwende für Klassenkonstanten.

Sie können define nicht in den Klassenbereich aufnehmen, und mit const können Sie. Natürlich können Sie const nicht außerhalb des Klassenbereichs verwenden.

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

21
Jacob Relkin

Die Antwort von NikiC ist die beste, aber lassen Sie mich eine nicht offensichtliche Einschränkung bei der Verwendung von Namespaces hinzufügen, damit Sie nicht von unerwartetem Verhalten überrascht werden. Beachten Sie, dass Definitionen im globalen Namespace immer sind, es sei denn, Sie fügen den Namespace explizit als Teil des Bezeichners define hinzu. Was dabei 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 const-Vorstellung unnötig verwirrend macht, da die Idee eines const in Dutzenden anderer Sprachen ist, dass es immer dasselbe ist, wo immer Sie sich in Ihrem Code befinden, und PHP garantiert das nicht wirklich.

15
slartibartfast

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" auch außerhalb von Klassendefinitionen verwenden. Die mit dem Schlüsselwort "const" zugewiesenen Werte müssen jedoch wie in Klassen 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, benutze define () wie folgt:

define('AWESOME', whatIsMyName()); // Valid
define('WEAKNESS', 4 + 5 + 6); // Valid
define('FOO', BAR . OF . SOAP); // Valid
12
AwesomeBobX64

Ja, const werden zur Kompilierungszeit definiert und da nikic states kein Ausdruck zugewiesen werden kann, wie define () es kann. Aber auch const's 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!
}

Wobei Sie mit einem define (). Es kommt also nicht wirklich auf die persönlichen Vorlieben an, es gibt einen richtigen und einen falschen Weg, beides zu benutzen.

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.

6
MrWhite

Um die Antwort von NikiC zu ergänzen. const kann in Klassen folgendermaßen verwendet werden:

class Foo {
    const BAR = 1;

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

Dies ist mit define() nicht möglich.

5
Marcus Lind

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';

Mit define keyword constant erhalten Sie die Funktionen von case
unempfindlich, aber mit dem Schlüsselwort const haben Sie es nicht getan.

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