Ausgeben von geladenen Klassen

nchristoph

Erfahrenes Mitglied
Hallo,

ich stehe gerade vor folgendem Problem:

Ich arbeite an einem eigenen Errorhandler, nur funktioniert die Ausgabe nicht richtig:

PHP:
<?php

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Description of errorHandler
 *
 * @author nchristoph
 */
class errorHandler {
  public $level;
  public $message;
   
   
  public static $instance;
   
  public static function getInstance(){
   
  if(!isset(self::$instance)){   
  self::$instance = new errorHandler();
  }
  return self::$instance;
  }
   
  public function __construct(){}
   
  public function printOutError(){
  if($this->level == 0){
  $error = "<p class=\"informationalert\"><span>This is an information alert</span> <br /> ".$message."</p>";
  }else if($this->level == 1){
  $error = "<p class=\"greenalert\"><span>This is an green alert</span> <br /> ".$this->message."</p>";
  }else if($this->level == 2){
  $error = "<p class=\"warningalert\"><span>This is an warning alert</span> <br /> ".$this->message."</p>";
  }else if($this->level == 3){
  $error = "<p class=\"rejectionalert\"><span>This is an rejection alert</span> <br /> ".$this->message."</p>";
  }else
  $error = "&nspb;";
  return $error;
  }
   
  public function handleErrorMessages($level, $message){

  $this->level = $level;
  $this->message = $message;
  }
}

Und so ruf ich Ihn auf:
PHP:
function __autoload($classname){
  require_once("core/classes/".strtolower($classname).".class.php");
  global $debug;
  $errorHandler = errorHandler::getInstance();
 
  if($debug == 1){
  $level = 1;
  $message = "Classname: ".$classname." loaded";
  $message .= "<br />";
  $message .= "File included: core/classes/".strtolower($classname).".class.php";
  $message .= "<br />";
  $errorHandler->handleErrorMessages($level, $message);   
  }
}

Jetzt wird aber immer nur die erste Klasse, die geladen wird, ausgegeben, nicht jedoch die anderen, die auch geladen sind.

Ich tüftel da schon eine Weile dran, hab schon versucht, die Pfade in einen Array zu laden und mit einer foreach Schleife auszugeben, bin allerdings daran gescheitert, das ich etwas eingerostet bin.

Kann mir eventuell wer weiterhelfen?
 
Die Frage ist schwierig zu beantworten, weil man irgendwie nicht weiß, aus welcher Richtung man die Sache greifen soll.

Eindeutig ist immerhin: __autoload nutzt man nicht mehr (zumindest nicht mehr direkt). spl_autoload_register ist die geeignete Funktion.

- http://php.net/manual/en/function.spl-autoload-register.php

Dann wird es aus mehreren Gründen kompliziert.

Einmal ist deine errorHandler-Klasse sozusagen eine Mischung aus verschiedenen Designkonzepten, die alle nicht wirklich gut in einer Klasse kombinierbar sind. Du hast teilweise ein Singleton (aber nicht richtig, weil die Klasse instanzierbar bleibt), teilweise eine Art Message-Entity (ein leichtes Objekt, das die Felder level und message besitzt, und eine Meldung repräsentiert) und teilweise eine Art Dispatcher oder Logger, der eingehende Meldungen verarbeitet. Deine Frage zielt dann noch auf eine Art Message-Buffer ab, der eingehende Meldungen zwischenspeichert und zu einem vom Anwender (im Sinne des Programmierers, der die Klasse nutzt) gewählten Zeitpunkt als HTML gerendert zurückliefern soll.

Dann ist schon durchgeklungen, dass deine Implementation eher in Richtung Logger geht, statt ein Error-Handler zu sein, wie der Name besagt. Ein Error-Handler ist tendenziell eher eine Komponente, die PHP-Errors und/oder Exceptions verarbeitet und beispielsweise per set_error_handler und/oder set_exception_handler global für einen PHP-Aufruf gesetzt werden kann.

Vielleicht als Beispiel, wie man es (Edit: jetzt als Logger) machen könnte:

PHP:
interface LoggerInterface
{
    public function log($level, $message);
}

class MyAutoloader
{
    /**
     *
     * @var LoggerInterface
     */
    private $logger;

    public function __construct(LoggerInterface $logger = null)
    {
        $this->logger = $logger;
    }

    public function register()
    {
        spl_autoload_register(array($this, 'autoload'));
    }

    public function autoload($className)
    {
        $path = '/path/to/src/' . $className . '.php';

        if (file_exists($path)) {
            require $path;

            if ($this->logger !== null) {
                $this->logger->log(1, sprintf('Class %s loaded', $className));
            }
        }
    }
}



$loader = new MyAutoloader();
$loader->register();

Dem Konstruktor von MyAutoloader kannst du dann verschiedene Logger übergeben. Eine simple Variante könnte so aussehen:

PHP:
class SimpleLogger implements LoggerInterface
{
    public function log($level, $message)
    {
        printf("Level: %s, Message: %s\n", $level, $message);
    }
}

Ein Logger, der Einträge erst mal zwischenspeichert, könnte so aussehen:

PHP:
class BufferingLogger implements LoggerInterface
{
    private $buffer = array();

    public function log($level, $message)
    {
        $this->buffer[] = sprintf("Level: %s, Message: %s", $level, $message);
    }

    public function clearBuffer()
    {
        $this->buffer = array();
    }

    public function getBuffer()
    {
        return $this->buffer;
    }
}


$logger = new BufferingLogger();
$logger->log(1, 'Hallo');
$logger->log(1, 'Welt');

var_dump($logger->getBuffer());

Für all das gibt es allerdings auch schon ausgereifte fertige Komponenten.

Logger:

- https://github.com/Seldaek/monolog
- https://github.com/katzgrau/KLogger

Und im Autoloading ist mittlerweile Composer immer die Option, die man zuerst und sehr ernsthaft in Erwägung ziehen sollte.

- https://getcomposer.org/
- http://php-de.github.io/jumpto/composer/ (Einführung)

Dann wären noch Namespaces zu nennen, die ich in diesem Beitrag nicht berücksichtigt habe. Ein Autoloader, der Namespaces berücksichtigt, muss noch mal etwas anders aussehen.

- http://php.net/manual/en/language.namespaces.php
 
Zuletzt bearbeitet:
Hallo,

Sry für die späte Antwort.

Danke erstmal, die Links waren allesamt sehr Informativ.

Was ich lediglich erreichen will ist, das bei einem Fehler der Fehler, der aufgetreten ist, über dem Contentbereich angezeigt wird im Div mit der ID errormessage.

Hast du dafür auch eine Lösung parat?
 
Na ja, schreib den Fehler in ein div-Element und positioniere das per CSS passend (z-index, position: absolute, …).

Das funktioniert natürlich nur für Fehler, von denen sich die Anwendung „erholen“ kann. Eine fehlende Klasse führt ja zum Beispiel dazu, dass es unmöglich wird, den Code weiter auszuführen.
 
Zurück