PHP | definir() frente a constante
En PHP, puedes declarar constantes de dos maneras:
Con
define
palabra clavedefine('FOO', 1);
Usando
const
palabra claveconst FOO = 1;
- ¿Cuáles son las principales diferencias entre esos dos?
- ¿Cuándo y por qué debería utilizar uno y cuándo utilizar el otro?
A partir de PHP 5.3, hay dos formas de definir constantes : ya sea usando la const
palabra clave 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 const
las desventajas. Algunas desventajas de const
son:
const
no se puede utilizar para definir constantes condicionalmente. Para definir una constante global, debe usarse en el ámbito más externo: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
) , mientras quefalse
acepta cualquier expresión. Desde PHP 5.6 también se permiten expresiones constantes :null
__FILE__
define()
const
const BIT_5 = 1 << 5; // Valid since PHP 5.6 and invalid previously define('BIT_5', 1 << 5); // Always valid
const
toma un nombre constante simple, mientras quedefine()
acepta cualquier expresión como nombre. Esto permite hacer cosas como esta:for ($i = 0; $i < 32; ++$i) { define('BIT_' . $i, 1 << $i); }
const
s siempre distinguen entre mayúsculas y minúsculas, mientras quedefine()
le permiten definir constantes que no distinguen entre mayúsculas y minúsculas pasándolastrue
como tercer argumento (Nota: la definición de constantes que no distinguen entre mayúsculas y minúsculas está obsoleta a partir de PHP 7.3.0 y se elimina desde PHP 8.0.0):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 personalmente siempre uso const
a menos que ocurra una de las situaciones anteriores:
const
simplemente se lee mejor. Es una construcción del lenguaje en lugar de una función y también es consistente con la forma en que se definen las constantes en las clases.const
, al ser una construcción del lenguaje, se puede analizar estáticamente mediante herramientas automatizadas.const
define una constante en el espacio de nombres actual, mientras quedefine()
se debe 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');
Dado que PHP 5.6
const
las constantes también pueden ser matrices, aunquedefine()
todavía no admite matrices. Sin embargo, las matrices serán compatibles en 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 and valid in PHP 7.0
Finalmente, tenga en cuenta que const
también se puede utilizar 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 algún tipo de definición condicional o expresiva, utilice const
s en lugar de define()
s, ¡simplemente por razones de legibilidad!
Hasta PHP 5.3, const
no se podía utilizar en el ámbito global. Sólo puedes usar esto desde dentro de una clase. Esto debe usarse cuando desee 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 enumeración.
define
se puede utilizar para el mismo propósito, pero solo se puede utilizar en el ámbito global. Sólo debe usarse para configuraciones globales que afecten a toda la aplicación.
Un ejemplo de buen const
uso es deshacerse de los números mágicos. Eche un vistazo a las constantes de PDO . Cuando necesite especificar un tipo de recuperación, deberá escribir PDO::FETCH_ASSOC
, por ejemplo. Si no se usaran constantes, terminaría escribiendo algo como 35
(o lo que sea que FETCH_ASSOC
se defina). Esto no tiene sentido para el lector.
Un ejemplo de buen define
uso es tal vez especificar la ruta raíz de su aplicación o el número de versión de una biblioteca.
Sé que esto ya está respondido, pero ninguna de las respuestas actuales menciona el espacio de nombres y cómo afecta las constantes y las definiciones.
A partir de PHP 5.3, las constantes y definiciones son similares en la mayoría de los aspectos. Sin embargo, todavía existen algunas diferencias importantes:
- Las constantes no se pueden definir a partir de una expresión.
const FOO = 4 * 3;
no funciona, perodefine('CONST', 4 * 3);
lo hace. - El nombre pasado
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 de la submatriz de usuario será ['foo\\BAR' => 1, 'BAZ' => 2, 'foo\\BAZ' => 3]
.
=== ACTUALIZACIÓN ===
El próximo PHP 5.6 permitirá un poco más de flexibilidad con const
. Ahora podrá definir constantes en términos de expresiones, siempre que esas expresiones estén formadas por otras constantes o literales. Esto significa que lo siguiente debería 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;
Sin embargo, aún no podrás definir constantes en términos de variables o retornos de funciones, por lo que
const RND = mt_rand();
const CONSTVAR = $var;
todavía estará fuera.
define
Lo uso para constantes globales.
const
Lo uso para constantes de clase.
No puedes define
entrar en el ámbito de la clase, y contigo const
puedes.
Además, con const
, en realidad se convierte en miembro de la clase y con define
, será llevado al ámbito global.