mitmario.dev

Werte aus der Adresse

PHP Sandbox 4 Min Lesezeit 3 BeispieleLektion 3 von 7

Eine Adresse kann mehr sein als ein Pfad. Hängt ein Fragezeichen daran, folgt eine Liste aus Schlüsseln und Werten, verbunden mit &. Aus /suche?ware=Kaffee&menge=3 liest PHP zwei Werte heraus und legt sie dir hin.

Das Array heißt $_GET

Was hinter dem Fragezeichen ankommt
<?php

// Alles hinter dem Fragezeichen landet in $_GET. Probier im Browser
// beide Links, und tipp danach selbst etwas in die Adresszeile.

echo "<!doctype html>\n";
echo "<html lang=\"de\">\n";
echo "<head><meta charset=\"utf-8\"><title>Adresse</title></head>\n";
echo "<body>\n";
echo "<h1>Was in \$_GET steht</h1>\n";
echo "<p>Angefragt: " . $_SERVER["REQUEST_URI"] . "</p>\n";

if ($_GET === []) {
    echo "<p>Nichts. An der Adresse haengt kein Fragezeichen.</p>\n";
} else {
    echo "<ul>\n";
    foreach ($_GET as $schluessel => $wert) {
        echo "  <li>$schluessel = $wert, Typ: " . get_debug_type($wert) . "</li>\n";
    }
    echo "</ul>\n";
}

echo "<p><a href=\"/?ware=Kaffee&amp;menge=3\">Mit zwei Werten</a> | ";
echo "<a href=\"/\">ganz ohne</a></p>\n";
echo "</body>\n";
echo "</html>\n";

$_GET ist ein ganz normales Array, du kannst es also mit allem anfassen, was du in Abschnitt 5 gelernt hast: foreach darüber laufen lassen, count() zählen, einzelne Schlüssel abfragen. Der Unterschied zu deinen eigenen Arrays ist nur, wo es herkommt: PHP füllt es, bevor deine erste Zeile läuft.

Und es heißt so, weil es zur Methode GET gehört. In Abschnitt 11 kommt $_POST dazu, für das, was ein Formular hinschickt. Der Aufbau ist derselbe.

Sieh dir im Beispiel die Typangabe hinter den Werten an. Da steht bei beiden string, auch bei der Menge. Alles, was aus der Adresse kommt, ist Text, denn eine Adresse ist Text. Wer damit rechnen will, wandelt vorher um: Eine Typangabe an einer Funktion erledigt das für dich (Lektion 6.2), und sonst schreibt man (int) vor den Wert.

Das ist keine Formsache, sondern der Unterschied zwischen einer Seite, die läuft, und einer, die abstürzt. "3" + 1 ergibt brav 4. "drei" + 1 bricht mit einem TypeError ab. Und "12,50" + 1 ergibt 13 plus eine Warnung, weil PHP am Komma aufhört zu lesen. Was in der Adresse steht, bestimmst nicht du.

Ein Parameter, der fehlen darf

Fehlt oder ist leer
<?php

$rohwert = $_GET["name"] ?? null;
$mitDoppelfrage = $_GET["name"] ?? "Gast";
$mitKurzform = ($_GET["name"] ?? "") ?: "Gast";

?>
<!doctype html>
<html lang="de">
<head><meta charset="utf-8"><title>Fehlt oder leer</title></head>
<body>
    <h1>Fehlt oder ist leer</h1>
    <p>Angefragt: <?= htmlspecialchars($_SERVER["REQUEST_URI"]) ?></p>
    <ul>
        <li>isset: <?= isset($_GET["name"]) ? "ja" : "nein" ?></li>
        <li>Rohwert: <?= var_export($rohwert, true) ?></li>
        <li>Mit ?? gefuellt: "<?= $mitDoppelfrage ?>"</li>
        <li>Mit ?: gefuellt: "<?= $mitKurzform ?>"</li>
    </ul>
    <p>
        <a href="/">ohne Parameter</a> |
        <a href="/?name=">leerer Parameter</a> |
        <a href="/?name=Mia">mit Wert</a>
    </p>
</body>
</html>

Niemand zwingt einen Besucher, deine Adresse vollständig einzutippen. Fragst du einen Schlüssel ab, den es nicht gibt, meldet PHP Undefined array key und liefert null. Die Meldung steht dabei mitten auf deiner Seite, denn der Server in diesem Kurs zeigt Fehler dort an, wo sie passieren (warum, steht in Lektion 10.4), und beim Prüfen zusätzlich im Terminal auf dem Fehlerkanal. Deine Seite läuft trotzdem weiter und zeigt Unsinn, und das ist genau die gefährliche Sorte Warnung aus Lektion 1.4.

