Flash: PDO Unklarheiten

Hallo Leute, ich beschäftige mich seit kurzem mit der PDO Klasse und finde sie eigentlich recht toll es funktioniert auch schon fast alles damit.
Leider habe ich ein paar Fragen bezüglich dieser Klasse die mit Google leider nicht beantworten konnte.

Zurste habe ich meine eigene Klasse erstellt:

  
class ePDO extends PDO  
{  
    public function __construct($host, $database, $user, $password)  
    {  
        parent::__construct('mysql:host=' . $host .';dbname='. $database . '', $user, $password);  
  
        $this->setAttribute(PDO::ATTR_PERSISTENT, true);  
        $this->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);  
        $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);  
    }  
}  

Sie dient mir rein dazu um die Einstellungen von PDO zu setzen.

Nun habe ich 2 Codes:
(Datenbankverbindung wurde bereits geöffnet) $this->ePdo = new ePDO(

  
$sql = 'select fisch from Meer';  
try {  
  $records = $this->ePdo->query($sql)->fetchAll();  
}  
catch (PDOException $e) {  
  print "Error!: " . $e->getMessage() . "<br/>";  
  die();  
}  
  
print_r($records);  

und mit prepare:

  
$sql = 'select fisch from Meer';  
try {  
  $SelStmt = $this->ePdo->prepare($sql);  
  
  $SelStmt->execute();  
  $records = $SelStmt->fetchAll();  
  $SelStmt->closeCursor();  
}  
catch (PDOException $e) {  
  print "Error!: " . $e->getMessage() . "<br/>";  
  die();  
}  

Nun meine Fragen:

1.) Macht es Sinn überall einen Try Catch Block zu verwenden? Auch bei query Abfragen?
2.) Wenn ich einen Fehler einbaue z.B 'selectttt fisch from Meer' dann bekomme ich keinen Fehler ausgegeben, aber der catch Block wird aufgerufen, warum?
3.) Hat die query Abfrage irgendwelche Nachteile gegenüber der prepare abfrage? Welche Abfrage macht mehr Sinn? (Im Einfachen Modus, wo nichts übergeben wird) Ich hab mal gehört das fehler nur im Prepare Modus geworfen werden.
4.) Macht es Sinn eine eigene Pdo Klasse zu machen wie ich es gemacht hab, oder geht das einfacher mit den Einstellungen?
5.) $SelStmt->closeCursor(); muss man den immer am Ende schließen, auch bei query Abfragen?
6.) $this->setAttribute(PDO::ATTR_PERSISTENT, true); was brint die Einstellung, immer steht in Google die soll man machen.
7.) Wenn ich eine Varibale einbinde mit:
$UpdStmt->bindParam(':pBetrag', $Betrag, PDO::PARAM_INT);
Hier nehme ich INT, aber int sind doch nur ganze Zahlen, was mache ich bei Kommastellen oder ganz großen Beträgen? Double gibt es ja nicht.

Dann waren somit mal meine Fragen und bedanke mich schon mal im Vorhinein auf die Antworten.

