Manipulación de tipos

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:

  • Numérico
  • String
  • Lógico
  • Integral y string
  • Comparativo
  • Función

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().

Contextos numéricos

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.

Contextos string

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.

Contextos lógicos

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.

Contextos integrales y string

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.

Contextos comparativos

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.

Contextos de funciones

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.

Advertencia

Las funciones internas fuerzan automáticamente null a los tipos escalares, este comportamiento está OBSOLETO a partir de PHP 8.1.0.

Tipado coercitivo con declaraciones de tipo simples

  • Tipo de declaración bool: valor se interpreta como bool.
  • Tipo de declaración int: valor se interpreta como int si la conversión está bien definida. Por ejemplo, la cadena es numérica.
  • Tipo de declaración float: valor se interpreta como float si la conversión está bien definida. Por ejemplo, la cadena es numérica.
  • Tipo de declaración string: valor se interpreta como string.

Tipado coercitivo con uniones de tipo

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:

  1. int
  2. float
  3. string
  4. bool
Si el tipo existe en la unión y el valor puede ser forzado a este tipo utilizando la semántica de verificación de tipo existente de PHP, entonces el tipo es elegido.

Precaución

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

Cast de tipo

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 NULL

Nota:

(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.

Advertencia

El alias de cast (real) está obsoleto a partir de PHP 8.0.0.

Advertencia

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.

Precaución

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:

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
?>
Ver la sección sobre el acceso a las cadenas por caracter para más información.

add a note

User Contributed Notes 9 notes

up
74
Raja
20 years ago
Uneven division of an integer variable by another integer variable will result in a float by automatic conversion -- you do not have to cast the variables to floats in order to avoid integer truncation (as you would in C, for example):

$dividend = 2;
$divisor = 3;
$quotient = $dividend/$divisor;
print $quotient; // 0.66666666666667
up
15
Anonymous
4 years ago
Cast operators have a very high precedence, for example (int)$a/$b is evaluated as ((int)$a)/$b, not as (int)($a/$b) [which would be like intdiv($a,$b) if both $a and $b are integers].
The only exceptions (as of PHP 8.0) are the exponentiation operator ** [i.e. (int)$a**$b is evaluated as (int)($a**$b) rather than ((int)$a)**$b] and the special access/invocation operators ->, ::, [] and () [i.e. in each of (int)$a->$b, (int)$a::$b, (int)$a[$b] and (int)$a($b), the cast is performed last on the result of the variable expression].
up
27
fardelian
12 years ago
Casting objects to arrays is a pain. Example:

<?php

class MyClass {

private
$priv = 'priv_value';
protected
$prot = 'prot_value';
public
$pub = 'pub_value';
public
$MyClasspriv = 'second_pub_value';

}

$test = new MyClass();
echo
'<pre>';
print_r((array) $test);

/*
Array
(
[MyClasspriv] => priv_value
[*prot] => prot_value
[pub] => pub_value
[MyClasspriv] => second_pub_value
)
*/

?>

Yes, that looks like an array with two keys with the same name and it looks like the protected field was prepended with an asterisk. But that's not true:

<?php

foreach ((array) $test as $key => $value) {
$len = strlen($key);
echo
"{$key} ({$len}) => {$value}<br />";
for (
$i = 0; $i < $len; ++$i) {
echo
ord($key[$i]) . ' ';
}
echo
'<hr />';
}

/*
MyClasspriv (13) => priv_value
0 77 121 67 108 97 115 115 0 112 114 105 118
*prot (7) => prot_value
0 42 0 112 114 111 116
pub (3) => pub_value
112 117 98
MyClasspriv (11) => second_pub_value
77 121 67 108 97 115 115 112 114 105 118
*/

?>

The char codes show that the protected keys are prepended with '\0*\0' and private keys are prepended with '\0'.__CLASS__.'\0' so be careful when playing around with this.
up
16
miracle at 1oo-percent dot de
19 years ago
If you want to convert a string automatically to float or integer (e.g. "0.234" to float and "123" to int), simply add 0 to the string - PHP will do the rest.

e.g.

$val = 0 + "1.234";
(type of $val is float now)

$val = 0 + "123";
(type of $val is integer now)
up
14
rmirabelle
14 years ago
The object casting methods presented here do not take into account the class hierarchy of the class you're trying to cast your object into.

/**
* Convert an object to a specific class.
* @param object $object
* @param string $class_name The class to cast the object to
* @return object
*/
public static function cast($object, $class_name) {
if($object === false) return false;
if(class_exists($class_name)) {
$ser_object = serialize($object);
$obj_name_len = strlen(get_class($object));
$start = $obj_name_len + strlen($obj_name_len) + 6;
$new_object = 'O:' . strlen($class_name) . ':"' . $class_name . '":';
$new_object .= substr($ser_object, $start);
$new_object = unserialize($new_object);
/**
* The new object is of the correct type but
* is not fully initialized throughout its graph.
* To get the full object graph (including parent
* class data, we need to create a new instance of
* the specified class and then assign the new
* properties to it.
*/
$graph = new $class_name;
foreach($new_object as $prop => $val) {
$graph->$prop = $val;
}
return $graph;
} else {
throw new CoreException(false, "could not find class $class_name for casting in DB::cast");
return false;
}
}
up
19
Anonymous
22 years ago
Printing or echoing a FALSE boolean value or a NULL value results in an empty string:
(string)TRUE //returns "1"
(string)FALSE //returns ""
echo TRUE; //prints "1"
echo FALSE; //prints nothing!
up
17
ieee at REMOVE dot bk dot ru
12 years ago
There are some shorter and faster (at least on my machine) ways to perform a type cast.
<?php
$string
='12345.678';
$float=+$string;
$integer=0|$string;
$boolean=!!$string;
?>
up
2
Anonymous
6 months ago
Type casting in expressions is executed first.
The casting is assigned to the value, not to the expression result.
Examples:

<?php

$string
= "777";

var_dump( $string === 777 ); // FALSE
var_dump( (int) $string === 777 ); // TRUE
var_dump( ( (int) $string ) === 777 ); // TRUE
var_dump( (int) ( $string === 777 ) ); // 0
?>
up
1
bioingbenito at gmail dot com
1 month ago
This PHP documentation is very thorough.
An observation about comments, maybe they lost sense when become old, and the page changes, so, should be signaled this condition, or add a link to the document version when the comment was made.
To Top