Fehlerbehandlung nur nach error_reporting

Anmerkungen, Fragen und Hinweise zur Konfiguration dürfen in diesem Forum gepostet werden. // Notes, questions, and hints on the configuration can be posted here.
Benutzeravatar
jwlighting
Beiträge: 466
Registriert: 14.07.2010, 14:23:58
Wohnort: LK Oldenburg
Kontaktdaten:

Fehlerbehandlung nur nach error_reporting

Beitrag von jwlighting » 13.11.2010, 17:47:04

Hallo,

mir war es so langsam lästig geworden, das ich jede E_USER_NOTICE nagezeigt bekommen habe (auch im Produktivsystem), obwohl ich error_reporting entsprechend eingestellt hatte.
Stattdessen wollte ich (gerade im Produktivsystem) alle Fehler lieber in den Logs des Webserver finden, da ich dort eh prophylaktisch öfters mal rein schaue:

Code: Alles auswählen

error_reporting(E_ALL ^ (E_NOTICE | E_USER_NOTICE));
ini_set('display_errors','0');
ini_set('log_errors', '1');
ini_set('html_errors','off');
ini_set('error_log', null);
Der APF-ErrorHandler interessiert sich allerdings wenig für den eingestellen error_reporting Level, weshalb mir die E_USER-NOTICE weiter "um die Ohren flog"
(Sie soll durchaus geschmissen werden, ist nur in diesem Fall nicht kritisch, daher auch eine Notice).

Also kurz nachgedacht und (quick&dirty) angepasst:

Code: Alles auswählen

function errorHandler($errorNumber,$errorMessage,$errorFile,$errorLine){
	  
      $error_reporting = error_reporting();
   	  
      // Don't raise error, if @ was applied
      if($error_reporting == 0){
         return;
       // end if
      }
      
      // Don't raise errors, that do not match the error_reporting setting
      if(($error_reporting & $errorNumber) == 0){
      	return;
       // end if
      }

      ...

  // end function
}

Meiner Meinung nach könnte es sinnvoll sein, dieses Verhalten über die Registry einstellen zu können. dabei könnte man dann eine error_reporting Bitmaske einstellen, und diese gegen $errorNumber vergleichen (anstelle des error_reporting Levels des Scipts). Also bspw. so:

Code: Alles auswählen

Registry::register('apf::core','ErrorHandler',new ErrorHandlerDefinition('core::errorhandler','DefaultErrorHandler'));
Registry::register('apf::core','ErrorReporting',E_ALL ^ E_NOTICE);

...

function errorHandler($errorNumber,$errorMessage,$errorFile,$errorLine){
	  
      // Don't raise error, if @ was applied
      if(error_reporting() == 0){
         return;
       // end if
      }
      
      $error_reporting = Registry::retrieve('apf::core','ErrorReporting');

      // Don't raise errors, that do not match the ErrorReporting setting
      if(($error_reporting & $errorNumber) == 0){
      	return;
       // end if
      }

      ...

  // end function
}
Was meint ihr dazu, und welchen Hintergrund hat die bisherige Lösung (für den fall, das es ganz bewusst nicht so gelöst ist).

LG :)

Menschen irren - Politiker sind Menschen.
Für den Norddeutschen ist 1kW = 2 Pfund Schlick.

APFelsahne
Beiträge: 222
Registriert: 18.03.2010, 13:13:07
Wohnort: Ludwigshafen am Rhein
Kontaktdaten:

Re: Fehlerbehandlung nur nach error_reporting

Beitrag von APFelsahne » 13.11.2010, 17:54:45

zumindest in der 1.13-version gibt es ja nicht nur den error sondern auch den exception-handler, evtl. war das ja dein problem?
zumindest läuft das bei mir mit den beiden problemlos
Grüße, Florian
BildAPF-Extension wsCatalyst

Benutzeravatar
dr.e.
Administrator
Beiträge: 4555
Registriert: 04.11.2007, 16:13:53

Re: Fehlerbehandlung nur nach error_reporting

Beitrag von dr.e. » 13.11.2010, 17:55:30

Hallo jwlighting,

der ErrorHandler "meldet" ganz bewusst alles, was auch nur ansatzweise ein Fehler ist. Das ist hinsichtlich einer sauberen Programmierung auch wichtig. Gerade NOTICE-Meldungen können oft zu unerwünschten Effekten führen, gerade wenn Variablen nicht korrekt initialisiert sind.

