¿Hay alguna diferencia particular entre intval y casting a int - `(int) X`?


¿Hay alguna diferencia particular entre intval y (int)?

Ejemplo:

$product_id = intval($_GET['pid']);
$product_id = (int) $_GET['pid'];

¿Hay alguna diferencia particular entre las dos líneas de código anteriores?

 181
php
Author: Vladislav Rastrusny, 2009-12-16

7 answers

intval() puede ser pasado una base a partir de la cual convertir. (int) no puede.

int intval( mixed $var  [, int $base = 10  ] )
 159
Author: Amber,
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
2009-12-16 06:01:35

Una cosa a tener en cuenta sobre la diferencia entre (int) y intval(): intval() trata las variables que ya son ints y floats como que no necesitan conversión, independientemente del argumento base (al menos a partir de PHP 5.3.5). Este comportamiento no es el más obvio, como se observa en los comentarios en la página PHP doc y se reitera descaradamente aquí:

$test_int    = 12;
$test_string = "12";
$test_float  = 12.8;

echo (int) $test_int;         // 12
echo (int) $test_string;      // 12
echo (int) $test_float;       // 12

echo intval($test_int, 8);    // 12 <-- WOAH!
echo intval($test_string, 8); // 10
echo intval($test_float, 8)   // 12 <-- HUH?
 44
Author: t-dub,
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
2011-10-19 17:16:36

Creo que hay al menos una diferencia: con intval, puede especificar qué base debe usarse como segundo parámetro (base 10 por defecto):

var_dump((int)"0123", intval("0123"), intval("0123", 8));

Te conseguirá:

int 123
int 123
int 83
 22
Author: Pascal MARTIN,
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
2009-12-16 06:19:23

Lo siento por necroing, solo quería ver si / cómo PHP7 tiene un efecto en esta pregunta:

$ php -v
PHP 7.0.4-5+deb.sury.org~trusty+1 (cli) ( NTS )

La prueba:

php > $start_ts = microtime(true); for($i = 0; $i < 100000000; $i++) { $a = (int) '1'; } var_dump((microtime(true) - $start_ts)*1000 . ' ms');
string(18) "3279.1121006012 ms"
php > $start_ts = microtime(true); for($i = 0; $i < 100000000; $i++) { $a = intval('1'); } var_dump((microtime(true) - $start_ts)*1000 . ' ms');
string(18) "5379.3351650238 ms"

Como puedes ver, el casting es definitivamente más rápido, por casi 100%

Pero tuve que aumentar el conteo de bucles a 100 millones antes de que la diferencia fuera cuestión de segundos, que es cuando realmente empezaría a preocuparme por el rendimiento, en la mayoría de los casos.

Así que me quedo con el uso de la función intval, porque casting es un poco de lenguaje magia que está pasando. Incluso si intval utiliza casting detrás de las escenas, si hubiera un error encontrado con casting, y por alguna razón no se podría arreglar (¿compatibilidad con versiones anteriores?), entonces podrían al menos arreglar intval para realizar su deber.

Actualización (PHP 7.1 + Caso extra):

$ php -v
PHP 7.1.0RC6 (cli) (built: Nov  9 2016 04:45:59) ( NTS )
$ php -a
php > $start_ts = microtime(true); for($i = 0; $i < 100000000; $i++) { $a = (int) '1'; } var_dump((microtime(true) - $start_ts)*1000 . ' ms');
string(18) "3583.9052200317 ms"
php > $start_ts = microtime(true); for($i = 0; $i < 100000000; $i++) { $a = intval('1'); } var_dump((microtime(true) - $start_ts)*1000 . ' ms');
string(18) "3569.0960884094 ms"
php > $start_ts = microtime(true); for($i = 0; $i < 100000000; $i++) { $a = '1' + 0; } var_dump((microtime(true) - $start_ts)*1000 . ' ms');
string(18) "1641.7920589447 ms"

Parece 7.1 optimizado intval, y '1' + 0 es ahora el ganador de este concurso de velocidad:) Todavía seguiría usando intval de todos modos

 20
Author: Populus,
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-12-03 00:24:30

Amber tiene razón y si me permite añadir una información útil type casting (agregar un "(int) " antes de su expresión) es de 300 a 600% más rápido que intval. Así que si su propósito no es tratar con otras bases que decimal, recomiendo usar: (int) $something

 12
Author: user900469,
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
2011-08-18 11:20:29

Una propiedad útil de intval es que, dado que es una función y no una construcción de lenguaje, se puede pasar como argumento a una función que espera una función. No puedes hacer esto con (int).

Por ejemplo, lo he usado para desinfectar enteros para incluirlos en una cláusula SQL IN() pasándola a array_map. He aquí un ejemplo:

$ids = implode(",", array_map('intval', $_POST['array_of_integers']));
$sql = "SELECT * FROM table WHERE ids IN ($ids)";
 11
Author: Kodos Johnson,
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-12-01 22:05:40

Lo que intval hace que un molde simple no lo hace es la conversión básica:

int intval ( mixed $var [, int $base = 10 ] )

Si la base es 10, intval debería ser lo mismo que un cast (a menos que seas quisquilloso y menciones que uno hace una llamada a la función mientras que el otro no). Como se indica en la página de manual de :

Se aplican las reglas comunes de fundición de enteros.

 8
Author: deceze,
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
2009-12-16 06:02:14