Question define () vs const


Question assez simple: En PHP, quand utilisez-vous

define('FOO', 1);

et quand utilisez-vous

const FOO = 1;

Quelles sont les principales différences entre ces deux?


564
2018-03-15 14:23


origine


Réponses:


À partir de PHP 5.3, il y a deux façons de définir des constantes: Soit en utilisant le const mot-clé ou en utilisant le define() fonction:

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

La différence fondamentale entre ces deux façons est que const définit les constantes au moment de la compilation, alors que define les définit au moment de l'exécution. Cela provoque la plupart des constLes inconvénients. Quelques inconvénients de const sont:

  • const ne peut pas être utilisé pour définir des constantes de manière conditionnelle. Pour définir une constante globale, elle doit être utilisée dans la portée la plus externe:

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

    Pourquoi voudriez-vous le faire de toute façon? Une application courante consiste à vérifier si la constante est déjà définie:

    if (!defined('FOO')) {
        define('FOO', 'BAR');
    }
    
  • const accepte un scalaire statique (nombre, chaîne ou autre constante comme true, false, null, __FILE__), tandis que define() prend n'importe quelle expression. Depuis PHP 5.6 expressions constantes sont autorisés dans const ainsi que:

    const BIT_5 = 1 << 5;    // valid since PHP 5.6, invalid previously
    define('BIT_5', 1 << 5); // always valid
    
  • const prend un nom constant, tandis que define() accepte toute expression comme nom. Cela permet de faire des choses comme ça:

    for ($i = 0; $i < 32; ++$i) {
        define('BIT_' . $i, 1 << $i);
    }
    
  • consts sont toujours sensibles à la casse, alors que define() vous permet de définir des constantes insensibles à la casse en passant true comme le troisième argument:

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

Donc, c'était le mauvais côté des choses. Maintenant, regardons la raison pour laquelle j'utilise toujours personnellement const sauf si l'une des situations ci-dessus se produit:

  • const lit simplement plus agréable. C'est une construction de langage au lieu d'une fonction et elle est également cohérente avec la façon dont vous définissez les constantes dans les classes.
  • const, étant une construction de langage, peut être analysée statiquement par un outillage automatisé.
  • const définit une constante dans l'espace de noms actuel, define() doit être passé le nom de l'espace de nom complet:

    namespace A\B\C;
    // To define the constant A\B\C\FOO:
    const FOO = 'BAR';
    define('A\B\C\FOO', 'BAR');
    
  • Depuis PHP 5.6 const les constantes peuvent également être des tableaux, tandis que define() ne supporte pas encore les tableaux. Cependant les tableaux seront supportés pour les deux cas en 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
    

Enfin, notez que const peut également être utilisé dans une classe ou une interface pour définir un constante de classe ou une constante d'interface. define ne peut pas être utilisé à cette fin:

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

Résumé

Sauf si vous avez besoin d'un type de définition conditionnelle ou expressionnelle, utilisez consts au lieu de define()s - simplement pour des raisons de lisibilité!


919
2017-07-07 09:59



Jusqu'à PHP 5.3, const n'a pas pu être utilisé dans la portée globale. Vous ne pouvez utiliser cela que dans une classe. Cela devrait être utilisé lorsque vous voulez définir une sorte d'option constante ou un paramètre qui appartient à cette classe. Ou peut-être que vous voulez créer une sorte d'énumération.

define peut être utilisé dans le même but, mais il ne peut être utilisé que dans la portée globale. Il ne doit être utilisé que pour les paramètres globaux qui affectent l'ensemble de l'application.

Un exemple de bien const l'usage est de se débarrasser des nombres magiques. Jeter un coup d'œil à Les constantes de PDO. Lorsque vous devez spécifier un type d'extraction, tapez PDO::FETCH_ASSOC, par exemple. Si les consts n'étaient pas utilisés, vous finiriez par taper quelque chose comme 35(ou peu importe FETCH_ASSOC est défini comme). Cela n'a aucun sens pour le lecteur.

Un exemple de bien define l'utilisation est peut-être spécifier le chemin racine de votre application ou le numéro de version d'une bibliothèque.


192
2018-03-15 14:26