Dass du dieses Verhalten im Live-System nicht möchtest ist klar, jedoch ist da meiner Ansicht nach auf eine korrekte und deterministische Implementierung zu achten. Sollten trotzdem Fehler auftreten, kannst du einen eigenen ErrorHandler nutzen, der die Informationen nur ins Log schreibt und dann entweder nichts mehr tut oder auf eine entsprechende Fehler-Seite weiterleitet (siehe http://wiki.adventure-php-framework.org ... rorHandler).

Ich hatte aber auch schon länger überlegt, diesen und einen relativ ignoranten ErrorHandler direkt in das APF zu integrieren, damit die relevanten Anwendungsfälle abgedeckt sind. Dein Anwendungsfall ist dabei ebenso relevant wie ein ErrorHandler, der den Fehler komplett ignoriert.

Aktuell ist das Release 1.13 zwar eigentlich schon voll und ich bin am überlegen, Features zu verschieben, aber das ist sicher nicht so viel Aufwand. Brauchst du das dringend? Falls ja, nehme ich es noch auf.
Viele Grüße,
Christian

Benutzeravatar
jwlighting
Beiträge: 466
Registriert: 14.07.2010, 14:23:58
Wohnort: LK Oldenburg
Kontaktdaten:

Re: Fehlerbehandlung nur nach error_reporting

Beitrag von jwlighting » 13.11.2010, 19:27:10

Hallo Christian,

momentan bastel ich mir das alles so zurecht, dass es läuft. Nur sind die Änderungen mit dem nächsten APF-Update dann ja wieder über den Haufen.

Ich schildere den genauen Fall mal etwas näher, eventuell verstehst du mein Problem dann besser.
Die Bilder, die ich zu einem Newseintrag hinzufüge, sollen alle in der Galerie in groß angesehen werden können, und vom Newseintrag aus verlinkt werden. Soweit kein Problem. Soll das Bild eigentlich nicht Bestandteil der Galerie sein, dann lege ich es in einem Unterverzeichnis mit einem Punkt am Anfang ab (.news), diese Verzeichnisse werden von der Galerie nicht mit gelistet. Die Datei selbst ist auch versteckt (Punkt am Anfang ...) - deswegen soll eine NOTICE geschmissen werden, um eventuelle Sicherheitslücken in den Logs zu entdecken, wenn eine versteckte Datei in der Galerie angefordert und angezeigt wird.
Die NOTICE soll natürlich nur geloggt, nicht gezeigt, werden.
Der ErrorHandler "meldet" ganz bewusst alles, was auch nur ansatzweise ein Fehler ist. Das ist hinsichtlich einer sauberen Programmierung auch wichtig. Gerade NOTICE-Meldungen können oft zu unerwünschten Effekten führen, gerade wenn Variablen nicht korrekt initialisiert sind.
Das finde ich soweit auch vollkommen richtig - solange ich nicht dazu gezwungen werde, und ich dies im Produktivsystem dann abstellen kann, ohne den Errorhandler ganz auslassen zu müssen.
Daher mein Vorschlag, dies über die Registry einstellen zu können. Ein Default kann man ja entsprechend setzen, für die genannten ScriptKiddies z.B.. Ebendso kann man implementieren, das Verhalten, prüfen eines reporting-Levels, durch einen 0-Wert abzustellen.
Sollten trotzdem Fehler auftreten, kannst du einen eigenen ErrorHandler nutzen, der die Informationen nur ins Log schreibt und dann entweder nichts mehr tut oder auf eine entsprechende Fehler-Seite weiterleitet.
Hmm. Dann müsste ich dort konfigurieren, welche Fehler ich logge, und welche ich auch anzeige. Ich finde das dann etwas unübersichtlich, da die interne Fehlerbehandlung von PHP vollkommen außen vor gelassen wird und ich an zig Stellen Fehlerverhalten konfiguriere... Wäre aber eine Möglichkeit.
zumindest in der 1.13-version gibt es ja nicht nur den error sondern auch den exception-handler, evtl. war das ja dein problem?
Nein, danke trotzdem. Eine Exception sollte ja grundsätzlich nicht auftreten, wenn das doch, sollte man das auch sofort bemerken, und nicht erst in den Logs (fünf Tage später). Sprich: das sollte man sehen.

LG :)

Menschen irren - Politiker sind Menschen.
Für den Norddeutschen ist 1kW = 2 Pfund Schlick.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4555
Registriert: 04.11.2007, 16:13:53

Re: Fehlerbehandlung nur nach error_reporting

Beitrag von dr.e. » 13.11.2010, 22:00:42

Hallo jwlighting,
Die Datei selbst ist auch versteckt (Punkt am Anfang ...) - deswegen soll eine NOTICE geschmissen werden, um eventuelle Sicherheitslücken in den Logs zu entdecken, wenn eine versteckte Datei in der Galerie angefordert und angezeigt wird.
Die NOTICE soll natürlich nur geloggt, nicht gezeigt, werden.
Das halte ich für einen Design-Fehler. Hier den ErrorHandler zu missbrauchen ist weder nötig noch sinnvoll. Du hast doch in deinem Programm-Code immer die Möglichkeit versteckte Dateien als solche zu identifizieren und dann mit dem Logger eine Nachricht ins Log zu schreiben. Warum muss das über einen NOTICE-Fehler geschehen? Zudem: Fehlerbehandlung ist hinsichtlich der Performance sehr teuer!
Daher mein Vorschlag, dies über die Registry einstellen zu können. Ein Default kann man ja entsprechend setzen, für die genannten ScriptKiddies z.B.. Ebendso kann man implementieren, das Verhalten, prüfen eines reporting-Levels, durch einen 0-Wert abzustellen.
Verstehe mich nicht falsch, ich finde die Erweiterung des ErrorHandlers durchaus sinnvoll, aber nicht für diesen Anwendungsfall. Grundsätzlich tendiere ich daher dazu, einen eigenen ErrorHandler, der das kann auszuliefern und den ErrorLevel über die Registry konfigurierbar zu machen. Hier denke ich an zwei Erweiterungen: einen ErrorHandler, der "einfach nur" loggt und zu einer dedizierten Seite redirectet und einen, den du wie beschrieben konfigurieren kannst.
Nein, danke trotzdem. Eine Exception sollte ja grundsätzlich nicht auftreten, wenn das doch, sollte man das auch sofort bemerken, und nicht erst in den Logs (fünf Tage später). Sprich: das sollte man sehen.
Diese Aussage musst du etwas vorsichtig genießen. Die Exception zu sehen, bedeutet für einen potentiellen Angreifer, dass er sieht, in wie weit deine Anwendung zu kompromitieren ist. Es werden Pfade, Dateien, Fehler-Codes und u.U. sensible Informationen über deine Software oder die aktuell verarbeiteten Daten ausgegeben. Ich persönlich möchte so etwas um jeden Preis verhindert wissen. Deswegen gibt der ScriptKiddie-ErrorHandler ja auch nichts an den Benutzer aus, sondern nur ins Log.

Bist du mit meinem Vorschlag einverstanden, zwei weitere ErrorHandler und einen ExceptionHandler auszuliefern, die per Registry konfigurierbar sind?
Viele Grüße,
Christian

Benutzeravatar
dr.e.
Administrator
Beiträge: 4555
Registriert: 04.11.2007, 16:13:53

Re: Fehlerbehandlung nur nach error_reporting

Beitrag von dr.e. » 13.11.2010, 23:12:28

