hawkmaster: PDO Fragen, Sicherheit? Prepared Statements?

Hallo,
seit gestern lese ich nun einige Manuals und Code Beispiele zu PDO und habe auch selbst schon ein wenig ausprobiert.
Dennoch habe ich ein paar grundsätzliche Fragen.

1.
Oft sieht man im Code die Funktion getMessage()
echo $e->getMessage();
Ich habe nirgend einen Hinweis dazu gefunden. Ist das eine spezielle Methode von PDO oder eine allgemeine Funktion von PHP?

2.Prepared Statements
---------------------------------------------------------------
$stmt->bindValue(1,$_POST['plz1'],PDO::PARAM_STR);
$stmt->bindParam(':animal_id', $animal_id, PDO::PARAM_INT);
$stmt->bindParam(':animal_name', $animal_name, PDO::PARAM_STR, 5);
---------------------------------------------------------------

Warum sind hier die Konstanten angegeben bzw. was bewirken diese?

Was bedeutet die zahl 5 hinter "PDO::PARAM_STR, 5" ?

man könnte doch auch einfach den bind so machen, oder?
$dbInsertLog->bindParam('message', $strNachricht);

3.Sicherheit
Wird bei Prepared Statements automatisch auch gefiltert? Somit immer sicher gegen SQL Injection?
Beispiel:
Wäre das automatisch abgesichert?
------------------------------------------------------------------
$dbInsertLog = $objDb->prepare("INSERT INTO login (username, password) VALUES (:username, :pass)");
$dbInsertLog->bindParam('username', $_POST['username']);
$dbInsertLog->bindParam('pass', $_POST['pass']);
-----------------------------------------------------------

Wie wäre eine Lösung mit "quote()"?
Genauso sicher?
------------------------------------------------------
$dbh->exec("INSERT INTO REGISTRY (name, value)
VALUES (".$dbh->quote($name,PDO::PARAM_STR).", ".$dbh->quote($value,PDO::PARAM_INT).")");
-------------------------------------------------

4. Fehlerausgaben
Bisher habe ich immer "mysql_error() gearbeitet.

$sql = mysql_query("SELECT Config FROM directories WHERE Name = 'Directories'") or mysql_error();

Um bei PDO Fehler (z.b. flascher Spalten namen) ausgeben zu können, muß man hier immer mit "try" und "catch" arbeiten?
try {
...
dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
...
}
catch(PDOException $e)
    {
    echo $e->getMessage();
    }

oder kann man auch sowas machen:
$dbResult = $objDb->query("SELECT * FROM log") or print_r($dbh->errorInfo());

Vielen Dank für die Hilfe
Gruss
hawk

  1. echo $begrüßung;

    Oft sieht man im Code die Funktion getMessage()
    echo $e->getMessage();
    Ich habe nirgend einen Hinweis dazu gefunden. Ist das eine spezielle Methode von PDO oder eine allgemeine Funktion von PHP?

    Methoden gehören immer der Klasse an, von der der Teil vor dem -> ein Objekt ist (oder zurückliefert). In deinem Fall also der Klasse des Objekts $e. Wo $e herkommt siehst du ja in deinem Programmablauf. Wenn du dabei auf die Exceptions stößt, solltest du dir das Kapitel Exceptions ansehen, oder auch anderswo nach Sinn und Einsatzmöglichkeiten von Exceptions im Allgemeinen informieren.

    2.Prepared Statements
    $stmt->bindParam(':animal_name', $animal_name, PDO::PARAM_STR, 5);
    Warum sind hier die Konstanten angegeben bzw. was bewirken diese?

    Bestimmte Parameter verlangen genau definierte Werte. Man könnte diese als String übergeben, was aber aufwendiger auszuwerten ist, als bei einer Zahl. Ein Zahl hingegen ist nicht sprechend. Eine Konstante verbindet beides. Ihr Name ist sprechend, ihr Wert eine Zahl.

    Was bedeutet die zahl 5 hinter "PDO::PARAM_STR, 5" ?

    Die Frage nach dem Bewirken der Konstanten habe ich oben ausgelassen, denn ihre Antwort trifft im Prinzip auch hier zu. Die Parameter, die eine Funktion/Methode erwartet, sind im PHP-Handbuch beschrieben. Der 3. Parameter von PDOStatement::bindParam() gibt einen Typ an, der 4. eine Länge.

    man könnte doch auch einfach den bind so machen, oder?
    $dbInsertLog->bindParam('message', $strNachricht);

    Kann man, denn ab dem dritten Parameter sind sie optional. Es werden dann Default-Werte verwendet.

    Wird bei Prepared Statements automatisch auch gefiltert? Somit immer sicher gegen SQL Injection?

    Das ist nicht notwendig, falls direkt das Feature Prepared Statements eines DBMS verwendet werden kann. Das SQL-Statement und die Daten gehen auf getrennten Wegen zum Server. Es ist deshalb nicht notwendig, die Daten zum Transport über einen Befehl und Daten gleichzeitig enthaltenden String zu präparieren. Falls PDO im Hintergrund ein Statement zusammenbaut, die Prepared Statement-Funktionalität also nur simuliert wird, dann kümmert es sich um die ordnungsgemäße Behandlung der Werte.

    SQL-Injection ist also ausgeschlossen, solange nicht der Statement-Teil aus variablen Dingen zusammengebaut wird (oder PDO intern einen Fehler hat).

    Wie wäre eine Lösung mit "quote()"?
    Genauso sicher?

    $dbh->exec("INSERT INTO REGISTRY (name, value)
    VALUES (".$dbh->quote($name,PDO::PARAM_STR).", ".$dbh->quote($value,PDO::PARAM_INT).")");

    Anders sicher. Wenn du das Statement selbst zusammenbaust, musst du auch selbst dafür sorgen, dass alles richtig ist. Keine Einwände gegen das von dir angeführte Beispiel. Verbessern kann man (muss man aber nicht): Verwendung von sprintf() statt String-Rein-Raus, sieht übersichtlicher aus, finde ich. PDO::PARAM_STR ist der Defaultwert dieses optionalen Parameters, kann also weggelassen werden.

    1. Fehlerausgaben
      Um bei PDO Fehler (z.b. flascher Spalten namen) ausgeben zu können, muß man hier immer mit "try" und "catch" arbeiten?

    Muss man nicht. Das hab ich dir aber schon in einem anderen Posting gesagt, dass es da drei Einstellungen gibt, wie sich PDO im Fehlerfall verhalten soll. Je nach gewählter Art kannst/musst du nun Exceptions behandeln oder die Fehlercodes direkt abfragen.

    echo "$verabschiedung $name";

    1. Hallo dedlfix,
      recht herzlichen Dank für deine ausführlichen Erklärungen.
      Das hat mir ein wenig geholfen.

      alles weitere muss ich einfach mal testen und ausprobieren.

      vielen dank nochmals.
      Gruss
      hawk