Je sais que cela a déjà été répondu, mais aucune des réponses actuelles ne fait mention de l'espace de noms et de la manière dont il affecte les constantes et les définitions.

Depuis PHP 5.3, les consts et les définitions sont similaires sur la plupart des points. Il y a cependant quelques différences importantes:

  • Les constats ne peuvent pas être définis à partir d'une expression. const FOO = 4 * 3; ne fonctionne pas, mais define('CONST', 4 * 3); Est-ce que.
  • Le nom est passé à define doit inclure l'espace de noms à définir dans cet espace de noms.

Le code ci-dessous devrait illustrer les différences.

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

namespace {
    var_dump(get_defined_constants(true));
}

Le contenu du sous-groupe utilisateur sera ['foo\\BAR' => 1, 'BAZ' => 2, 'foo\\BAZ' => 3].

=== UPDATE ===

Le prochain PHP 5.6 permettra un peu plus de flexibilité avec const. Vous pourrez désormais définir des constantes en termes d'expressions, à condition que ces expressions soient constituées d'autres constantes ou de littéraux. Cela signifie que les éléments suivants devraient être valables à partir de 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;

Vous ne serez toujours pas en mesure de définir des consts en termes de variables ou de retours de fonctions, donc

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

sera toujours dehors.


34
2017-09-26 12:20



Je crois que depuis PHP 5.3, vous pouvez utiliser const en dehors des classes, comme montré ici dans le deuxième exemple:

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
2018-06-30 01:16



define J'utilise pour les constantes globales.

const J'utilise pour les constantes de classe.

Vous ne pouvez pas define dans la portée de la classe, et avec const vous pouvez. Inutile de dire que vous ne pouvez pas utiliser const hors champ de la classe

Aussi, avec const, il devient en fait un membre de la classe, avec define, il sera poussé à l'échelle mondiale.


15
2018-03-15 14:24



La réponse de NikiC est la meilleure, mais permettez-moi d'ajouter une mise en garde non évidente lorsque vous utilisez des espaces de noms afin de ne pas vous faire attraper avec un comportement inattendu. La chose à retenir est que les définitions sont toujours dans l'espace de noms global sauf si vous ajoutez explicitement l'espace de noms dans le cadre de l'identificateur de définition. Ce qui n'est pas évident à ce sujet, c'est que l'identifiant namespaced l'emporte sur l'identifiant global. Alors :

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

produit:

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

Ce qui me rend toute la notion de const inutilement confuse puisque l'idée d'un const dans des douzaines d'autres langages est que c'est toujours pareil partout où vous êtes dans votre code, et PHP ne le garantit pas vraiment.


12
2018-05-17 20:21



La plupart de ces réponses sont fausses ou ne racontent que la moitié de l'histoire.

  1. Vous pouvez définir vos constantes en utilisant des espaces de noms.
  2. Vous pouvez utiliser le mot clé "const" en dehors des définitions de classe. Cependant, comme dans classes les valeurs affectées en utilisant le mot-clé "const" doivent être expressions constantes.

Par exemple:

const AWESOME = 'Bob'; // Valid

Mauvais exemple:

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

Pour créer des constantes variables, utilisez define () comme ceci:

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

12
2018-02-07 09:49



Oui, const est défini au moment de la compilation et les états nikic ne peuvent pas être affectés d'une expression, comme peut le définir (). Mais aussi const ne peut pas être déclaré conditionnellement (pour la même raison). c'est à dire. Tu ne peux pas faire ça:

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

Alors que vous pourriez avec un define (). Donc, il ne s'agit pas vraiment d'une préférence personnelle, il y a une bonne et une mauvaise façon d'utiliser les deux.

En aparté ... J'aimerais voir une sorte de const de classe qui peut être assignée à une expression, une sorte de define () qui peut être isolée des classes?


5
2017-07-07 22:40



Pour ajouter sur la réponse de NikiC. const peut être utilisé dans les classes de la manière suivante:

class Foo {
    const BAR = 1;

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

Tu ne peux pas faire ça avec define().


3
2018-04-05 07:57



Personne ne dit quoi que ce soit à propos de php-doc, mais pour moi c'est aussi un argument très significatif pour la préférence de const:

/**
 * My foo-bar const
 * @var string
 */
const FOO = 'BAR';

1
2017-12-23 09:58