Hallo Jan,

ich habe nun zwei Varianten von ErrorHandler'n und einen "neuen" ExceptionHandler hinzugefügt (zunächst lokal):

ProductionErrorHandler:

Code: Alles auswählen

   class ProductionErrorHandler extends DefaultErrorHandler {
      
      public function handleError($errorNumber, $errorMessage, $errorFile, $errorLine) {

         // fill attributes
         $this->errorNumber = $errorNumber;
         $this->errorMessage = $errorMessage;
         $this->errorFile = $errorFile;
         $this->errorLine = $errorLine;

         // log error
         $this->logError();

         // redirect to configured page
         $url = Registry::retrieve('apf::core::errorhandler', 'ProductionErrorRedirectUrl', '/');
         header('Location: ' . $url, null, 302);
         exit(0);

      }

   }
ConfigurableErrorHandler:

Code: Alles auswählen

   class ConfigurableErrorHandler extends DefaultErrorHandler {
      
      public function handleError($errorNumber, $errorMessage, $errorFile, $errorLine) {

         // ignore errors, that have been excluded by configuration
         $errorReporting = Registry::retrieve('apf::core::errorhandler', 'ConfigurableErrorReportingLevel', E_ALL);

         if (($errorReporting & $errorNumber) == 0) {
            return;
         }

         // otherwise, handle the error as intended by the default error handler
         parent::handleError($errorNumber, $errorMessage, $errorFile, $errorLine);

      }

   }
ProductionExceptionHandler:

Code: Alles auswählen

   class ProductionExceptionHandler extends DefaultExceptionHandler {

      public function handleException(Exception $exception) {

         // fill attributes
         $this->exceptionNumber = $exception->getCode();
         $this->exceptionMessage = $exception->getMessage();
         $this->exceptionFile = $exception->getFile();
         $this->exceptionLine = $exception->getLine();
         $this->exceptionTrace = $exception->getTrace();
         $this->exceptionType = get_class($exception);

         // log exception
         $this->logException();

         // redirect to configured page
         $url = Registry::retrieve('apf::core::exceptionhandler', 'ProductionExceptionRedirectUrl', '/');
         header('Location: ' . $url, null, 302);
         exit(0);

      }

   }
Bildet das im wesentlichen die aktuell genutzte Funktion ab (abgesehen von der Sinnhaftigkeit ;))?
Viele Grüße,
Christian

Thalo
Beiträge: 247
Registriert: 10.08.2009, 16:56:52

Re: Fehlerbehandlung nur nach error_reporting

Beitrag von Thalo » 14.11.2010, 17:42:16

Hi,

warum nicht direkt mit ini_get und Bitwise-Operatoren arbeiten? (so zum Beispiel). Ich finde es nicht wirklich sinnig, dass die Registry nun per default schon so viel mitschleppt :?

$url = Registry::retrieve('apf::core::errorhandler', 'ProductionErrorRedirectUrl', '/');
sollte doch eher vom Entwickler selber bestimmt werden. Sonst ist ja immer noch die Möglichkeit der Erweiterung.
$errorReporting = Registry::retrieve('apf::core::errorhandler', 'ConfigurableErrorReportingLevel', E_ALL);
finde persönlich ini_get und die Bitwise-Operatoren besser.


Just my 2Cents :)

Benutzeravatar
dr.e.
Administrator
Beiträge: 4555
Registriert: 04.11.2007, 16:13:53

Re: Fehlerbehandlung nur nach error_reporting

Beitrag von dr.e. » 14.11.2010, 18:33:01

Hallo Thalo,
warum nicht direkt mit ini_get und Bitwise-Operatoren arbeiten? (so zum Beispiel).
Du hast doch genau die Möglichkeit, die PHP-internen Konstanten und die Notation für error_reporting dafür zu verwenden?! Der ConfigurableErrorHandler verhält sich also genau wie error_reporting(). Wo siehst du den Unterschied?
Ich finde es nicht wirklich sinnig, dass die Registry nun per default schon so viel mitschleppt :?
Dafür ist die Registry im APF aber da. Da die hier zu konfigurierenden Werte Daten-technisch sehr klein sind, sehe ich aus Performance-Gründen auch kein Problem. Du?
sollte doch eher vom Entwickler selber bestimmt werden. Sonst ist ja immer noch die Möglichkeit der Erweiterung.
Das kannst du doch per

Code: Alles auswählen

Registry::register( 'apf::core::errorhandler', 'ProductionErrorRedirectUrl', '/pages/global-error' );
tun. Sofern du die URL selbst bestimmen möchtest, kannst du den ErrorHandler gerne überschreiben und per
Registry::register( 'apf::core', 'ErrorHandler', new ErrorHandlerDefinition( 'core::errorhandler', 'MyProductionErrorHandler' ) );
deinen eigenen registrieren.
Viele Grüße,
Christian

Benutzeravatar
dr.e.
Administrator
Beiträge: 4555
Registriert: 04.11.2007, 16:13:53

Re: Fehlerbehandlung nur nach error_reporting

Beitrag von dr.e. » 14.11.2010, 18:34:34

Hallo Jan,

ich habe die oben genannten Handler nun für 1.13 in den Code aufgenommen und in die Dokumentation aufgenommen (ist noch nicht online). Die Konfiguration gestaltet sich jedoch wie zuvor beschrieben relativ einfach über die Registry.
Viele Grüße,
Christian

Thalo
Beiträge: 247
Registriert: 10.08.2009, 16:56:52

Re: Fehlerbehandlung nur nach error_reporting

Beitrag von Thalo » 14.11.2010, 20:44:22

Hi Doc,

es ist nicht nur das. Meiner Meinung nach geht hier das APF bzw du öfter den falschen Weg.
Du hast doch genau die Möglichkeit, die PHP-internen Konstanten und die Notation für error_reporting dafür zu verwenden?! Der ConfigurableErrorHandler verhält sich also genau wie error_reporting(). Wo siehst du den Unterschied?
Im Detail geht es mir hier vorallem darum, dass ich so gezwungen bin die Einstellungen für das ErrorReporting an zwei Stellen zu ändern.

