PHP no requiere una definición de tipo explícita en las declaraciones de variables. En este caso, el tipo de una variable se determina en función del valor que tiene almacenado. Es decir, si una string se asigna a la variable $var, entonces $var es de tipo string. Si después se asigna un valor int a $var, será de tipo int.
PHP puede intentar convertir el tipo de un valor en otro automáticamente en ciertos contextos. Los diferentes contextos que existen son:
Nota: Cuando un valor necesita ser interpretado como un tipo diferente, el valor en sí no cambia de tipo.
Para forzar una variable a ser evaluada como un tipo particular, ver la sección sobre casting de tipo. Para cambiar el tipo de una variable, ver la función settype().
Este es el contexto al utilizar un operador aritmético.
En este contexto, si uno de los operandos es un float (o no interpretable como int), ambos operandos se interpretan como floats, y el resultado será un float. De lo contrario, los operandos se interpretan como ints, y el resultado será también un int. A partir de PHP 8.0.0, si uno de los operandos no puede ser interpretado como TypeError se lanza.
Este es el contexto al utilizar echo, print, la interpolación de cadenas de caracteres, o el operador de concatenación para las cadenas de caracteres.
En este contexto, el valor se interpretará como una string.
Si el valor no puede ser interpretado, se levanta una
TypeError.
Anterior a PHP 7.4.0, se generaba una E_RECOVERABLE_ERROR
.
Este es el contexto al utilizar declaraciones condicionales, el operador ternario, o un operador lógico.
En este contexto, el valor se interpretará como un bool.
Este es el contexto al utilizar un operador bit a bit.
En este contexto, si todos los operandos son de tipo string entonces el resultado será también una string. De lo contrario, los operandos se interpretarán como ints, y el resultado será también un int. A partir de PHP 8.0.0, si uno de los operandos no puede ser interpretado, se lanza una TypeError.
Este es el contexto al utilizar un operador de comparación.
Las conversiones de tipos que se producen en este contexto se explican en el tabla Comparación con varios tipos.
Este es el contexto cuando un valor se pasa a un parámetro o propiedad tipada o se devuelve desde una función que declara un tipo de retorno.
En este contexto, el valor debe ser una valor del tipo. Existen dos excepciones, la primera es la siguiente: si el valor es de tipo int y el tipo declarado es float, entonces el entero se convierte en número de coma flotante. La segunda es: si el tipo declarado es un tipo escalar , el valor es convertible en un tipo escalar, y el modo de tipado coercitivo está activo (por omisión), el valor puede ser convertido en un valor escalar aceptado. Ver a continuación para una descripción de este comportamiento.
Las funciones internas
fuerzan automáticamente null
a los tipos escalares,
este comportamiento está OBSOLETO a partir de PHP 8.1.0.
Cuando strict_types
no está activado, las
declaraciones de tipo escalar están sujetas a restricciones de tipo
implícitas limitadas.
Si el tipo exacto del valor no forma parte de la unión, el tipo objetivo
se elige en el siguiente orden de preferencia:
A título de excepción, si el valor es una cadena y int y float forman
ambos parte de la unión, el tipo preferido se determina por la
semántica de cadena numérica.
Por ejemplo, para "42"
int es elegido,
mientras que para "42.0"
float es elegido.
Nota:
Los tipos que no forman parte de la lista de preferencias anterior no son objetivos admisibles para la coerción implícita. En particular, ninguna restricción implícita a los tipos
null
yfalse
se produce.
Ejemplo #1 Ejemplo de tipos restringidos a una parte del tipo de la unión
<?php // int|string 42 --> 42 // tipo exacto "42" --> "42" // tipo exacto new ObjectWithToString --> "Result of __toString()" // objeto nunca compatible con int, recurrir a string 42.0 --> 42 // float compatible con int 42.1 --> 42 // float compatible con int 1e100 --> "1.0E+100" // float demasiado grande para el tipo int, recurrir a string INF --> "INF" // float demasiado grande para el tipo int, recurrir a string true --> 1 // bool compatible con int [] --> TypeError // array no compatible con int o string // int|float|bool "45" --> 45 // int string numérico "45.0" --> 45.0 // float string numérico "45X" --> true // no string numérico, recurrir a bool "" --> false // no string numérico, recurrir a bool "X" --> true // no string numérico, recurrir a bool [] --> TypeError // array no compatible con int, float o bool ?>
El casting de tipo convierte el valor a un tipo dado escribiendo el tipo entre paréntesis antes del valor a convertir.
Ejemplo #2 Conversión de tipo
<?php
$foo = 10; // $foo es un integer
$bar = (bool) $foo; // $bar es un bool
var_dump($bar);
?>
Los casts permitidos son:
(int)
- cast en int(bool)
- cast en bool(float)
- cast en float(string)
- cast en string(array)
- cast en array(object)
- cast en object(unset)
- cast en NULLNota:
(integer)
es un alias del cast(int)
.(boolean)
es un alias del cast(bool)
.(binary)
es un alias del cast(string)
.(double)
y(real)
son alias del cast(float)
. Estos casts no utilizan el nombre de tipo canónico y no son recomendados.
El alias de cast (real)
está obsoleto a partir de PHP 8.0.0.
El cast (unset)
fue declarado obsoleto a partir de PHP 7.2.0.
A notar que el cast (unset)
es idéntico a asignar el
valor NULL a una variable o una llamada.
El cast (unset)
es eliminado a partir de PHP 8.0.0.
El cast (binary)
y el prefijo b
existen únicamente para la compatibilidad ascendente. Actualmente
(binary)
y (string)
son idénticos,
pero esto puede cambiar: no se debe contar con ello.
Nota:
Los espacios en blanco se ignoran dentro de los paréntesis de un cast. Así, los dos casts siguientes son equivalentes:
<?php
$foo = (int) $bar;
$foo = ( int ) $bar;
?>
Cast de strings literales y variables en strings binarios:
<?php
$binary = (binary) $string;
$binary = b"binary string";
?>
En lugar de transtypar una variable en una string, también es posible rodear la variable con comillas dobles.
Ejemplo #3 Diferentes mecanismos de conversión
<?php
$foo = 10; // $foo es un integer
$str = "$foo"; // $str es una cadena
$fst = (string) $foo; // $fst es también una cadena
// Esto muestra "Son iguales"
if ($fst === $str) {
echo "Son iguales", PHP_EOL;
}
?>
Lo que ocurrirá exactamente al transtypar entre ciertos tipos no es necesariamente evidente. Para más información, ver estas secciones:
Nota: Como PHP soporta la indexación en las strings mediante posiciones utilizando la misma sintaxis que la indexación de array, el siguiente ejemplo es válido para todas las versiones de PHP:
Ver la sección sobre el acceso a las cadenas por caracter para más información.Ejemplo #4 Uso de un índice de array con una cadena
<?php
$a = 'car'; // $a es una cadena de caracteres
$a[0] = 'b'; // $a sigue siendo una cadena de caracteres
echo $a; // bar
?>