Abschnitt 6 · Lektion 2
Typen an Funktionen
Bis hierher hast du nirgends hingeschrieben, was für ein Wert irgendwo steckt. Bei einer gewöhnlichen Variablen geht das auch gar nicht. An einer Funktion darfst du es: vor jedem Parameter und hinter der Klammer für die Rückgabe. Ob PHP sich daran hält, ist allerdings eine zweite Frage.
Ohne Typen wird alles irgendwie passend gemacht
<?php
function rabatt($preis, $prozent)
{
return $preis - $preis * $prozent / 100;
}
echo number_format(rabatt("24.99", "20"), 2), "\n";
echo number_format(rabatt("59.90", "10"), 2), "\n";
// Und jetzt ein Preis mit deutschem Komma:
echo number_format(rabatt("12,50", "50"), 2), "\n"; Drei Aufrufe, drei Ergebnisse, und php index.php; echo $? im Terminal meldet eine 0. Sieh dir
trotzdem die dritte Zeile an: Aus 12,50 mit deutschem Komma wird 6.00 statt 6.25.
Was passiert ist: PHP hat aus dem Text so viel Zahl gemacht, wie vorne draufstand, nämlich 12,
und den Rest weggeworfen. Auf dem Fehlerkanal steht dazu zweimal A non-numeric value encountered,
aber die Ausgabe sieht völlig in Ordnung aus, und das Programm läuft weiter.
Was in der Funktion wirklich ankommt, zeigt dir der Reiter Debug. Nach Aufzeichnen steht an
der return-Zeile dreimal preis="24.99", preis="59.90", preis="12,50", jedes Mal in
Anführungszeichen: Text, keine Zahl. Merk dir das Bild, gleich sieht dieselbe Zeile anders aus.
Das ist die Warning aus Lektion 1.4 in ihrer teuersten Form: eine Rechnung, die falsch ist und sich nicht so anfühlt. Auf einer echten Seite wäre das ein Preis, den niemand nachrechnet.
Ein Typ macht daraus einen Abbruch
<?php
// Getypt, aber ohne die strenge Zeile:
function rabatt(float $preis, int $prozent): float
{
return $preis - $preis * $prozent / 100;
}
// Eine saubere Zahl in Anfuehrungszeichen wird umgewandelt:
var_dump(rabatt("24.99", "20"));
// Diese hier ist keine saubere Zahl, und jetzt bricht es ab:
var_dump(rabatt("12,50", 50));
echo "Diese Zeile wird nie erreicht.\n"; Jetzt steht float vor $preis, int vor $prozent und : float hinter der Klammer. Sieh dir
an, was die beiden Aufrufe daraus machen.
Der erste Aufruf geht weiterhin durch. "24.99" ist eine saubere Zahl in Anführungszeichen,
und PHP wandelt sie stillschweigend um; im Reiter Debug steht an der return-Zeile jetzt
preis=24.99 ohne Anführungszeichen, aus dem Text ist eine Zahl geworden. Der zweite Aufruf bricht
dagegen ab, mit einem TypeError und der 255 hinter php index.php; echo $?: "12,50" ist keine
saubere Zahl, und ein Typ lässt sich das nicht mehr gefallen. Die letzte Zeile wird nie erreicht.
Das ist schon ein großer Gewinn. Aus einem falschen Ergebnis ist ein Abbruch geworden, und ein Abbruch nennt dir die Zeile.
Die eine Zeile, die aus einer Empfehlung eine Zusage macht
<?php
declare(strict_types=1);
function rabatt(float $preis, int $prozent): float
{
return $preis - $preis * $prozent / 100;
}
// Echte Zahlen, kein Problem:
var_dump(rabatt(24.99, 20));
var_dump(rabatt(12.50, 50));
// Dieselbe Zahl in Anfuehrungszeichen ist jetzt ein Fehler:
var_dump(rabatt("24.99", 20)); declare(strict_types=1); schaltet die stillschweigende Umwandlung für diese Datei ab. Danach ist
auch "24.99" ein Fehler, obwohl es sich rechnen ließe. Wer eine Zahl will, bekommt nur noch eine
Zahl.
Ab dieser Lektion steht die Zeile in jeder Datei dieses Kurses. Der Grund ist nicht Strenge um ihrer selbst willen. Ohne sie ist ein Typ eine Empfehlung, die PHP im Zweifel umgeht, und du weißt beim Lesen nicht, was wirklich ankommt. Mit ihr ist er eine Zusage, auf die du dich verlassen kannst, und genau darum hast du ihn ja hingeschrieben.
Der Preis dafür steht in der Aufgabe zu dieser Lektion: Du musst die Aufrufe in Ordnung bringen. Das ist keine Schikane, sondern die Arbeit, die vorher niemand gemacht hat.
Sie muss wirklich ganz oben stehen
<?php
echo "Erst etwas anderes\n";
declare(strict_types=1);
echo "Und danach\n"; Hier passiert etwas, das du dir merken solltest: Die Ausgabe bleibt komplett leer. Nicht einmal
das echo von oben läuft.
declare(strict_types=1); muss die erste Anweisung der Datei sein. Steht davor irgendetwas anderes,
sagt PHP strict_types declaration must be the very first statement in the script, und zwar schon
beim Einlesen, nicht beim Ausführen. Es ist derselbe Fall wie ein Parse-Fehler aus Lektion 1.4: Das
Programm startet gar nicht erst.
Erlaubt sind davor nur das <?php, Leerzeilen und Kommentare. Ein echo, ein include oder eine
Zuweisung nicht.
Zwei Angaben, die du oft brauchst
<?php
declare(strict_types=1);
function alterVon(string $name): ?int
{
$liste = ["Mia" => 34, "Ben" => 28];
return $liste[$name] ?? null;
}
var_dump(alterVon("Mia"));
var_dump(alterVon("Tom"));
function melde(string $text): void
{
echo $text, "\n";
}
var_dump(melde("fertig"));
// Eine ganze Zahl darf auch strikt an ein float:
function haelfte(float $z): float
{
return $z / 2;
}
var_dump(haelfte(9)); Das Fragezeichen vor einem Typ heißt „oder null”. ?int sagt: Hier kommt eine ganze Zahl
zurück, oder eben nichts, weil es den Namen nicht gab. Ohne das Fragezeichen wäre die zweite Zeile
ein TypeError, und das ist gut so, denn dann müsstest du dich entscheiden.
void heißt „gibt nichts zurück”. Eine solche Funktion tut etwas, statt etwas zu liefern, und
var_dump zeigt dir trotzdem NULL: Das ist der Wert, den jede Funktion ohne return liefert, wie
in Lektion 6.1. Ein return mit einem Wert wäre in einer void-Funktion ein Fehler.
Die letzte Zeile zeigt die einzige Umwandlung, die auch strikt erlaubt bleibt: Eine ganze Zahl darf
an einen float-Parameter, und im Reiter Debug steht sie dort als z=9.0, also schon als
Kommazahl. Andersherum geht es nicht, auch nicht mit 10.0. Union-Typen wie array|false gibt es
ebenfalls, ein Strich zwischen zwei Typen heißt „das eine oder das andere”; der erste begegnet dir
in Lektion 7.4, erklärt wird er in 14.3.
Zum Mitnehmen
PHP verlangt nirgends, dass du hinschreibst, was für ein Wert in einer Variablen steckt. An Funktionen darfst du es trotzdem, und dort lohnt es sich wirklich. Ob daraus eine Empfehlung oder eine Zusage wird, entscheidet eine einzige Zeile am Dateianfang.
Jetzt du
Basis Konto, kostenlosZu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.
Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.
In diesem Kurs läuft dein Code auf einem Server. Dafür hat das Basis Konto 1 Stunde im Monat, mehr Zeit gibt es mit dem Premium Konto.
Was in dieser Lektion steckt
-
Artikel mit 5 Beispielen zum Ausprobieren
Steht hier, ohne Konto lesbar.
-
Aufgabe, dein Code läuft auf einem Server
Öffnet sich mit dem Basis Konto.