Worum es mir aber vorallem im einzelnen geht ist, dass der ConfigurableErrorHandler vom DefaultErrorHandler erbt, was meiner Meinung nach nicht wirklich zielführend ist da wohl niemand die Standard-Error-Page des APFs in seiner Live Application präsentiert. Hier müsste man also eine weitere erweiterung des ErrorHandlers vornehmen womit dann IMHO der jetzige Vorteil nicht mehr gegeben wäre.

Auch finde ich es wenig praktisch, dass nach wie vor 2 ErrorHandler - einer für die Exceptions und einer für error_log einzeln konfiguriert werden muss.

Dazu kommt, dass in der Praxis IMHO ein

Code: Alles auswählen

$url = Registry::retrieve('apf::core::errorhandler', 'ProductionErrorRedirectUrl', '/');
         header('Location: ' . $url, null, 302);
nicht ausreicht. Wie es momentan auf der APF Seite gelöst ist, dass 404s einfach auf die Startseite geleitet werden, finde ich wenig Benutzerfreundlich. Hier müsste man also eine weitere Erweiterung vornehmen wo man "wirkliche" Fehler von nicht gefunden Seiten oder ähnlichem trennt.

Wobei ich allgemein die Weiterleitung zur Startseite wenig schön finde - so ist der Benutzer nur verunsichert ob das Verhalten gewünscht ist oder er es zu einem späteren Zeitpunkt noch einmal probieren sollte. Der nicht versierte Nutzer denkt nicht zuerst an einen Fehler der Applikation. Aber das hat nun nichts direkt mit meinem Anliegen zutun.

Für mich sind das Argumente die eine solche Erweiterung allein aus oben genannten Gründen nicht rechtfertigen.

Ferner habe ich manchmal das Gefühl, dass bei solchen Sachen wieder der Gedanke eines Frameworks in den vordergrund rückt, aber sachen wie die Unterstützt von UTF-8 aussen vor bleibt. Hier wird dann einfach mit "möglichkeit der Erweiterung" argumentiert.

Somit muss jeder Entwickler für sich die I/O Filter, Filter und Validatoren für die Formulare, Tagblibs, ...

neu implementieren. Das erweckt in mir den Eindruck, dass viele Funktionen zugunsten des einzelnen implementiert werden wovon die komplette Community weniger hat. Auf der einen Seite will man die maximale Performance rausholen, dass sogar als so dringend empfunden wird, dass die Registry auf Static umgestellt wird und das direkt am selben Tag noch eingecheckt wird, andererseits dann soetwas.

Auch ist mir aufgefallen, dass in vielen Diskussionen schon durchschien, dass die jetzige Rechteverwaltung vom UMGT schon für die meisten viel zu oversized ist und sie es nicht benutzen. Trotzdem wird nun hier erweitert. Auch ließt man häufiger, dass vieles nicht aus dem UMGT benötigt wird, wie eine vielzahl der Attribute. Hier wird dann wieder mit der Erweiterung argumentiert anstatt sich hier eine bessere Lösung zu überlegen und sich an den Bedürfnissen der Community zu orientieren.

Man muss bedenken, dass das APF schon seit 7(?) Jahren existiert daher verstehe ich nicht warum nun alles geändert werden muss wo es IMHO auch vererbung tun würde. Sofern die Frage öfter gestellt wird und daher das Interesse der Community signalisiert wird, sollte es mit ins Framework aufgenommen werden - vorher nicht.

Ich denke das reicht nun erstmal. Wollte zwar noch ein wenig mehr schreiben aber ich warte erstmal euer Feedback ab :)

Benutzeravatar
jwlighting
Beiträge: 466
Registriert: 14.07.2010, 14:23:58
Wohnort: LK Oldenburg
Kontaktdaten:

Re: Fehlerbehandlung nur nach error_reporting

Beitrag von jwlighting » 14.11.2010, 21:09:47

Hallo Christian,

erstmal meine Anerkennung, dass du meinem Vorschlag gefolgt bist, ohne das es aus dem konkreten Fall heraus Sinn gemacht hast.

Ich habe deine Erläuterungen zu meinen Design-Fehler überlesen. Letztendlich hast du Recht, ich bin da wirklich etwas unsauber gewesen.
Ursprünglich wurde keine Notice, sondern ein Warning geschmissen; an einen Anwendungsfall in dem es sinnvoll ist, die Datei zu verstecken, hatte ich beim Programmieren noch gar nicht gedacht.
Als es dann notwendig wurde, habe ich den schnellen Weg gewählt und das Warning einfach zur Notice degradiert und versteckt (erst sogar das trigger_error einfach schnell auskommentiert), da die Zeit gedrängt hat.
Eigentlich wäre es richtig, weder einen Fehler zu werfen, noch ins Log zu schreiben, und auf das Datei-verstecken zu verzichten und einen saubereren Weg einzuschlagen, um das Problem zu lösen (Den Link hinter dem Bild z.B. nur zu generieren, wenn das Bild auch unterhalb/in der Galerie liegt...).
Dazu kam, dass mir der Logger und das ErrorHandling-Konzept noch gar nicht wirklich bekannt waren, daher auch mein etwas wirrer Ansatz oben, in dem ich keinen neuen Handler definiert habe, sondern in der Funktion rumgefuscht habe. Es war also auch ein bisschen Unwissenheit im Spiel, sorry dafür. ;)
Diese Aussage musst du etwas vorsichtig genießen. Die Exception zu sehen, bedeutet für einen potentiellen Angreifer, dass er sieht, in wie weit deine Anwendung zu kompromitieren ist.
... Ja... ! Hast du Recht. Was mich ein wenig stört, ist das weiterleiten. Für mich gehört eine Exception auf letzter Ebene (wenn sie aus dem Modell kommt, im Controller) vor dem View abgefangen und eine entsprechende Meldung dann in den View, mit der der Nutzer auch etwas anfangen kann. Wenn man dazu ins Log schreibt oder in kritischen Fällen eine Mail verschickt (was mich schon oft gerettet hat...), klar ok und richtig. Wenn man als Nutzer allerdings einfach nur auf Home landet, finde ich das etwas dreckig.
Thalo hat geschrieben:Im Detail geht es mir hier vorallem darum, dass ich so gezwungen bin die Einstellungen für das ErrorReporting an zwei Stellen zu ändern.
Wenn man das muss, stimme ich dir zu. Gerade für einen erfahrenen PHPler , der aber gerade erst in's APF einsteigt, ist das eine Falle, die ich vermeiden wollen würde. Daher möchte ich vorschlagen, für den Fall, das die APF-eigene Error-Reporting Konstante nicht gesetzt ist, den System ER-Level zu verwenden, statt E_ALL.

