Für besser oder schlechter, loose-Typisierung ist „Die PHP-Way“. Viele der eingebauten und die meisten der Sprachkonstrukte werden auf den Typen funktionieren, die Sie ihnen geben - still (und oft gefährlich), indem sie hinter die Kulissen geworfen werden, damit die Dinge (irgendwie) zusammenpassen.
Da ich selbst von einem Java/C/C++ - Hintergrund herrühre, war das Modell für die lose Eingabe von PHP immer eine Quelle der Frustration für mich. Aber im Laufe der Jahre habe ich festgestellt, dass ich, wenn ich PHP schreiben muss, einen besseren Job machen kann (d. H. Sauberer, sicherer, testbarer Code), indem ich die "Lockerheit" von PHP anerkenne, anstatt sie zu bekämpfen; und ich lande deswegen einen glücklicheren Affen.
Casting ist wirklich grundlegend für meine Technik - und (IMHO) ist es die einzige Möglichkeit, sauberen, lesbaren PHP-Code zu erstellen, der gemischte Argumente in einer gut verständlichen, testbaren, deterministischen Art behandelt.
Der Hauptpunkt (den Sie auch klar verstehen) ist, dass Sie in PHP nicht einfach davon ausgehen können, dass ein Argument der Typ ist, den Sie erwarten. Dies kann schwerwiegende Folgen haben, die Sie wahrscheinlich erst nach dem Produktivstart Ihrer App feststellen.
Um diesen Punkt zu veranschaulichen:
<?php
function displayRoomCount($numBoys, $numGirls) {
// we'll assume both args are int
// check boundary conditions
if(($numBoys < 0) || ($numGirls < 0)) throw new Exception('argument out of range');
// perform the specified logic
$total = $numBoys + $numGirls;
print("{$total} people: {$numBoys} boys, and {$numGirls} girls \n");
}
displayRoomCount(0, 0); // (ok) prints: "0 people: 0 boys, and 0 girls"
displayRoomCount(-10, 20); // (ok) throws an exception
displayRoomCount("asdf", 10); // (wrong!) prints: "10 people: asdf boys, and 10 girls"
Ein Ansatz zur Lösung dieses die Typen zu beschränken ist, dass die Funktion übernehmen kann, eine Ausnahme auszulösen, wenn ein ungültiger Typ erkannt wird. Andere haben diesen Ansatz bereits erwähnt. Es passt gut zu meiner Ästhetik von Java/C/C++, und ich habe diesen Ansatz jahrelang in PHP verfolgt. Kurz gesagt, es ist nichts falsch daran, aber es geht gegen "The PHP Way", und nach einer Weile fühlt es sich an, als würde man flussaufwärts schwimmen.
Als Alternative bietet Casting eine einfache und saubere Methode, um sicherzustellen, dass sich die Funktion für alle möglichen Eingaben deterministisch verhält, ohne dass für jeden einzelnen Typ spezifische Logik geschrieben werden muss.
Mit Gießen, unserem Beispiel wird jetzt:
<?php
function displayRoomCount($numBoys, $numGirls) {
// we cast to ensure that we have the types we expect
$numBoys = (int)$numBoys;
$numGirls = (int)$numGirls;
// check boundary conditions
if(($numBoys < 0) || ($numGirls < 0)) throw new Exception('argument out of range');
// perform the specified logic
$total = $numBoys + $numGirls;
print("{$total} people: {$numBoys} boys, and {$numGirls} girls \n");
}
displayRoomCount("asdf", 10); // (ok now!) prints: "10 people: 0 boys, and 10 girls"
Die Funktion nun wie erwartet verhält. In der Tat ist es einfach zu zeigen, dass das Verhalten der Funktion nun für alle möglichen Eingaben gut definiert ist. Dies liegt daran, dass die Cast-Operation für alle möglichen Eingaben klar definiert ist. Die Casts stellen sicher, dass wir immer mit ganzen Zahlen arbeiten; und der Rest der Funktion ist so geschrieben, dass sie für alle möglichen ganzen Zahlen wohldefiniert ist.
Rules for type-casting in PHP are documented here, (siehe die typspezifischen Links in der Mitte der Seite - zB: "Converting to Integer").
Dieser Ansatz hat den zusätzlichen Vorteil, dass sich die Funktion jetzt in einer Weise verhält, die mit anderen PHP-Einbauten und Sprachkonstrukten übereinstimmt. Zum Beispiel:
// assume $db_row read from a database of some sort
displayRoomCount($db_row['boys'], $db_row['girls']);
werden gut funktionieren, trotz der Tatsache, dass $db_row['boys']
und $db_row['girls']
tatsächlich Strings sind die numerischen Werte enthalten. Dies ist konsistent mit der Art, wie der durchschnittliche PHP-Entwickler (der kein C, C++ oder Java kennt) davon ausgehen wird, dass es funktioniert.
Als Rückgabewert zum Gießen: es gibt sehr wenig Punkt dabei, es sei denn, Sie wissen, dass Sie einen potenziell Mischtyp-Variable haben, und Sie wollen immer sicherstellen, dass der Rückgabewert eine bestimmte Art ist. Dies ist häufiger an Zwischenpunkten im Code und nicht an dem Punkt, an dem Sie von einer Funktion zurückkehren.
Ein praktisches Beispiel:
<?php
function getParam($name, $idx=0) {
$name = (string)$name;
$idx = (int)$idx;
if($name==='') return null;
if($idx<0) $idx=0;
// $_REQUEST[$name] could be null, or string, or array
// this depends on the web request that came in. Our use of
// the array cast here, lets us write generic logic to deal with them all
//
$param = (array)$_REQUEST[$name];
if(count($param) <= $idx) return null;
return $param[$idx];
}
// here, the cast is used to ensure that we always get a string
// even if "fullName" was missing from the request, the cast will convert
// the returned NULL value into an empty string.
$full_name = (string)getParam("fullName");
Sie erhalten die Idee.
Es gibt ein paar der Gotcha von
PHP Casting Mechanismus bewusst zu sein, ist nicht intelligent genug, die "no-op" cast zu optimieren. So Casting immer verursacht eine Kopie der Variablen vorgenommen werden. In den meisten Fällen ist dies kein Problem, aber wenn Sie diesen Ansatz regelmäßig verwenden, sollten Sie dies im Hinterkopf behalten. Aus diesem Grund kann das Casting zu unerwarteten Problemen mit Referenzen und großen Arrays führen. Weitere Informationen finden Sie unter PHP Bug Report #50894.
In php wird eine ganze Zahl, die zu groß (oder zu klein) ist, um sie als Integer-Typ darzustellen, automatisch als Float (oder, falls erforderlich, als Double) dargestellt. Das bedeutet, dass das Ergebnis von ($big_int + $big_int)
tatsächlich ein Float sein kann, und wenn Sie es zu einem int umwandeln, wird die resultierende Zahl Kauderwelsch sein. Also, wenn Sie Funktionen erstellen, die mit großen ganzen Zahlen arbeiten müssen, sollten Sie dies im Hinterkopf behalten und wahrscheinlich einen anderen Ansatz in Betracht ziehen.
Sorry für den langen Post, aber es ist ein Thema, das ich in der Tiefe betrachtet habe, und im Laufe der Jahre, ich habe einiges an Wissen (und Meinung) über sie gesammelt. Wenn ich es hier herausbringe, hoffe ich, dass es jemand hilfreich finden wird.
Sie können denken, dass schwache Typisierung (wie in PHP, Javascript, Smalltalk, C, C++, etc.) ein Fehler ist, aber es ist Teil des Designs von PHP, und daher unwahrscheinlich, zu ändern. Es ist auch eine der Eigenschaften, die PHP zu einer C-Type-Sprache macht. – GZipp
@GZopp: C und C++ sind keine schwach typisierten Sprachen. –
Sie können tatsächlich verlangen, dass Argumente zu einem bestimmten Typ gehören, aber es funktioniert nur mit Klassen und Arrays, nicht mit anderen integrierten Typen. http://www.php.net/manual/en/functions.arguments.php#98425 – mwhite