definir () vs const


Pregunta bastante sencilla: En PHP, ¿cuándo se usa

define('FOO', 1);

Y cuando se utiliza

const FOO = 1;

¿Cuáles son las principales diferencias entre esos dos?

Author: Skelly1983, 2010-03-15

10 answers

A partir de PHP 5.3 hay dos maneras de definir constantes : Ya sea usando la palabra clave const o usando la define() función:

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

La diferencia fundamental entre esas dos formas es que const define constantes en tiempo de compilación, mientras que define las define en tiempo de ejecución. Esto causa la mayoría de las desventajas de const. Algunas desventajas de const son:

  • const no se puede usar para definir constantes condicionalmente. Para definir una constante global, debe utilizarse en el ámbito ultraperiférico:

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

    ¿Por qué querrías hacer eso de todos modos? Una aplicación común es comprobar si la constante ya está definida:

    if (!defined('FOO')) {
        define('FOO', 'BAR');
    }
    
  • const acepta un escalar estático (número, cadena u otra constante como true, false, null, __FILE__), mientras que define() toma cualquier expresión. Desde PHP 5.6 también se permiten expresiones constantes en const:

    const BIT_5 = 1 << 5;    // valid since PHP 5.6, invalid previously
    define('BIT_5', 1 << 5); // always valid
    
  • const toma un nombre constante simple, mientras que define() acepta cualquier expresión como nombre. Esto permite hacer cosas como esta:

    for ($i = 0; $i < 32; ++$i) {
        define('BIT_' . $i, 1 << $i);
    }
    
  • consts siempre distinguen entre mayúsculas y minúsculas, mientras que define() le permite definir constantes que no distinguen entre mayúsculas y minúsculas pasando true como tercer argumento:

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

Entonces, ese fue el lado malo de las cosas. Ahora veamos la razón por la que yo personalmente siempre uso const a menos que ocurra una de las situaciones anteriores:

  • const simplemente se lee mejor. Es una construcción de lenguaje en lugar de una función y también es consistente con cómo se definen las constantes en las clases.
  • const, al ser una construcción de lenguaje, se puede analizar estáticamente mediante herramientas automatizadas.
  • const define una constante en el espacio de nombres actual, mientras que define() tiene que pasar el nombre completo del espacio de nombres:

    namespace A\B\C;
    // To define the constant A\B\C\FOO:
    const FOO = 'BAR';
    define('A\B\C\FOO', 'BAR');
    
  • Desde PHP 5.6 const las constantes también pueden ser arrays, mientras que define() todavía no soporta arrays. Sin embargo, los arrays serán soportados para ambos casos 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
    

Finalmente, tenga en cuenta que const también se puede usar dentro de una clase o interfaz para definir una constante de clase o constante de interfaz. define no se puede utilizar para este propósito:

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

Resumen

A menos que necesite cualquier tipo de definición condicional o expresiva, use consts en lugar de define()s - ¡simplemente por el bien de la legibilidad!

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-18 16:11:40

Hasta PHP 5.3, const no se podía usar en el ámbito global. Solo puedes usar esto desde dentro de una clase. Esto se debe usar cuando desea establecer algún tipo de opción o configuración constante que pertenezca a esa clase. O tal vez quieras crear algún tipo de enum.

define se puede usar para el mismo propósito, pero solo se puede usar en el ámbito global. Solo debe usarse para configuraciones globales que afecten a toda la aplicación.

Un ejemplo de buen uso de const es obtener deshazte de los números mágicos. Echa un vistazo a constantes de la DOP. Cuando necesite especificar un tipo fetch, escriba PDO::FETCH_ASSOC, por ejemplo. Si no se usaran conss, terminarías escribiendo algo como 35 (o como se defina FETCH_ASSOC). Esto no tiene sentido para el lector.

Un ejemplo de buen uso de define es tal vez especificar la ruta raíz de su aplicación o el número de versión de una biblioteca.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-11 14:13:12

Sé que esto ya está contestado, pero ninguna de las respuestas actuales menciona el espacio de nombres y cómo afecta a las constantes y define.

A partir de PHP 5.3, los componentes y las definiciones son similares en la mayoría de los aspectos. Todavía hay, sin embargo, algunas diferencias importantes:

  • Los Conss no se pueden definir a partir de una expresión. const FOO = 4 * 3; no funciona, pero define('CONST', 4 * 3); sí.
  • El nombre pasado a define debe incluir el espacio de nombres que se definirá dentro de ese espacio de nombres.

El siguiente código debería ilustrar las diferencias.

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

namespace {
    var_dump(get_defined_constants(true));
}

El contenido del sub-array de usuario será ['foo\\BAR' => 1, 'BAZ' => 2, 'foo\\BAZ' => 3].

=== ACTUALIZAR ===

El próximo PHP 5.6 permitirá un poco más de flexibilidad con const. Ahora podrá definir conss en términos de expresiones, siempre que esas expresiones estén compuestas de otros conss o de literales. Esto significa que lo siguiente debe ser válido a 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;

Todavía no podrás para definir conss en términos de variables o retornos de función, entonces

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

Todavía estará fuera.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-16 11:28:14

Creo que a partir de PHP 5.3, se puede usar const fuera de las clases, como se muestra aquí en el segundo ejemplo:

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-06-30 01:16:29

define uso para constantes globales.

const uso para constantes de clase.

No puede define entrar en el ámbito de clase, y con const puede hacerlo. No hace falta decir que no se puede usar const fuera del ámbito de clase

También, con const, realmente se convierte en un miembro de la clase, con define, será empujado al ámbito global.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-15 14:30:52

La respuesta de NikiC es la mejor, pero permítanme agregar una advertencia no obvia al usar espacios de nombres para que no te atrapen con un comportamiento inesperado. Lo que hay que recordar es que defines are always en el espacio de nombres global a menos que agregue explícitamente el espacio de nombres como parte del identificador define. Lo que no es obvio es que el identificador de espacio de nombres triunfa sobre el identificador global. Entonces:

<?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

Lo que para mí hace que toda la noción de const sea innecesaria confusa ya que la idea de una const en docenas de otros lenguajes es que siempre es la misma donde quiera que estés en tu código, y PHP realmente no garantiza eso.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-17 20:21:15

La mayoría de estas respuestas son erróneas o solo cuentan la mitad de la historia.

  1. Puede delimitar sus constantes mediante espacios de nombres.
  2. Puede usar la palabra clave "const" fuera de las definiciones de clase. Sin embargo, al igual que en clases los valores asignados usando la palabra clave "const" deben ser expresiones constantes.

Por ejemplo:

const AWESOME = 'Bob'; // Valid

Mal ejemplo:

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

Para crear constantes de variables use define () de la siguiente manera:

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-07 09:49:19

Sí, const se define en tiempo de compilación y como estados nikic no se puede asignar una expresión, como puede definir (). Pero también las const no pueden ser declaradas condicionalmente (por la misma razón). IE. No puedes hacer esto:

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

Mientras que podrías con un define (). Por lo tanto, realmente no se reduce a la preferencia personal, hay una forma correcta y una incorrecta de usar ambos.

Como un aparte... Me gustaría ver algún tipo de clase const que se puede asignar una expresión, una especie de definir() que se puede aislar a las clases?

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-07 22:40:56

Para añadir la respuesta de NikiC. const se puede utilizar dentro de las clases de la siguiente manera:

class Foo {
    const BAR = 1;

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

No puedes hacer esto con 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-05 07:57:55

Nadie dice nada sobre php-doc, pero para mí también es un argumento muy significativo para la preferencia de 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-23 09:58:25