Btw: ich gucke meist nur in die ApacheLogs, da wäre es praktisch, wenn der Logger seine Logs mit error_log() auch dort platzieren würde/könnte. Weiter ist mir aufgefallen, dass viele Fehler gar nicht geloggt werden. Liegt das an den Rechten, oder liegt der Fehler sonst irgendwie bei mir?

LG :)

Menschen irren - Politiker sind Menschen.
Für den Norddeutschen ist 1kW = 2 Pfund Schlick.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4555
Registriert: 04.11.2007, 16:13:53

Re: Fehlerbehandlung nur nach error_reporting

Beitrag von dr.e. » 14.11.2010, 23:45:42

Hallo Thalo,

danke zunächst für deine kritischen Worte. Ich bin immer gerne bereit über die Themen zu diskutieren und möchte das auch an dieser Stelle tun. Sicher ist das ein oder andere - bzw. die Beweggründe zu einer Implementierung - nicht immer transparent, deswegen sollten wir das einfach offen diskutieren. Ich versuche mal zu den einzelnen Punkten Stellung zu nehmen.
Im Detail geht es mir hier vorallem darum, dass ich so gezwungen bin die Einstellungen für das ErrorReporting an zwei Stellen zu ändern.
Das bist du meiner Ansicht nach nicht, sofern du nur mit dem APF arbeitest, denn sobald du in PHP einen ErrorHandler per set_error_handler() registrierst, bist du ganz alleine verantwortlich für das, was bei einem Fehler passiert. Damit reicht es völlig, die Einstellungen des APF zu konfigurieren. Die Einstellungen von PHP werden dabei komplett überschrieben (Zitat aus der deutschen PHP-Dokumentation):
Vergessen Sie bei der Implementation auf keinen Fall, dass auf diese Weise die standardmäßige PHP-Fehlerbehandlung vollkommen umgangen wird!
Ich will das Vorgehen damit nicht schön reden, sondern ich würde mit dir gerne diskutieren, warum du es als nicht korrekt ansiehst. Denn meiner Ansicht nach ist es das.
Worum es mir aber vorallem im einzelnen geht ist, dass der ConfigurableErrorHandler vom DefaultErrorHandler erbt, was meiner Meinung nach nicht wirklich zielführend ist da wohl niemand die Standard-Error-Page des APFs in seiner Live Application präsentiert. Hier müsste man also eine weitere erweiterung des ErrorHandlers vornehmen womit dann IMHO der jetzige Vorteil nicht mehr gegeben wäre.
Die aktuelle Hierarchie sieht wie folgt aus:

Code: Alles auswählen

DefaultErrorHandler ----> ConfigurableErrorHandler
                    | 
                    + ---> ProductionErrorHandler
Für das Live-System wird in der aktualisierten Dokumentation explizit der ProductionErrorHandler empfohlen. Hier der Auszug aus der Doku für 1.13, die ich aktuell zunächst lokal aktualisiert habe und mit dem Erscheinen des RC1 online verfügbar sein wird:
Fehlerbehandlung_1_13.zip
(320.39 KiB) 78-mal heruntergeladen
Welche weitere Erweiterung des ErrorHandlers siehst du da? Welcher Vorteil wäre nicht mehr gegeben?
Auch finde ich es wenig praktisch, dass nach wie vor 2 ErrorHandler - einer für die Exceptions und einer für error_log einzeln konfiguriert werden muss.
Das habe ich leider nicht in der Hand. Die PHP-API ist so ausgelegt, dass es sowohl den Zustand "Error" als auch "Exception" für beliebige Fehler gibt, die bei Nutzung der PHP-API auftreten können. Die mysqli-Erweiterung beispielsweise wirft Fehler wo hingegen andere Elemente Exceptions werfen. Exakt danach richtet sich das APF und bietet die Möglichkeit an, zwischen diesen zu unterscheiden.

Im Rahmen der Umstellung des APF auf Exceptions habe ich bereits darüber nachgedacht, den ErrorHandler komplett zu entfernen und diesen einfach durch eine Funktionalität zu ersetzen, die den Error in Exceptions umsetzt. Damit könnte man sich einen Teil sparen und hätte eine einheitliche API basierend auf der nicht ganz einheitlichen PHP-API. Wobei du auch in JAVA zwischen VM-Errors und "echten" Exceptions (abgeleitet von RuntimeException) unterscheidest, dort jedoch beides mal stringente Syntax hinsichtlich der Möglichkeit hast, Exceptions zu fangen. Sofern du auf diese Erweiterung/Vereinheitlichung anspieltst, kann ich dir nur zustimmen.
Dazu kommt, dass in der Praxis IMHO ein [..] nicht ausreicht. Wie es momentan auf der APF Seite gelöst ist, dass 404s einfach auf die Startseite geleitet werden, finde ich wenig Benutzerfreundlich. Hier müsste man also eine weitere Erweiterung vornehmen wo man "wirkliche" Fehler von nicht gefunden Seiten oder ähnlichem trennt.
Mit der genannten Methode bist du in der Lage für unerwartete Fehler (dazu gehört ein 404 nicht) eine Behandlung zu definieren, die sicherstellt, dass eine funktionierende Seite angezeigt wird. Wenn du möchtest, dass du bei einem solchen nicht die Startseite, sondern eine hübsche Seite angezeigt wird, die dem Benutzer den Umstand beschreibt und weitere Navigations-Möglichkeiten anbietet, so kannst du das (für das Beispiel der APF-Seite) so tun:

