Gibt es einen besonderen Unterschied zwischen intval und Casting zu int - `(int) X`?

219

Gibt es einen besonderen Unterschied zwischen intval und (int)?

Beispiel:

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

Gibt es einen besonderen Unterschied zwischen den beiden obigen Codezeilen?

Sarfraz
quelle

Antworten:

192

intval()kann eine Basis übergeben werden, von der konvertiert werden soll. (int)kann nicht.

int intval( mixed $var  [, int $base = 10  ] )
Bernstein
quelle
73
(int) ist schneller als intval (), laut wiki.phpbb.com/Best_Practices:PHP
Martin Thoma
Wie ich unten erwähnt heute früher, wird die Basis Umwandlung nicht wie erwartet funktionieren , wenn das Argument ein int oder float ist.
T-Dub
1
die Seite von Staaten @moose $i++ist falsch in rot. Aber es sollte langsamer sein !!
Shiplu Mokaddim
1
Ich habe nie darüber gesprochen $i++. Was meinst du? Wenn du sagst "Aber es sollte langsamer sein !!" was vergleichst du
Martin Thoma
6
Ich habe ein Benchmarking für ideone durchgeführt - Typografie (int)ist schneller x 2! (int): ideone.com/QggNGc , intval(): ideone.com/6Y8mPN
jave.web
52

Eine Sache, die Sie über den Unterschied zwischen (int)und beachten sollten intval(): intval()Behandelt Variablen, die bereits ints und floats sind, unabhängig vom Basisargument (zumindest ab PHP 5.3.5) als nicht konvertierungsbedürftig. Dieses Verhalten ist nicht das offensichtlichste, wie in den Kommentaren auf der PHP-Dokumentseite erwähnt und hier schamlos wiederholt:

$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?
t-dub
quelle
13
Der Doc hat sagen The base parameter has no effect unless the var parameter is a string.Dann wieder die Seite wurde anscheinend 4 Tage aktualisiert, vor so vielleicht das ist , was hinzugefügt wurde.
Leichtigkeitsrennen im Orbit
3
Hmm, nein. Dies ist seit fast 11 Jahren prominent dokumentiert .
Leichtigkeitsrennen im Orbit
6
Ob prominent dokumentiert oder nicht, das Verhalten ist ein wenig überraschend, da die Funktion theoretisch eine Basiskonvertierung durchführen kann. Es hat mich definitiv schon einmal gestolpert, aber vielleicht muss ich nur etwas vorsichtiger RTFM :)
T-Dub
7
Mir ist klar, dass dies ein alter Thread ist, und wenn Sie noch programmieren, dann hoffe ich, dass Sie jetzt sehen, warum dies tatsächlich das offensichtlichste Ergebnis ist. Ein int hat keine Basis, da base nur in Zeichenfolgendarstellungen verwendet wird. Oder einfacher gesagt, ein Int von 12 in Basis 10 ist dasselbe wie ein Int von 12 in Basis 99. Es ist immer noch 12. Die Erwartung, intval(12,8)die eine Antwort geben würde, dass bei der Konvertierung in eine Zeichenfolge ohne Formatierung wie eine Basis 8 aussehen würde Nummer ist einfach falsch. Was würden Sie erwarten, intval(12,16)weil es kein int a machen kann c?
Robert McKee
1
Oder anders ... Seit dem 1. Januar 1970 gab es 1523994328 Ticks. Die Frage, ob diese als MM / TT / JJJJ oder TT / MM / JJJJ gespeichert sind, ist nicht sinnvoll, da sie in keinem dieser Formate gespeichert sind. Es wird als Nummer gespeichert, nicht in einem bestimmten Datumsformat. Genauso wie zu fragen, was die Basis eines Int ist. Es ist sehr wichtig, Werte von dem Format zu trennen, in dem sie angezeigt werden.
Robert McKee
32

Entschuldigung für das Nekroing, ich wollte nur sehen, ob / wie sich PHP7 auf diese Frage auswirkt:

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

Der Test:

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"

Wie Sie sehen können, ist das Casting definitiv um fast 100% schneller

Aber ich musste die Anzahl der Schleifen auf 100 Millionen erhöhen, bevor der Unterschied eine Frage von Sekunden war. In den meisten Fällen würde ich mich dann tatsächlich um die Leistung kümmern.

