PHP/Probleme mit der Übertragung via URL

Aus Mikiwiki
< PHP
Wechseln zu: Navigation, Suche

Störende Escape-Zeichen

Werden die Daten in folgendem Beispiel um Anführungszeichen ergänzt, so zeigen sich versteckte Probleme.

<h3>Kodierung von Daten für den URL</h3>
<p>Senden Sie eine E-Mail!</p>
<?php
if (isset($_GET['email']))
{
  $email = $_GET['email'];
  echo stripslashes($email) . " wurde übertragen";
}
$email = "Jürg's E-Mail?";
$coded = urlencode($email);
$xx    = $coded;
echo <<<XLINKS
  <p><a href="{$_SERVER['PHP_SELF']}?email=$coded">
       Inhalt von <b>$email</b> übertragen?
     </a>
XLINKS;
?>

Kodierung von Daten für den URL

Senden Sie eine E-Mail!

Inhalt von Jürg's E-Mail? übertragen?

PHP hat in der Konfigurationsdatei "php.ini" im Abschnitt "[Data handling]" den folgenden Eintrag. In diesem Fall werden einfache und doppelte Anführungszeichen mit dem Escape-Zeichen (also "\", dem Backslash) versehen. Auch der Backslash selber wird so gekennzeichnet und verdoppelt sich dadurch ("\\").

magic_quotes_gpc = On

Die Zeichenfolge "Jörg's "E-Mail?"" sieht dann wie folgt aus.

Jörg\'s \"E-Mail?\"

Bei der Arbeit mit Datenbanken ist dieser Effekt unerwünscht, denn oft werden zeichenbasierte Daten mit Anführungszeichen umgeben. Für die Ausgabe in HTML stört das. Der Escape-Effekt muss also ausgeschaltet werden. Um die Funktion grundsätzlich nicht zu nutzen, kann sie in der Konfigurationsdatei "php.ini" deaktiviert werden.

magic_quotes_gpc = Off

Um die Ausgabe der Escape-Zeichen nur gelegentlich zu unterdrücken, kann die Funktion "stripslashes" eingesetzt werden, wie das auch im obigen Beispiel geschehen ist.

echo stripslashes($email) . " wurde übertragen";

Ein anderes Problem taucht auf, wenn Formularfelder und Variablen im URL mit demselben Namen verwendet werden. In solchen Fällen wird vorrangig der URL dekodiert. Es kann dennoch auf den Inhalt "beider" Variablen zugegriffen werden.

Arbeiten mit der Query-Zeichenkette

Um die übertragenen Daten selber zu analysieren, wird die in einem Superarray befindliche Servervariable "$_SERVER" genutzt. Im Zusammenhang mit "GET" ist der Zugriff folgendermassen möglich.

$_SERVER['QUERY_STRING']

Zum einen steht die Variable "$_SERVER['QUERY_STRING']" zur Verfügung, die den gesamten Teil des URL nach dem "?"-Zeichen enthält. Hier muss man sich zwar selber um die Analyse der einzelnen Elemente kümmern, man umgeht dafür aber die automatische Auswertung des PHP-Parsers. Da einem der Zugriff auf die Formularvariable verwehrt ist, bleibt auch hier die Nutzung der Servervariablen. Das folgende Beispiel zeigt die Anwendung und auch, wie der URL zur Datenübertragung mit einem Formular verwendet werden kann.

<?php
if (isset($_GET['sent']))
{
  echo "<p>Übertragen wurde sent = {$_GET['sent']}</p>\n";
}
if (isset($_SERVER['QUERY_STRING']))
{
  echo "<p>{$_SERVER['QUERY_STRING']}</p>\n";
}
if (is_array($_POST))
{
  while (list($key, $val) = each($_POST))
  {
    echo "<b>$key</b>: $val<br />\n";
  }
}
?>
<form action="<?=$_SERVER['PHP_SELF']?>?sent=yes" method="post">
<input type="hidden" name="sent" value="no">
<input type="submit">
</form>

Übertragen wurde sent = yes

sent=yes

sent: no

Interessant ist die Reaktion bei der Anwendung der Methode "GET" im Formular. In diesem Fall nehmen die Formularelemente den Platz der Daten im URL ein; die bereits im Attribut "action" gekennzeichneten Parameter werden nicht beachtet. Dieses Verhalten hat nichts mit PHP zu tun, sondern basiert auf HTTP und den Vorschriften zur Verarbeitung von Daten mit Hilfe der Methoden "GET" und "POST".

<form action="<?=$_SERVER['PHP_SELF']?>?sent=yes" method="post">
<input type="hidden" name="sent" value="no">
<input type="submit">

Übertragen wurde sent = no

sent=no

Beim Weiterreichen von Daten ist die Anwendung von "$QUERY_STRING" besonders bequem. Muss bei der Erstellung einer aus mehreren Skripten bestehenden Anwendung auf Cookies verzichtet werden, so ist eine "Verfolgung" der Nutzer unerlässlich. Es werden dann meist sogenannte Session-IDs verwendet - per Zufallsgenerator erzeugte Nummern oder Zeichenfolgen, die den Nutzer immer wieder eindeutig zuordnen.

Gleichlautende Variablen

Bei der automatischen Erzeugung von Variablen kann es vorkommen, dass mehrere gleichlautende Variablen unterschiedliche Werte enthalten. In diesem Fall extrahiert PHP nur die letzte Variable und den dazugehörigen Wert. Die Ausgabe von "echo $x" zeigt im vorliegenden Fall "3".

<a href=zielskript.php?x=1&x=2&x=3"Link</a>

Werden dagegen alle Daten angesehen, so ist zu erkennen, dass tatsächlich alle Daten übertragen wurden.

echo $_SERVER['QUERY_STRING'];

In diesem besonderen Fall müssen die Daten mit der Funktion "explode" dekodiert werden. "explode" zerlegt eine Zeichenkette anhand eines Trennzeichens in ein eindimensionales Array. Anschliessend erfolgt die nochmalige Trennung anhand des Gleichheitszeichens und (hier zu Demonstrationszwecken) die Ausgabe in einer "while"-Schleife. Dieses Vorgehen ist nicht sonderlich elegant - gleichnamige Variablen sollten wo immer möglich vermieden werden.

<?php
$pairs = array();
if (isset($_SERVER['QUERY_STRING']))
{
  $pairs = explode("&", $_SERVER['QUERY_STRING']);
}
$query = "";
for ($i = 0; $i < count($pairs); $i++) 
{
  $query[$i] = explode("=", $pairs[$i]);
}
if (is_array($query))
{
  while (list($key, $val) = each($query)) 
  {
    echo "Parameter: <b>$val[0] </b>: $val[1]<br />\n";
  }
}
?>
<p><a href="<?=$_SERVER['PHP_SELF']?>?x=1&x=2&x=3">Link mit ?x=1&amp;x=2&amp;x=3</a></p>

Parameter: x : 1
Parameter: x : 2
Parameter: x : 3

Link mit ?x=1&x=2&x=3

Unabhängigkeit vom Übertragungsweg

Manchmal ist eine Unterscheidung zwischen "GET" und "POST" nicht erwünscht, sondern nur das Auftreten eines Parameters entscheidend. Dann wird das Superarray "$_REQUEST" genutzt, das sowohl den Inhalt von "$_GET" als auch von "$_POST" enthält. Da die Befüllung der Arrays fast immer alternativ erfolgt - entweder / oder - bietet "$_REQUEST" in der Praxis einen etwas vereinfachten Zugriff.

Zur Benutzung der in "$_REQUEST" gespeicherten Variablen als globale Variablen wird die Funktion "import_requested_variables", die vorzugsweise am Anfang eines Skripts aufgerufen werden sollte.

Beherrschung langer Parameterschlangen

Müssen mit "GET" viele Parameter übergeben werden, so kann der entsprechende Befehl sehr unübersichtlich werden. Korrekturen oder Änderungen gestalten sich entsprechend schwierig. Ein nützlicher Trick ist die Bildung des URL mit der Anweisung "sprintf". Dazu wird erst eine Vorlage mit allen Variablen des URL gefertigt. Dann werden die Werte mit "sprintf" zugewiesen und später ausgegeben. Alternativ kann natürlich auch gleich "printf" verwendet werden oder - wenn die Parameter als Array vorliegen - "vprintf" bzw. "vsprintf". Mit der Funktion "urlencode" wird sichergestellt, dass jeder beliebige Inhalt einer Variablen übertragen wird.

<?php
$text_to_show = "Klick mich!";
$wert1 = 1;
$wert2 = 2;
$wert3 = 3;
$get   = "<a href=\"%s?wert1=%s&wert2=%s&wert3=%s\">%s</a>";
$openlink = sprintf($get, 
                    $_SERVER['PHP_SELF'],
                    urlencode($wert1), 
                    urlencode($wert2), 
                    urlencode($wert3),
                    $text_to_show);
echo $openlink;
echo "<br />";
echo htmlspecialchars($openlink);
?>

Klick mich!
<a href="/test/test.php?wert1=1&wert2=2&wert3=3">Klick mich!</a>

Bei sehr umfangreichen Variablensammlungen können auch Arrays eingesetzt werden. Dabei ist grundsätzlich zu beachten, dass die Webbrowser als maximale Länge des URL etwa 2'000 Zeichen zulassen. Dabei zählen ausser den Variablennamen auch der jeweilige Inhalt und die Trennzeichen mit.