lg Flash

  1. Hi!

    1.) Macht es Sinn überall einen Try Catch Block zu verwenden? Auch bei query Abfragen?

    Auch bei einer Query kann ein Fehler auftreten. Das können zum Beispiel Syntaxfehler oder ein Abbruch der Verbindung sein. Es ist also sinnvoll, wenn du auf Fehler eingehen willst. Wenn du sie einfach so dem Benutzer vor die Füße werfen willst und/oder das Script in einem undefinierten Zustand weiterlaufen lassen willst, ergibt es natürlich keinen Sinn, auf sie zu reagieren.

    2.) Wenn ich einen Fehler einbaue z.B 'selectttt fisch from Meer' dann bekomme ich keinen Fehler ausgegeben, aber der catch Block wird aufgerufen, warum?

    Bitte informiere dich über die Grundlagen des Exception-Handlings. Exceptions innerhalb des try-Blocks geworfen, können im catch-Teil ausgewertet werden.

    3.) Hat die query Abfrage irgendwelche Nachteile gegenüber der prepare abfrage? Welche Abfrage macht mehr Sinn? (Im Einfachen Modus, wo nichts übergeben wird)

    Welche Eigenschaften haben denn die normale Abfrage und Prepared Statements, auch in Bezug auf zu übergebende Werte. In welchen Fällen braucht man diese Eigenschaften und wann nicht? Was kann man mit einem PS nachdem es prepared wurde anstellen und wie oft muss man eine herkömmliche Query zum Server senden, wenn man sie mehrfach ausführen will? Was muss der Server machen, wenn er eine herkömmliche Query abarbeiten will und was kann er sich schenken, wenn er ein Prepare und mehrere Executes zu erledigen hat?

    Ich hab mal gehört das fehler nur im Prepare Modus geworfen werden.

    Das PHP-Handbuch hat im PDO-Teil auch ein Kapitel zur Fehlerbehandlung.

    4.) Macht es Sinn eine eigene Pdo Klasse zu machen wie ich es gemacht hab, oder geht das einfacher mit den Einstellungen?

    Du kannst einen Connection-String (DSN) auch anderweitig zusammenbauen und an die bereits vorhandene PDO-Klasse übergeben. Es ist deine Entscheidung, was dir besser gefällt.

    5.) $SelStmt->closeCursor(); muss man den immer am Ende schließen, auch bei query Abfragen?

    Was sagt das Handbuch dazu? Was passiert im Allgemeinen mit Ressourcen am Ende eines PHP-Scripts? Hast du Not mit den Ressourcen und willst während der Script-Laufzeit welche freigeben? Schreibst du eine Bibliothek, von der du nicht weißt, ob sie bei ihren Einsetzen möglichst ressourcenschonend arbeiten muss?

    6.) $this->setAttribute(PDO::ATTR_PERSISTENT, true); was brint die Einstellung, immer steht in Google die soll man machen.

    Welches setAttribute meinst du? $this kann alles mögliche enthalten und PDO kennt zwei Klassen mit dieser Methode. Die generische Form, Methoden zu benennen ist: Klassenname::Methodenname, also PDO::setAttribute() oder PDOStatement::setAttribute().

    Was sagt das Handbuch zu ihrer Funktionsweise? Welcher Begründung steht "in Google"? Was wird generell an Eigenschaften und zu beachtenden Dingen bei persistenten Verbindungen genannt? Insbesondere, mit welcher PHP-Einbindung (Modul vs. CGI) können sie verwendet werden?

    7.) Wenn ich eine Varibale einbinde mit:
    $UpdStmt->bindParam(':pBetrag', $Betrag, PDO::PARAM_INT);
    Hier nehme ich INT, aber int sind doch nur ganze Zahlen, was mache ich bei Kommastellen oder ganz großen Beträgen? Double gibt es ja nicht.

    Das liegt vielleicht daran, dass gebrochene Zahlen nicht in allen Systemen zur Verfügung stehen. Wer weiß. Man kann zumindest für MySQL Zahlen auch wie Strings übergeben.

    Lo!

    1. Hallo!
      Erstmals danke für deine Antworten, leider bin ich noch nicht ganz schlau daraus geworden:

      Punkt 2:
      Normal sollte die Fehlermeldung ja in $e->getMessage stehen oder? Oder muss ich da $SelStmt->eroorInfo() das array nehmen? Versteh nur nicht warum keine Message augegeben wird. Im PHP Handbuch steht bei den Fehlerbehandlungen nur die PDO einstellungen.

      Punkt 3:
      Ich mache es nun einfach so:
      Bei select bei denen ich bei where nichts übergeben muss nehme ich query und sonnst hat prepare Statements für die bessere Escapung :-)

      Punkt 5:
      Ok habs verstanden
      $SelStmt->closeCursor(); braucht man wenn man prepare Statements hat um Resourcen zu bereinigen.

      Punkt 6: gefunden
      Der Cache an persistenten Verbindungen erlaubt Ihnen, den Overhead zu vermeiden, wenn jedesmal eine neue Verbindung geöffnet wird, sobald ein Skript mit der Datenbank kommunizieren muss, was sich in einer schnelleren Anwendung widerspiegelt

      Ich denke ich bin mir dadurch etwas im Klareren.

      lg Flash

      1. Hi!

        Normal sollte die Fehlermeldung ja in $e->getMessage stehen oder? Oder muss ich da $SelStmt->eroorInfo() das array nehmen? Versteh nur nicht warum keine Message augegeben wird. Im PHP Handbuch steht bei den Fehlerbehandlungen nur die PDO einstellungen.

        PDO arbeitet in drei Error-Modi, wie das Handbuch sagt. Im Modus PDO::ERRMODE_EXCEPTION wird zusätzlich eine Exception mit ausgefüllten Feldern geworfen. Der Fehlercode sollte also in der Exception und mit den error*-Methoden abfragbar sein. Wenn du mit Exceptions arbeitest, solltest du nur die Exception nach den Fehlerumständen befragen. Dass die PDO-Klassen Fehlermeldungskomponenten enthalten ist dem Fakt geschuldet, dass man auch ohne Exceptions arbeiten können soll. Aus OOP-Sicht würde ich es aber nicht als besonders sauber bezeichnen, bei einer geworfenen Exception etwas anderes als das Exception-Objekt zu befragen. Exceptions können quasi an beliebigen Stellen gefangen werden und diese Stelle muss einerseits kein Wissen um den Code an der Fehlerstelle und die dortigen Variablen haben, andererseits kann der fehlererzeugende Code und das Exception-Handling auch in unterschiedlichen Scopes angesiedelt sein, so dass aus dem Catch-Block gar nicht direkt auf die interessanten Variablen zugegriffen werden kann.

        Der Cache an persistenten Verbindungen erlaubt Ihnen, den Overhead zu vermeiden, wenn jedesmal eine neue Verbindung geöffnet wird, sobald ein Skript mit der Datenbank kommunizieren muss, was sich in einer schnelleren Anwendung widerspiegelt

        Ja, das ist der versprochene Vorteil. Aber der Cache kann sich in einem CGI-Programm, dass aufgerufen und nach dem Request wieder beendet wird, nicht halten, weswegen im CGI-Modus keine persistenten Verbindungen möglich sind. Und dann solltest du genau anschauen, wie sich die Anzahl der offenen Verbindungen auf dem MySQL-Server verhält, wenn du das Script ein paar mal startest. Weiterhin solltest du nicht nur die Lobeshymnen sondern auch die Kritiken zu persistenten Verbindungen suchen, beispielsweise hier im Forum mit dem Autor Sven Rautenberg.

        Lo!

        1. Moin!

          Weiterhin solltest du nicht nur die Lobeshymnen sondern auch die Kritiken zu persistenten Verbindungen suchen, beispielsweise hier im Forum mit dem Autor Sven Rautenberg.

          Das hab ich gelesen! :)

          Persistente Connections zur Datenbank zu eröffnen ist in aller Regel nicht empfehlenswert. Der eventuell versprochene Performancegewinn ist so gering, die damit eingehandelten Probleme hingegen sind enorm.

          Zum ersten: Sie funktionieren nur, wenn PHP als Apache-Modul arbeitet.

          Zum zweiten: Pro Apache-Thread wird genau eine persistente Connection eröffnet, die nicht wieder geschlossen wird. Gut ausgelastete Server starten aber schon gerne mal zweihundert Threads, also sind gleichzeitig auch 200 Connections zur Datenbank aktiv ... aber nur, wenn die DB auch diese Anzahl an Connections erlaubt.

          Das Problem, dass die DB keine neuen Connections mehr erlaubt, hat man natürlich auch dann, wenn man keine persistenten Connections benutzt und 200 parallele Requests zu verarbeiten hat. Aber wenn der 201. Request eine DB-Connection starten will, wird er mit der DB Kontakt aufnehmen und eine Zeit lang versuchen, die Verbindung herzustellen. In der Zwischenzeit sind andere Skripte fertig abgearbeitet. Wenn die jetzt ihre Connection schließen und freigeben, kann der 201. Request doch noch eine DB-Connection herstellen. Mit persistenten Connections würde das erst passieren, wenn der Apache den Thread beendet, weil er nicht mehr gebraucht wird.

          Nicht-persistente Connections passen sich also viel besser den tatsächlichen Bedürfnissen der Requests an, denn es werden nur die hergestellt, die tatsächlich benötigt werden, und sie werden auch recht schnell wieder geschlossen, um die Ressourcen der Datenbank für x-beliebige andere Zwecke freizugeben.

          Erst wenn man eine total kontrollierbare Hosting-Umgebung administriert (also sowohl Datenbank als auch Webserver), und durch Performance-Messung bewiesen hat, dass persistente Connections einen Vorteil bieten, und sich bei der Konfiguration von maximalen Threads und maximalen Connections in der DB sicher ist, dass es zu keinen Aussperrungseffekten kommen kann, kann man sie in Erwägung ziehen.

          Üblicherweise sind andere performance-steigernde Maßnahmen aber wirksamer und leichter erreichbar.

          - Sven Rautenberg

          1. Vielen Dank für eure Antworten werde die Persistente Connections sein lassen :-)

            lg flash