Also bleibe ich bei der Verwendung der intvalFunktion, denn Casting ist ein bisschen Sprachmagie, die gerade stattfindet. Selbst wenn intvalCasting hinter den Kulissen verwendet wird, wenn beim Casting ein Fehler gefunden wird und dieser aus irgendeinem Grund nicht behoben werden kann (Abwärtskompatibilität?), Könnten sie zumindest das Problem beheben intval, um seine Aufgabe zu erfüllen.

Update (PHP 7.1 + Extrafall):

$ 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"

Sieht aus wie 7.1 optimiert intval, und ‚1‘ + 0 ist jetzt der Gewinner dieser Geschwindigkeit Wettbewerb :) ich noch mit halten würde intvalsowieso

Populus
quelle
1
Der einzige verbleibende Maßstab ist +0der var ... nicht sicher, ob die implizite Umwandlung hier schneller ist als die explizite.
SparK
2
LOL @ +0gewinnen ... das ist ein sehr schmutziger Hack
SparK
@SparK Ihre Idee :) Ich würde es aber nicht vertrauen, PHP Typ Casting Regeln sind nicht gerade die besten
Populus
Für v5.5.34meine Ergebnisse waren 9191.0059452057 ms, 23307.397127151 msund 11483.719110489 msjeweils. Vor PHP 7 ist das Casting also das schnellste.
GreeKatrina
Obwohl es weit weniger verständlich ist, mag ich $a = '1' + 0;und ich wette, die meisten haben nie daran gedacht, es so zu machen
mic
26

Ich denke, es gibt mindestens einen Unterschied: Mit intval können Sie angeben, welche Basis als zweiter Parameter verwendet werden soll (Basis 10 standardmäßig):

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

Kriege dich :

int 123
int 123
int 83
Pascal MARTIN
quelle
11
Ich finde es unglaublich amüsant, dass man die Basis-17-Zahl "g" in eine Dezimalzahl umwandeln kann:intval("2g", 17) = 50 = 2*17 + 16
JSchaefer
1
@JSchaefer Ich ging noch weiter und stellte fest, dass das Maximum, das ich als Basis passieren konnte 36, wie in intval("g", 36) //16. Jeder Wert größer als 36 gibt 0 zurück. Dies legt nahe, dass wir alle 0-9 plus az-Zeichen für unsere benutzerdefinierte Basis verwenden können, z intval("z",36) //35. Es sollte auch beachtet werden, dass der erste Parameter die Groß- und Kleinschreibung nicht berücksichtigt .
Jay Dadhania
17

Eine nützliche Eigenschaft von intvalist, dass es - da es sich um eine Funktion und nicht um ein Sprachkonstrukt handelt - als Argument an eine Funktion übergeben werden kann, die eine Funktion erwartet. Das kann man nicht machen (int).

Zum Beispiel habe ich es verwendet, um Ganzzahlen für die Aufnahme in eine SQL- IN()Klausel zu bereinigen , indem ich sie an übergeben habe array_map. Hier ist ein Beispiel:

$ids = implode(",", array_map('intval', $_POST['array_of_integers']));
$sql = "SELECT * FROM table WHERE ids IN ($ids)";
Kodos Johnson
quelle
anonyme Funktion als Rückruf:array_map(function($n){return (int)$n;}, $_POST['array_of_integers'])
Daniel Omine
@ DanielOmine Ich meinte, dass Sie es verwenden können, ohne die Rückruffunktion definieren zu müssen.
Kodos Johnson
15

Amber hat recht und wenn ich einen nützlichen Informationstyp hinzufügen darf, ist das Casting (Hinzufügen eines "(int)" vor Ihrem Ausdruck) 300 bis 600% schneller als intval. Wenn Sie also nicht mit anderen Basen als Dezimalzahlen arbeiten möchten, empfehle ich die Verwendung von: (int) $something

user900469
quelle
2
Etwas, das Sie vielleicht interessant finden könnte: programmers.stackexchange.com/questions/99445/…
Gerry
8

Das, was intvaleine einfache Besetzung nicht tut, ist die Basiskonvertierung:

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

Wenn die Basis jedoch 10 ist, intvalsollte dies mit einer Besetzung identisch sein (es sei denn, Sie werden pingelig sein und erwähnen, dass einer einen Funktionsaufruf ausführt, während der andere dies nicht tut). Wie auf der Manpage vermerkt :

Es gelten die allgemeinen Regeln für das Ganzzahl-Casting.

täuschen
quelle