Stefan: PDO: Wo fange ich den Fehler ab?

Hallo,

wenn ich normalerweise z.b. bei einem Insert Statement den Fehler abfange, mache ich das über:

  
if (!$result)  
{  
     fehler($statement);  
}  

Wo kann ich meine Funktion "fehler" bei einem Prepared Statement einbringen?

  
$abfrage="insert into tabelle ( ID,ID2,ID3,Del )  
VALUES (?, ?, ?, ?)  
WHERE ID = ".kontextwechsel_beachten($id,int)."";  
$stmt = $dbh->prepare($abfrage);  
while ($row_aus_anderer_abfrage = $result_aus_anderer_abfrage->fetch()) {  
$stmt->execute(NULL,$last_insert_id,$row_aus_anderer_abfrage[0],$row_aus_anderer_abfrage[1]);  
}  

Wenn dieser Insert einen Fehler produziert, wie fange ich diesen ab und mache was damit?

Stefan

  1. Tach!

    Wo kann ich meine Funktion "fehler" bei einem Prepared Statement einbringen?

    Die Frage ist, ob man überhaupt eine Universalfunktion haben möchte, oder ob man nicht lieber individuell entscheiden möchte, was dem Anwender bei einem Fehler als Alternative vorgesetzt wird.

    $abfrage="insert into tabelle ( ID,ID2,ID3,Del )
    VALUES (?, ?, ?, ?)
    WHERE ID = ".kontextwechsel_beachten($id,int)."";

    Ein Insert hat keine Where-Klausel. Und wenn du schon mit Prepared Statements arbeitest, dann wäre es angebracht, es vollständig zu tun, nicht teils mit Platzhaltern und teils herkömmlich zusammengefummelt.

    $stmt = $dbh->prepare($abfrage);

    An dieser Stelle kann ein Fehler auftreten.

    $stmt->execute(NULL,$last_insert_id,$row_aus_anderer_abfrage[0],$row_aus_anderer_abfrage[1]);

    An dieser Stelle auch.

    Wenn dieser Insert einen Fehler produziert, wie fange ich diesen ab und mache was damit?

    Bei PDO kann man eine von drei Arten der Fehlermeldungen einstellen, Silent, Warning und Exception. Ich würde vermutlich in dem Fall zu Exception greifen und alles in den try-Block setzen, wenn keine Individualbehandlung von Prepare und Execute notwendig ist.

    dedlfix.

    1. Hi,

      Ein Insert hat keine Where-Klausel.

      Copy+Paste-Fehler aus zusammengestzten Codeteilen ;-)

      Wenn dieser Insert einen Fehler produziert, wie fange ich diesen ab und mache was damit?

      Bei PDO kann man eine von drei Arten der Fehlermeldungen einstellen, Silent, Warning und Exception. Ich würde vermutlich in dem Fall zu Exception greifen und alles in den try-Block setzen, wenn keine Individualbehandlung von Prepare und Execute notwendig ist.

      Wo würde denn ein "schlichter" SQL Error 1064 oder 1054 auftreten? Im Prepare Teil oder im Execute Teil?
      Und muß man das mit catch und try realisieren oder gibt es andere Möglichkeiten?

      Stefan

      1. Hallo,

        Wo würde denn ein "schlichter" SQL Error 1064 oder 1054 auftreten? Im Prepare Teil oder im Execute Teil?

        Im Exec Teil.

        Und muß man das mit catch und try realisieren oder gibt es andere Möglichkeiten?

        Ja, das wäre das Beste: Etwa so:

        $dbInsertlanguageid = $DBO->prepare("INSERT INTO language (typeid,languageid) VALUES (:typeid,:languageid)");
        $dbInsertlanguageid->bindParam(':typeid', $typeid);
        $dbInsertlanguageid->bindParam(':languageid', $languageid);

        try {  
        	$dbInsertlanguageid->execute();  
        } catch (PDOException $e) {  
        	showsqlerrorbox($e);  
        	return "SQLERROR";  
        }  
        

        viele Grüße
        hawk

        1. Ja, das wäre das Beste: Etwa so:

          "Das Beste" ist stetes eine mutige Aussage, weil es IMMER was zu verbessern gibt.

          ## config  
          define('DEBUG', false);  
          define('SQL_ERROR_TO_SAPI_ERRORLOG', true);  
            
            
          $dbInsertlanguageid = $DBO->prepare("INSERT INTO language (typeid,languageid) VALUES (:typeid,:languageid)");  
          	$dbInsertlanguageid->bindParam(':typeid', $typeid);  
          	$dbInsertlanguageid->bindParam(':languageid', $languageid);  
          	  
          	try {  
          		$dbInsertlanguageid->execute();  
          	} catch (PDOException $e) {  
          		if (DEBUG) { showsqlerrorbox($e) };  
          		if (SQL_ERROR_TO_SAPI_ERRORLOG) { error_log ($e, 4) };  
          		return "SQLERROR";  
          	}  
          
          

          Und pass auf, gleich kommt jemand und macht es - unbestreitbar - noch besser.

          Jörg Reinholz

          1. Und pass auf, gleich kommt jemand und macht es - unbestreitbar - noch besser.

            Hi Jörg,

            nein, gleich kommt jemand, der erklärt haben möchte, was an Deiner Lösung noch besser ist?

            Ich nämlich.

            Stefan

            1. Und pass auf, gleich kommt jemand und macht es - unbestreitbar - noch besser.

              Hi Jörg,

              nein, gleich kommt jemand, der erklärt haben möchte, was an Deiner Lösung noch besser ist?

              Ich nämlich.

              Das ist doch ganz einfach. Über zwei in der Konfiguration zu setzende Einstellungen (am besten natürlich zentral) kann man bestimmen, ob der SQL-Fehler auf der erzeugten Webseite angezeigt wird und/oder im error-Log des Webservers landet.

              Jörg Reinholz

              1. hi,

                nein, gleich kommt jemand, der erklärt haben möchte, was an Deiner Lösung noch besser ist?

                Ich nämlich.

                Oder ein Wanderer...

                Das ist doch ganz einfach. Über zwei in der Konfiguration zu setzende Einstellungen (am besten natürlich zentral) kann man bestimmen, ob der SQL-Fehler auf der erzeugten Webseite angezeigt wird und/oder im error-Log des Webservers landet.

                ... kommt Des Weges und meint: In das Errorlog schaut doch sowieso keiner rein.

                Tatsächlich hatte ich mal Kollegen, die loggten was das Zeug hält. So nach dem Motto: Vielleicht schaut ja doch einer mal ins Log. Dummerweise war der Einzige, der da ab und zu mal reinschaute, der Vorgesetzte der Entwicklergilde, der sich die unfassbare Frage stellte, warum das Error-Log größer als das Access-Log sei.

                Mein Standpunkt hierzu: Entwicklergetrieben geloggt wird nur, wenn es keine andere Möglichkeit gibt, einem Fehler auf die Spur zu kommen.

                Horst

                1. Ha!

                  Mein Standpunkt hierzu: Entwicklergetrieben geloggt wird nur, wenn es keine andere Möglichkeit gibt, einem Fehler auf die Spur zu kommen.

                  Der Gag ist, dass im Produktionsbetrieb außer Störungen und (vermeintlichen) Angriffen nichts im Error-Log auftauchen sollte.

                  der sich die unfassbare Frage stellte, warum das Error-Log größer als das Access-Log sei

                  Das soll gleich gar nicht vorkommen. Wir schreiben ja schließlich keine Wordpress-Plugins.

                  Jörg Reinholz

                  1. Hai,

                    der sich die unfassbare Frage stellte, warum das Error-Log größer als das Access-Log sei

                    Das soll gleich gar nicht vorkommen. Wir schreiben ja schließlich keine Wordpress-Plugins.

                    LOL ;)

                    Um die Sache mal auf den Punkt zu bringen, ich nutze das Exception-Model, das ist vielfältig.

                    Beim Entwickeln:
                      Wie sieht die momentane Datenstruktur aus, $self->dd($ref), Dump'n die, kommt selbstverständlich wieder raus, wenn ich das Teil gesehen habe, gleich im Browser, da brauche ich kein tail -f error_log

                    Höhere Gewalt:
                      Kann passieren, als Entwickler kann ich in etwa abschätzen, wo das passieren kann, keine DB-Verbindung o.ä., der Besucher kann da nichts für, er kriegt ne schöne Seite mit Texten, die er ggf. auf buchstabieren und mit denen der Support was anfangen kann(!)

                    Fehlerhafte Benutzereingaben:
                      Oops, hier ist der Benutzer schuld. Ich blende ganz oben einen rotgefärbten Abschnitt ein und weise den Benutzer höflich darauf hin, dass dof mit d und hinten mit h geschrieben wird

                    Und überhaupt: Die Zeiten, wo ein Script mit print "Content-Type: text/html\n\n"; beginnt, sind längst vorbei, spätestens seit PHP die Welt der Internetanwendungen erobert, PHP macht es uns vor, das Zauberwort heißt Puffer. Geht auch in Perl, andere Geschichte. Und: Wollte ich überhaupt einen Content-Type: text/html ausgeben? Spricht auch für den Puffer, die Sache ist doch ganz einfach: Alles was die Response erzeugt (Interface, Control, Factory) wird in einen try-Block gesetzt, fertig. Dem Puffer ists egal, ob das, was drinsteht, ein jpeg ist, ein pdf oder schnödes HTML, das weiß nur der Entwickler und der wird schon den richtigen Header vorwegschicken. Es sei denn, in der Factory wurde gestreikt oder der Entwickler wollte vorübergehend mal was anderes gucken, was im catch-Block mit dem Content-Type: text/plain auf jeden Fall gut lesbar ist.

                    Der Sonderfall sind fehlerhafte Benutzereingaben, die sollten nicht im catch-Block landen, was sie auch nicht machen, wenn ich eine Exception zwar fallen lasse aber nicht durchreiche sondern weiter oben abfange, solange der Benutzer das noch korrigieren kann.

                    Ja, lieber Jörg, wir wissen, wie das alles geht. Aber draußen siehts anders aus. Tut mir leid, wenn ich beim Stichwort Loggen Sodbrennen kriege und andere Zustände. Es wird Zeit, dass ich mit meinen Ideen was Besseres mache, als mich in irgendeiner Saftwarebude vorführen lasse.

                    Viele Grüße,
                    Horst

      2. Tach!

        Wo würde denn ein "schlichter" SQL Error 1064 oder 1054 auftreten? Im Prepare Teil oder im Execute Teil?
        Und muß man das mit catch und try realisieren oder gibt es andere Möglichkeiten?

        Syntax-Fehler werden eher im Prepare-Teil auftreten, Duplicate-Entry-Fehler zum Beispiel im Execute. Was jetzt genau deine genannten Fehlernummern für Fehler sind, hab ich nicht geprüft. Es kann aber auch sein, dass Syntaxfehler auch erst beim Execute bemerkt werden. Nämlich dann, wenn PDO Prepared Statments nur simuliert und nicht direkt an das jeweilige DBMS durchreichen kann.

        Wenn dir egal ist, zu unterscheiden wo der Fehler genau auftrat, dann setz sowohl Prepare als auch Execute in den try-Block.

        dedlfix.