Code: Alles auswählen

Registry::register( 'apf::core::errorhandler', 'ProductionErrorRedirectUrl', '/Seite/999-Unbekannter-Fehler' );
Die 404-Fehler werden auf der Seite durch eine Front-Controller-Action abgefangen, die eine nicht identifizierbare Seite aufspürt und statt dessen die "echte" 404-Seite anzeigt. Das kannst du mit dem Link http://adventure-php-framework.org/Seite/777-Unbekannt ausprobieren. Du wirst nicht zur Startseite geleitet, sondern erhälst die beschriebene Fehler-Seite.

Um es nochmals zu verdeutlichen: Fehler im Sinne der PHP-Errors treten nur dann auf, wenn du das auch "möchtest" (z.B. trigger_error()) oder wenn ein (ungesicherter) API-Call schief geht (z.B. mysql_connect()). Sofern du in deiner Applikation ausschließlich mit Exceptions arbeitest und diese an den relevanten Stellen fängst, kommst du mit dem ErrorHandler nicht in Berührung. Selbiges gilt übrigens für Exceptions. Auch hier werden vom APF-Exception-Handler nur die nicht vorher abgefangen Exceptions gefangen.
Ferner habe ich manchmal das Gefühl, dass bei solchen Sachen wieder der Gedanke eines Frameworks in den vordergrund rückt, aber sachen wie die Unterstützt von UTF-8 aussen vor bleibt. Hier wird dann einfach mit "möglichkeit der Erweiterung" argumentiert.
Magst du mir das etwas genauer erläutern? Ich kann mich erinnern, dass wir vor einiger Zeit über die Codierung der APF-Code-Dateien diskutiert haben jedoch unterstützt das APF UTF-8 genauso viel und wenig wie PHP das tut. Ferner verstehe ich den Zusammenhang zwischen Erweiterbarkeit und Framework-Gedanke nicht...
Somit muss jeder Entwickler für sich die I/O Filter, Filter und Validatoren für die Formulare, Tagblibs, ... neu implementieren. Das erweckt in mir den Eindruck, dass viele Funktionen zugunsten des einzelnen implementiert werden wovon die komplette Community weniger hat. Auf der einen Seite will man die maximale Performance rausholen, dass sogar als so dringend empfunden wird, dass die Registry auf Static umgestellt wird und das direkt am selben Tag noch eingecheckt wird, andererseits dann soetwas.
Ich habe das Gefühl, dass dich das Bestreben stört, etwas allgemeingültiges bereitzustellen, da dir die Anwendbarkeit nicht gegeben scheint? Oder denkst du, dass die Entwicklung auf Anforderung einzelner nicht mit dem Framework-Gedanken vereinbar ist? Kannst du mal Bereiche konkreter nennen, die deiner Meinung nach nicht für den täglichen Einsatz brauchbar sind? Mir ist es wichtig das zu hören, denn das APF - und im speziellen auch ich - haben zum Ziel eine bestmögliche Unterstützung des Entwicklers abbilden zu können. An vielen Stellen ist das IMHO schon so, andere Stellen bedürfen noch der Nachbesserung.

Um das Thema Registry nochmals aufzugreifen: ich bin schon sehr lange im Geschäft und habe viele positive und negative Erfahrungen im Hosting-Geschäft gemacht. Diese lehren mich immer wieder, dass es nicht nur wichtig ist Werkzeuge mit möglichst vielen Features zu haben, sondern auch beste Performance bereit zu stellen. Nicht umsonst kann sich das APF mit den Konkurrenz-Produkten erfolgreich messen und stellt damit eine gute Plattform für Applikationen zur Verfügung, die in einer Umgebung mit hohen Performance-Ansprüchen laufen.

Dies lässt mich jedoch nicht die Funktionalität vergessen, die ein Framework für die tägliche Arbeit bereitstellen muss. Eins sehr positives Beispiel ist für mich da das Key-Features von 1.13: der neue ConfigurationManager. Dort haben wir über 80 Beiträge über eine Umsetzung diskutiert, die schließlich in das Release 1.13 eingeflossen ist und meiner Ansicht nach am Ende eine gute Lösung bereitstellt. Sofern es also Themen gibt, über die du diskutieren möchtest - die sich deiner Meinung nach zur Überarbeitung anbieten -, dann immer gerne.
Auch ist mir aufgefallen, dass in vielen Diskussionen schon durchschien, dass die jetzige Rechteverwaltung vom UMGT schon für die meisten viel zu oversized ist und sie es nicht benutzen. Trotzdem wird nun hier erweitert. Auch ließt man häufiger, dass vieles nicht aus dem UMGT benötigt wird, wie eine vielzahl der Attribute. Hier wird dann wieder mit der Erweiterung argumentiert anstatt sich hier eine bessere Lösung zu überlegen und sich an den Bedürfnissen der Community zu orientieren.
Welchen Weg schlägst du vor? Die deiner Argumentation nach zu urteilen konsequente Antwort wäre ein ACL-Konzept einzuführen. Das ist natürlich eine legale Forderung und stellt für Entwickler einfacher Anwendungen sicher eine gute Alternative für das RBAC-basierte UMGT-Modul bereit. An was denkst du genau?
Man muss bedenken, dass das APF schon seit 7(?) Jahren existiert daher verstehe ich nicht warum nun alles geändert werden muss wo es IMHO auch vererbung tun würde.
Das verstehe ich jetzt nicht ganz. Oben stellst du das Thema Vererbung in Frage, hier ist es ein Stilmittel? Was meinst du mit "nun alles geändert werden"? Das Framework wird gemäß Roadmap weiterentwickelt. Wenn du ein Features für dringend notwendig erachtest oder etwas hast, was dich aufhält oder umgekehrt produktiver machen würde, dann immer her damit. Vererbung ist machmal das richtige Mittel, manches Mal aber auch nicht.
Sofern die Frage öfter gestellt wird und daher das Interesse der Community signalisiert wird, sollte es mit ins Framework aufgenommen werden - vorher nicht.
Auf welche Features stellst du ab? Um den Hintergrund vielleicht etwas transparenter aussehen zu lassen: die Erweiterung des ErrorHandler ist keine, die mal eben schnell aufgenommen wurde auch wenn das so aussieht. Mit dem Gedanken habe ich schon länger gespielt, da ich es als Benutzer-unfreundlich empfinge für eine Standard-Aufgabe bei einem Framework eine Erweiterung schreiben zu müssen, obwohl man das allgemeingültig lösen kann. Genau das ist auch mein Vorgehen, Features zu bewerten und eben mit der Community - bzw. denjenigen, die sich an der Diskussion beteiligen - zu diskutieren.
Ich denke das reicht nun erstmal. Wollte zwar noch ein wenig mehr schreiben aber ich warte erstmal euer Feedback ab :)
Immer gerne. Bitte erweitere dein Feedback, dann können wir die Punkte sicherlich zu einer konstruktiven Erweiterung des Feature-Sets oder der Doku oder was auch immer führen.
Viele Grüße,
Christian

