In PHP, quando usi
define('FOO', 1);
e quando lo usi
const FOO = 1;
?
Quali sono le principali differenze tra questi due?
In PHP, quando usi
define('FOO', 1);
e quando lo usi
const FOO = 1;
?
Quali sono le principali differenze tra questi due?
Risposte:
A partire da PHP 5.3 ci sono due modi per definire le costanti : usare la const
parola chiave o usare la define()
funzione:
const FOO = 'BAR';
define('FOO', 'BAR');
La differenza fondamentale tra questi due modi è che const
definisce le costanti in fase di compilazione, mentre le define
definisce in fase di esecuzione. Ciò causa la maggior parte const
degli svantaggi. Alcuni svantaggi di const
sono:
const
non può essere utilizzato per definire in modo condizionale le costanti. Per definire una costante globale, deve essere utilizzata nell'ambito più esterno:
if (...) {
const FOO = 'BAR'; // Invalid
}
// but
if (...) {
define('FOO', 'BAR'); // Valid
}
Perché dovresti farlo comunque? Un'applicazione comune è verificare se la costante è già definita:
if (!defined('FOO')) {
define('FOO', 'BAR');
}
const
accetta uno scalare statico (numero, una stringa o un altro costante come true
, false
, null
, __FILE__
), che define()
prende qualsiasi espressione. Poiché anche in PHP 5.6 sono consentite espressioni costanti const
:
const BIT_5 = 1 << 5; // Valid since PHP 5.6 and invalid previously
define('BIT_5', 1 << 5); // Always valid
const
prende un semplice nome costante, mentre define()
accetta qualsiasi espressione come nome. Ciò consente di fare cose del genere:
for ($i = 0; $i < 32; ++$i) {
define('BIT_' . $i, 1 << $i);
}
const
gli s sono sempre sensibili al maiuscolo / minuscolo, mentre define()
consente di definire costanti senza distinzione tra maiuscole e minuscole passando true
come terzo argomento (Nota: la definizione di costanti senza distinzione tra maiuscole e minuscole è obsoleta a partire da PHP 7.3.0.):
define('FOO', 'BAR', true);
echo FOO; // BAR
echo foo; // BAR
Quindi, quello era il lato negativo delle cose. Ora diamo un'occhiata al motivo per cui uso sempre personalmente a const
meno che non si verifichi una delle situazioni sopra:
const
legge semplicemente meglio. È un costrutto di linguaggio anziché una funzione ed è anche coerente con il modo in cui si definiscono le costanti nelle classi.const
, essendo un costrutto linguistico, può essere analizzato staticamente con strumenti automatizzati.const
definisce una costante nello spazio dei nomi corrente, mentre define()
deve essere passato il nome completo dello spazio dei nomi:
namespace A\B\C;
// To define the constant A\B\C\FOO:
const FOO = 'BAR';
define('A\B\C\FOO', 'BAR');
Poiché le const
costanti di PHP 5.6 possono anche essere array, mentre define()
non supporta ancora array. Tuttavia, le matrici saranno supportate per entrambi i casi in 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
Infine, si noti che const
può essere utilizzato anche all'interno di una classe o interfaccia per definire una costante di classe o costante di interfaccia. define
non può essere utilizzato per questo scopo:
class Foo {
const BAR = 2; // Valid
}
// But
class Baz {
define('QUX', 2); // Invalid
}
Sommario
A meno che tu non abbia bisogno di qualsiasi tipo di definizione condizionale o espressiva, usa const
s invece di define()
s - semplicemente per motivi di leggibilità!
const
costrutto del linguaggio - vedi wiki.php.net/rfc/const_scalar_exprs
const
è la mancanza di virgolette, il che significa che è formattato allo stesso modo in cui viene utilizzato nel tuo IDE.
define('a', $_GET['param']);
, const b = a;
funziona perfettamente e ottiene il valore mentre const c = $_GET['param'];
non è valido. È const
davvero tempo di compilazione? Non credo proprio ... (testato su PHP 7.0.7)
Fino a PHP 5.3, const
non poteva essere utilizzato nell'ambito globale. Puoi usarlo solo all'interno di una classe. Questo dovrebbe essere usato quando si desidera impostare una sorta di opzione costante o impostazione relativa a quella classe. O forse vuoi creare una sorta di enum.
define
può essere utilizzato per lo stesso scopo, ma può essere utilizzato solo nell'ambito globale. Dovrebbe essere utilizzato solo per le impostazioni globali che interessano l'intera applicazione.
Un esempio di buon const
uso è sbarazzarsi dei numeri magici. Dai un'occhiata alle costanti DOP . Quando è necessario specificare un tipo di recupero, digitare PDO::FETCH_ASSOC
, ad esempio. Se non si usassero i consessi, si finirebbe per digitare qualcosa del genere 35
(o qualunque cosa FETCH_ASSOC
sia definita come). Questo non ha senso per il lettore.
Un esempio di buon define
utilizzo è forse specificare il percorso radice dell'applicazione o il numero di versione di una libreria.
const
con namespace.
So che questa è già una risposta, ma nessuna delle risposte attuali menziona la spaziatura dei nomi e come influenza le costanti e le definizioni.
A partire da PHP 5.3, i consessi e le definizioni sono simili per la maggior parte degli aspetti. Vi sono tuttavia alcune importanti differenze:
const FOO = 4 * 3;
non funziona, ma define('CONST', 4 * 3);
funziona. define
deve includere lo spazio dei nomi da definire all'interno di quello spazio dei nomi.Il codice seguente dovrebbe illustrare le differenze.
namespace foo
{
const BAR = 1;
define('BAZ', 2);
define(__NAMESPACE__ . '\\BAZ', 3);
}
namespace {
var_dump(get_defined_constants(true));
}
Sarà il contenuto dell'array secondario dell'utente ['foo\\BAR' => 1, 'BAZ' => 2, 'foo\\BAZ' => 3]
.
=== AGGIORNAMENTO ===
Il prossimo PHP 5.6 consentirà un po 'più di flessibilità con const
. Ora sarai in grado di definire i consessi in termini di espressioni, a condizione che quelle espressioni siano costituite da altri consensi o letterali. Ciò significa che quanto segue dovrebbe essere valido dal 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;
Tuttavia, non sarai ancora in grado di definire i costi in termini di variabili o ritorni di funzioni
const RND = mt_rand();
const CONSTVAR = $var;
sarà ancora fuori.
FORTY_TWO
come 54?
Credo che a partire da PHP 5.3, puoi usare const
al di fuori delle classi, come mostrato qui nel secondo esempio:
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
Uso per le costanti globali.
const
Uso per le costanti di classe.
Non puoi define
rientrare nell'ambito della classe, e con const
te puoi. Inutile dire che non è possibile utilizzare un const
ambito di classe esterna.
Inoltre, con const
, diventa effettivamente un membro della classe e con define
, verrà spinto a livello globale.
La risposta di NikiC è la migliore, ma lasciami aggiungere un avvertimento non ovvio quando usi gli spazi dei nomi in modo da non rimanere sorpreso da comportamenti inaspettati. La cosa da ricordare è che le definizioni sono sempre nello spazio dei nomi globale a meno che non si aggiunga esplicitamente lo spazio dei nomi come parte dell'identificatore di definizione. Ciò che non è ovvio al riguardo è che l'identificatore con spaziatura dei nomi supera l'identificatore globale. Così :
<?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);
}
?>
produce:
What kind of bar is a cheers bar?
What kind of bar is a wonka bar?
willy wonka
three cheers
Il che per me rende l'intera nozione inutilmente confusa poiché l'idea di una const in dozzine di altre lingue è che è sempre la stessa ovunque tu sia nel tuo codice, e PHP non lo garantisce davvero.
BAR
e \foo\BAR
sono solo , non le stesse costanti. Sono d'accordo che è davvero confuso, ma se consideri che cose come la logica dello spazio dei nomi siano coerenti in questo modo, e che né const
né define()
è né come una macro C ( #define
), allora PHP può avere qualche scusa.
Molte di queste risposte sono sbagliate o raccontano solo metà della storia.
Per esempio:
const AWESOME = 'Bob'; // Valid
Cattivo esempio:
const AWESOME = whatIsMyName(); // Invalid (Function call)
const WEAKNESS = 4+5+6; // Invalid (Arithmetic)
const FOO = BAR . OF . SOAP; // Invalid (Concatenation)
Per creare costanti di variabili usa define () in questo modo:
define('AWESOME', whatIsMyName()); // Valid
define('WEAKNESS', 4 + 5 + 6); // Valid
define('FOO', BAR . OF . SOAP); // Valid
Sì, const è definito in fase di compilazione e poiché agli stati nikic non è possibile assegnare un'espressione, come può definire (). Ma anche le const non possono essere dichiarate condizionatamente (per lo stesso motivo). vale a dire. Non puoi farlo:
if (/* some condition */) {
const WHIZZ = true; // CANNOT DO THIS!
}
Considerando che potresti con un define (). Quindi, non si riduce davvero alle preferenze personali, c'è un modo corretto e un modo sbagliato di usare entrambi.
A parte questo ... Vorrei vedere un tipo di const di classe a cui può essere assegnata un'espressione, una sorta di define () che può essere isolata alle classi?
Per aggiungere la risposta di NikiC. const
può essere utilizzato all'interno delle classi nel modo seguente:
class Foo {
const BAR = 1;
public function myMethod() {
return self::BAR;
}
}
Non puoi farlo con define()
.
Nessuno dice nulla su php-doc, ma per me questo è anche un argomento molto significativo per la preferenza di const
:
/**
* My foo-bar const
* @var string
*/
const FOO = 'BAR';
Con la definizione della costante di parola chiave, otterrai le funzionalità di maiuscole e minuscole, ma con la parola chiave const no.
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
è due volte più veloce didefine
. Informazioni sul tempo di caricamento della pagina e sull'utilizzo della memoria: vedi questa domanda e questo articolo ... Vedi anche qualcosa sulla cache opcode qui .