Der Doppelfragezeichen-Operator aus Lektion 5.2 löst den Fall in einem Zeichen: $_GET["name"] ?? "Gast" liefert den Wert, falls er da ist, und sonst den Ersatz.

Nur reicht das oft nicht, und das Beispiel zeigt warum. Klick dich im Browser durch die drei Links und achte auf die vierte Zeile. Bei /?name= existiert der Schlüssel, sein Wert ist nur die leere Zeichenkette. ?? greift deshalb nicht, es fragt nach dem Vorhandensein und nicht nach dem Inhalt. Heraus kommt eine Begrüßung ohne Namen.

Dafür gibt es die Kurzform des Fragezeichen-Operators aus Lektion 4.1: $wert ?: "Gast" nimmt den Ersatz, sobald der Wert als falsch gilt, und dazu gehört die leere Zeichenkette (Lektion 2.5). Zusammen ergibt das die Form, die du im Rest des Kurses immer wieder sehen wirst: erst ?? gegen den fehlenden Schlüssel, dann ?: gegen den leeren Wert.

Aufpassen musst du dabei nur an einer Stelle: Für PHP ist auch die Zeichenkette "0" falsch. Wo eine Null ein gültiger Wert wäre, ist ?: also die falsche Wahl, und man fragt lieber ausdrücklich mit trim($wert) === "".

Was ankommt, ist fremder Text

Roh eingesetzt und entschärft
<?php

$text = $_GET["text"] ?? "<b>fett</b> und <em>schief</em>";

?>
<!doctype html>
<html lang="de">
<head><meta charset="utf-8"><title>Roh und entschaerft</title></head>
<body>
    <h1>Derselbe Text, zweimal eingesetzt</h1>
    <p>Roh eingesetzt: <?= $text ?></p>
    <p>Entschaerft: <?= htmlspecialchars($text) ?></p>
    <p>
        <a href="/?text=Kaffee">harmlos</a> |
        <a href="/?text=%3Cb%3Efett%3C%2Fb%3E">mit Markup</a>
    </p>
</body>
</html>

Und jetzt die Sache, die man einmal gesehen haben muss. Klick im Browser auf den Link mit dem Markup. In der ersten Zeile ist das Wort wirklich fett, in der zweiten stehen die spitzen Klammern als Zeichen da.

Der Unterschied ist eine Funktion. htmlspecialchars() ersetzt die fünf Zeichen, die in HTML eine Bedeutung haben, durch ihre Ersatzschreibweise: Aus < wird &lt;, aus & wird &amp; und so weiter. Der Browser zeigt sie dann an, statt sie auszuführen.

In der ersten Zeile hat der Besucher deiner Seite Markup untergeschoben. Bei <b> ist das lustig. Mit einem <script>-Element ist es das nicht mehr, denn dann läuft fremder Code im Browser deiner Besucher, und zwar so, als käme er von dir. Der Angriff heißt XSS, er ist der häufigste im ganzen Netz, und Abschnitt 15 nimmt ihn auseinander.

Bis dahin reicht eine Regel, und sie gilt ohne Ausnahme: Was von außen kommt, geht nie roh in deine Seite. Nicht aus $_GET, ab Abschnitt 11 nicht aus $_POST, ab Abschnitt 14 nicht aus der Datenbank. Wenn du dir eine einzige Gewohnheit aus diesem Kurs mitnimmst, dann diese.

Warum man Werten auch inhaltlich nicht traut

htmlspecialchars sorgt dafür, dass ein Wert deine Seite nicht kaputtmacht. Es sagt nichts darüber, ob der Wert stimmt.

In der Adresse steht, was jemand hineinschreibt. Eine Seitennummer kann -4 sein, eine Menge 999999, eine Artikelnummer die eines fremden Kunden. Ein Formular im Browser schützt dich davor nicht, denn die Adresse lässt sich von Hand ändern, und genau das macht auch jeder, der es einmal gemerkt hat.

Prüfen musst du also selbst: Ist der Wert überhaupt da, ist er die erwartete Art, liegt er im erlaubten Bereich, und darf dieser Besucher ihn sehen. Wie das aussieht, steht in Lektion 11.2, und richtig ernst wird es in Abschnitt 15.

Zum Mitnehmen

Alles hinter dem Fragezeichen einer Adresse landet bei dir in einem Array. Damit hört deine Seite auf, für alle dasselbe zu zeigen. Und damit fängt zugleich der Teil an, in dem du niemandem mehr glauben darfst.

Jetzt du

Basis Konto, kostenlos

Zu 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 3 Beispielen zum Ausprobieren

    Steht hier, ohne Konto lesbar.

  • Aufgabe, dein Code läuft auf einem Server

    Öffnet sich mit dem Basis Konto.