Benutzeravatar
dr.e.
Administrator
Beiträge: 4555
Registriert: 04.11.2007, 16:13:53

Re: Fehlerbehandlung nur nach error_reporting

Beitrag von dr.e. » 15.11.2010, 00:05:03

Hallo Jan,

nun zu deinem Post:
Eigentlich wäre es richtig, weder einen Fehler zu werfen, noch ins Log zu schreiben, und auf das Datei-verstecken zu verzichten und einen saubereren Weg einzuschlagen, um das Problem zu lösen (Den Link hinter dem Bild z.B. nur zu generieren, wenn das Bild auch unterhalb/in der Galerie liegt...).
Exakt das meinte ich.
Dazu kam, dass mir der Logger und das ErrorHandling-Konzept noch gar nicht wirklich bekannt waren, daher auch mein etwas wirrer Ansatz oben, in dem ich keinen neuen Handler definiert habe, sondern in der Funktion rumgefuscht habe. Es war also auch ein bisschen Unwissenheit im Spiel, sorry dafür. ;)
Kein Problem, dafür gibt es ja das Forum: für's Fragen stellen und für die Diskussion. Sofern du für den Moment an der Implementierung festhalten musst/möchtest, kannst du dies mit einem eigenen ErrorHandler schon mit dem Release 1.12 tun.
... Ja... ! Hast du Recht. Was mich ein wenig stört, ist das weiterleiten. Für mich gehört eine Exception auf letzter Ebene (wenn sie aus dem Modell kommt, im Controller) vor dem View abgefangen und eine entsprechende Meldung dann in den View, mit der der Nutzer auch etwas anfangen kann. Wenn man dazu ins Log schreibt oder in kritischen Fällen eine Mail verschickt (was mich schon oft gerettet hat...), klar ok und richtig. Wenn man als Nutzer allerdings einfach nur auf Home landet, finde ich das etwas dreckig.
Die Anforderungen für das Abfangen von "globalen" und nicht vorhersehbaren Fehlern ist sicher an den Einzelfall geknüpft. Insofern kann das APF nur den Mechanismus und den Standard-Fall anbieten. Wie im vorangegangenen Post beschrieben, werden natürlich nur diejenigen Fehler tatsächlich durch den globalen ErrorHandler gefangen, die nicht zuvor schon im Applikations-Code behandelt werden. Selbies gilt für Exceptions. Auch hier ist der globale ExceptionHandler nur für nicht vorher im Applikations-Code gefangene Exceptions da. Fängst du eine Exception im Code, ist der ExceptionHandler garnicht erst im Spiel. Sofern du schon mal im JAVA-Bereich unterwegs warst, gibt es soetwas ähnliches auch für den Servlet-Container (z.B. TOMCAT). Dort kannst du in einer JSP (vergleichbar mit APF-Templates) auch einen globalen ErrorHandler angeben (etwa der des APFs entsprechend), die den Fehler mit dem Stack und den aktuellen Informationen zum Zeitpunkt des Fehlers ausgibt. Fängst du in deinem JSP- oder JAVA-Code den Fehler schon vorher ab, wird diese nicht involviert.

Konkret bedeutet das: wenn dein Model eine Exception wirft, weil ein über einen URL-Parameter geforderter Datensatz nicht existiert, kannst du diese im Controller abfangen und den View entsprechend informieren (z.B. Fehlermeldung anzeigen) und den Fehler vielleicht in ein Log schreiben.
Wenn man das muss, stimme ich dir zu. Gerade für einen erfahrenen PHPler , der aber gerade erst in's APF einsteigt, ist das eine Falle, die ich vermeiden wollen würde. Daher möchte ich vorschlagen, für den Fall, das die APF-eigene Error-Reporting Konstante nicht gesetzt ist, den System ER-Level zu verwenden, statt E_ALL.
Den Standard-Error-Level der aktuellen PHP-/VHOST-Konfiguration zu verwenden halte ich für einen guten Vorschlag. Ich möchte jedoch nochmal betonen, dass der APF-ErrorHandler den PHP-eigenen komplett überschreibt (siehe vorheriger Post) und dadurch keine zwei Stellen entstehen, die konfiguriert werden müssen. Sobald du die pagecontroller.php inkludierst, wird der PHP-Mechanismus ersatzlos gestrichen und durch den APF-eigenen überschrieben. Ich ändere die Default-Wert-Einstellung noch.
Btw: ich gucke meist nur in die ApacheLogs, da wäre es praktisch, wenn der Logger seine Logs mit error_log() auch dort platzieren würde/könnte. Weiter ist mir aufgefallen, dass viele Fehler gar nicht geloggt werden. Liegt das an den Rechten, oder liegt der Fehler sonst irgendwie bei mir?
Der Logger des APF ist so implementiert, dass er sein eigenes Logfile schreibt. Das ist bewusst so gehalten, dass klar zwischen den Logfiles von PHP und dem Apachen getrennt wird. Andernfalls verwässern Apache-Meldungen die PHP-Logs und umgekehrt. Möchtest du diese mt error_log() in das Apache-Log schreiben, muss dies in einem eigenen Error- bzw. Exception-Handler so realisiert werden. Die mit dem APF mitgelieferten Handler unterstützen das aktuell nicht. Die Erweiterung ist jedoch mehr oder weniger ein Einzeiler, zusammen mit dem Versenden eines Fehlers per Mail sicher ein paar mehr, aber trotzdem sehr einfach zu realisieren.

