dedlfix: Folgefrage

Beitrag lesen

echo $begrüßung;

Das sind Platzhalter, die die Funktion sprintf() auswertet und durch die nachfolgenden Parameterwerte ersetzt. Es ist im Prinzip nur eine andere Art, einen String aus festen und variablen Bestandteilen zusammenzusetzen. In meinen Augen jedoch eine übersichtlichere, weil das SQL-Statement vollständig, in einem Teil notiert ist (wenn auch mit Platzhaltern statt Werten) und nicht ständig durch Stringende-Stringverknüpfung-Stringanfang unterbrochen wird.

Es tut mir leid, ich habe _keine Ahnung_, wovon Du sprichst. =(
Gibts die Erklärung auch für Dummys, so wie mich?

So ein SQL-Statement ist eine Mischung aus einem festen Anteil und variablen Werten. Letztere kommen aus deiner Eingabe und müssen in das SQL-Statement eingearbeitet werden.

Am Ende möchtest du beispielsweise

INSERT INTO tabelle (feld) VALUES ("wert")

haben. Du hast da die drei Teile

INSERT INTO tabelle (feld) VALUES ("
  wert
  ")

die zusammengesetzt werden müssen. Eine einfache Methode ist die Verknüpfung von Strings:

$sql = 'INSERT INTO tabelle (feld) VALUES ("' . $wert . '")';

Nun muss aber auch noch berücksichtigt werden, dass bestimmte Zeichen eine besondere Bedeutung haben. Nachdem mit " ein String eingeleitet wurde, beendet ein weiteres " den String wieder. Kommt so ein " im Eingabewert vor, wird der nicht als Eingabe sondern als Stringende interpretiert. Die Folge ist bestenfalls ein Syntaxfehler. Aus diesem Grunde ist ein " als " zu notieren, dann erkennt der SQL-Server es als Datenbestandteil und nicht als Stringende an. Darum und um noch ein paar andere zu beachtende Zeichen kümmert sich die Funktion mysql_real_escape_string(). Der String wird nun also so gebildet:

$sql = 'INSERT INTO tabelle (feld) VALUES ("' . mysql_real_escape_string($wert) . '")';

Nun hast du hier einen Stringteil, dann einen PHP-Funktionsaufruf und am Ende noch ein Stück String. Dieses Beispiel hat nur einen variablen Wert. Wenn noch mehr dazukommen, wird diese Methode schnell unübersichtlich, weil immer mehr Stringverknüpfungen notiert werden müssen.

$sql = 'INSERT INTO tabelle (feld1, feld2) VALUES ("' . mysql_real_escape_string($wert1) . '", "' . mysql_real_escape_string($wert2) . '")';

Die Funktion sprintf() kann hier abhelfen. Eigentlich kann sie noch viel mehr, beispielsweise Zahlen zum Zwecke der Ausgabe formatieren, doch wir verwenden sie hier nur auf eine recht einfache Weise. Statt der variablen Werte wird der Platzhalter %s notiert. Der erste Parameter der Funktion sprintf() ist der String mit den Platzhaltern. Nun folgen genauso viele Argumente, wie im ersten String Platzhalter vorhanden sind. sprinf() fügt diese der Reihe nach bei den einzelnen Platzhaltern ein.

  $sql = sprintf('INSERT INTO tabelle (feld1, feld2) VALUES ("%s", "%s")',  
    mysql_real_escape_string($wert1),  
    mysql_real_escape_string($wert2));

So hat man das SQL-Statement am Stück stehen und es nicht ständig von Stringoperationen unterbrochen.

Wenn du wissen willst, was sprintf() nun fabriziert hat, machst du eine Kontrollausgabe. Das macht man immer dann, wenn irgendwo ein anderes Verhalten auftritt, als man erwartet hat, um sich zu überzeugen, dass die verwendeten Funktionen das Ergebnis bringen, das man sich vorgestellt hat.

echo $sql;

Es kommt KEINE Fehlermeldung, allerdings werden die Datensätze nicht eingetragen. Woran _das_ liegt, verstehe ich auch nicht.

Die mysql_*-Funktionen haben die Angewohnheit im Stillen zu operieren. Wenn ein Fehler aufgetreten ist, melden sie das durch ihren Rückgabewert. Diesen musst du stets auswerten und dann darauf reagieren. Der Rückgabewert ist im Fehlerfall ein false, im Gutfall eine Ressourcenkennung. Gibst du nun einfach das false unbehandelt an die nachfolgende mysql_*-Funktion weiter, beschwert sich PHP mit dem berühmt-berüchtigten "supplied argument is not a valid MySQL result resource", weil false eben keine Ressourcenkennung ist. Doch das ist eher beim Abfragen das Problem, weil man da das Ergebnis von mysql_query() braucht, um die Datensätze abfragen zu können. Bei dir tut sich einfach nur nichts offensichtliches.

Eine mögliche Vorgehensweise ist:

  if (! $connection = mysql_connect(...)) {  
    // Tut mir leid lieber Anwender, die Daten stehen grad nicht zur Verfügung. Bitte später nochmal probieren.  
    // echo mysql_error();  
  } else {  
    if (! $result = mysql_query($sql, $connection)) {  
      // Fehler aufgetreten. Anwender vertrösten.  
      // echo mysql_error();  
    } else {  
      // alles i.O.  
      // mach was mit dem Ergebnis. z.b. Abfragen  
    }  
  }

Das echo mysql_error(); ist für Debuggingzwecke gut geeignet. Im produktiven Einsatz sollte man den Anwender nicht mit diesen technischen Details belästigen. Den Fehler sollte man anderweitig an den Administrator melden, z.B. Logfiles oder eine Mail senden.

// Die Verbindung zur Datenbank wird hergestellt.
    if(get_magic_quotes_gpc())
     {
      $vorname=stripslashes($_POST["vorname"]);
      $familienname=stripslashes($_POST["familienname"]);
      // Wenn "get_magic_quotes_gpc" auf ON eingestellt ist, dann wird die automatische Maskierung entfernt.
     }
    else
     {
      $vorname=$_POST["vorname"];
      $familienname=$_POST["familienname"];
      // Wenn "get_magic_quotes_gpc" auf OFF eingestellt ist, dann werden die nicht automatisch maskierten Einträge übernommen.
     }

PHP kennt ein Feature namens Magic Quotes. Das macht das, was wir oben mit dem mysql_real_escape_string() gemacht haben automatisch mit sämtlichen Eingabedaten. Und das ist nicht gut. Diese Daten werden ja nicht in jedem Fall an eine Datenbank übergeben. Besonders bei der Affenformulartechnik drehen die Daten erstmal ein paar Runden zwischen Anwender und PHP, ohne dass dabei eine Datenbank im Spiel ist. Doch die Magic Quotes wirken bei jeder Runde und stören nur.

Mit obigem Code erstellst du neue Variablen aus den Eingabewerten. Wenn M.Q. aktiviert sind, machst du dessen Auswirkungen rückgängig. Soweit so gut. Doch dieses Stück Code ist genau auf deine beiden derzeitigen Werte zugeschnitten. Wenn noch einer hinzukommt, musst du für alle Verzweigungen die gleiche Behandlung hinzufügen, nur mit anderen Variablennamen. Besser ist es, statt Einzelbehandlung und neuen Variablen eine generelle Behandlung vorzunehmen und die bereits bestehenden Strukturen ($_GET/$_POST) weiterzuverwenden. Das hat auch noch den Vorteil, dass man im weiteren Verlauf des Scripts anhand eines $_POST['vorname'] im Gegensatz zu $vorname sofort ansieht, dass die Daten vom Benutzer kommen (und ungeprüfte Werte enthalten).

Im Kapitel Disabling Magic Quotes findest du ein Stück Code, das am Scriptanfang eingebunden werden kann und sollte, und das die M.Q. direkt in den $_POST- usw. -Arrays entfernt. Wenn dann irgendwann PHP6 erschienen ist, und M.Q. endgültig gestorben sind, muss nur noch dieses Stück entfernt werden, und weiter läuft dein Script, ohne weitere Umbauarbeiten.

Leider krankt diese Tutorialseite an den altbekannten Anfängerunsitten und -fehlern. Zum einen ist da das übliche unsinnige Umkopieren der Eingabewerte in andere Variablen enthalten, und zum anderen fehlt die kontextgerechte Behandlung der Werte, die unter anderem auch dem Schutz gegenüber SQL-Injection dient.
Schade, das war eines der wenigen Dinge, die ich verstanden habe. *seufz*

Vielleicht weißt du ja jetzt, was dort und warum beanstandenswert ist.

echo "$verabschiedung $name";