Ich hoffe, das hilft dir weiter.
Viele Grüße,
Christian

Thalo
Beiträge: 247
Registriert: 10.08.2009, 16:56:52

Re: Fehlerbehandlung nur nach error_reporting

Beitrag von Thalo » 15.11.2010, 00:31:10

Hi Doc,

danke für deine ausführliche Erklärung zu den einzelnen Positionen. Das lässt vieles in einem anderen Licht erscheinen. Aus den Gründen möchte ich da vorher noch einmal in mich gehen bevor ich mich zu den einzelnen Punkten im Detail äussere. Zu der Kritik mit der Zeichencodierung möchte ich aber schon jetzt eingehen:

Ferner habe ich manchmal das Gefühl, dass bei solchen Sachen wieder der Gedanke eines Frameworks in den vordergrund rückt, aber sachen wie die Unterstützt von UTF-8 aussen vor bleibt. Hier wird dann einfach mit "möglichkeit der Erweiterung" argumentiert.
Magst du mir das etwas genauer erläutern? Ich kann mich erinnern, dass wir vor einiger Zeit über die Codierung der APF-Code-Dateien diskutiert haben jedoch unterstützt das APF UTF-8 genauso viel und wenig wie PHP das tut. Ferner verstehe ich den Zusammenhang zwischen Erweiterbarkeit und Framework-Gedanke nicht...
Dass die standard String Bibliotheken von PHP keine Multibyte Zeichensätze unterstützen ist richtig. Hierfür gibt es aber die Multibyte-Bibliothek. Dass hier die Seiten (genauer auch die Seite des APF) mit Mehrbyteigen-Codierten Strings und den Singlebyte Bibliotheken arbeiten halte ich für ein Sicherheitsrisiko.

Kurzes Beispiel:

ä hat schon 2 Bytes in UTF-8 (geht hoch bis 4 Byte pro Zeichen) und die standard Bibliotheken von PHP erkennen hier statt 1 Zeichen 2. Auch die Regulären Ausdrücke bekommen hier Probleme.

Daher wie schon damals mein Vorschlag, dass hier die Filter, Validatoren, Taglibs, Parser, .. auf die Multibyte Bibliothek umgestellt werden. Beim mitlesen bekomme ich zumindest mit, dass sehr viele der hier anwensenden UTF-8 verwenden. Daher denke ich, dass hier, wie du mir damals geraten hast, eine einfache Vererbung nicht der richtige Weg ist. Hier sollte, wie du schon ansprachst, ein generischer Weg zugunsten der Community gewählt werden.

Da die Multibyte-Funktionen auch Singlebyte-Zeichencodierungen unterstützen sehe ich hier im Grunde kein Problem. Du etwa?

Benutzeravatar
dr.e.
Administrator
Beiträge: 4555
Registriert: 04.11.2007, 16:13:53

Re: Fehlerbehandlung nur nach error_reporting

Beitrag von dr.e. » 15.11.2010, 10:49:21

Hallo Thalo,

das Risiko, das das APF durch die Nutzung der "Ein-Byte"-Funktionen potentiell Probleme hat ist mir definitiv bewusst. Eine Umstellung auf die genannten Funktionen (z.B. mb_stripos()) ist zudem keine große Sache, da es nur wenige Stellen gibt, an denen diese Anwendung finden. Ich sehe hierbei jedoch ernste Probleme bei der Kompatibilität auf das APF zukommen, denn damit ist das Framework schon nur noch auf denjenigen Hosting-Paketen einsetzbar, die die Erweiterung auch installiert und aktiviert haben. Eigene Server und eigene Hosting-Umgebungen sind da zwar nicht betroffen. Dagegen steht die Tatsache, dass die für den Parser relevanten Zeichen (=, ", <, >) sowohl in ISO latin1 als auch UTF-8 an der selben Stelle im Zeichensazu aufgehoben sind und der Parser bisher erfolgreich mit beiden Zeichensätzen zurecht kommt.

Ich hatte ehrlich gesagt auch gehofft, dass die PHP-Entwickler native UTF-8-Unterstützung schon früher bringen und dafür nicht wirklich sinnvolle Erweiterungen wie goto-Anweisungen einfach nicht implementieren. Das APF ist an dieser Stelle leider von der PHP-API direkt abhängig und muss sich auf den Support von UTF-8 verlassen können. Das soll bitte nicht als Ausrede betrachtet werden, sondern als Tatsache, die mit dem Vorhaben konkurriert, das APF für eine möglichst breite Masse benutzbar zu machen.
Da die Multibyte-Funktionen auch Singlebyte-Zeichencodierungen unterstützen sehe ich hier im Grunde kein Problem. Du etwa?
Hinsichtlich der Abwärts-Kompatibilität mache ich mir keine Gedanken. Eher schon zur Aufwärts-Kompatibilität und zur Performance.
Viele Grüße,
Christian

Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast