Frage

Gibt es eine Möglichkeit, Ausnahmen von einem SPL -Autoloader in PHP zu werfen, falls es fehlschlägt? Es scheint nicht unter PHP 5.2.11 zu funktionieren.

class SPLAutoLoader{

    public static function autoloadDomain($className) {
        if(file_exists('test/'.$className.'.class.php')){
            require_once('test/'.$className.'.class.php');
            return true;
        }       

        throw new Exception('File not found');
    }

} //end class

//start
spl_autoload_register( array('SPLAutoLoader', 'autoloadDomain') );

try{
    $domain = new foobarDomain();
}catch(Exception $c){
    echo 'File not found';
}

Wenn der obige Code aufgerufen wird, gibt es keine Anzeichen für eine Ausnahme. Stattdessen erhalte ich einen Standard "Fatal ERROR: Klasse" Foobardomain ", das in Bla nicht zu finden ist. Und die Ausführung des Skripts endet.

War es hilfreich?

Lösung

Dies ist kein Fehler, es ist eine Designentscheidung:

Notiz: Ausnahmen eingeworfen __autoload Funktion kann nicht in der gefangen werden catch Blockieren Sie und führt zu einem tödlichen Fehler.

Der Grund dafür ist, dass es möglicherweise mehr als einen Autoload -Handler gibt. In diesem Fall möchten Sie nicht, dass der erste Handler eine Ausnahme auswirft und den Second -Handler umgeht. Sie möchten, dass Ihr Second -Handler eine Chance hat, seine Klassen zu automatisieren. Wenn Sie eine Bibliothek verwenden, die die Autoloading -Funktion verwendet, möchten Sie nicht, dass sie Ihren Autoload -Handler umgeht, da sie Ausnahmen in den Autoloader werfen.

Wenn Sie prüfen möchten, ob Sie eine Klasse instanziieren können oder nicht, dann verwenden Sie dann class_exists und passieren true als zweites Argument (oder weglassen, true ist der Standard):

if (class_exists('foobarDomain', $autoload = true)) {
    $domain = new foobarDomain();
} else {
    echo 'Class not found';
}

Andere Tipps

Nach den Kommentaren in Die Dokumentation für spl_autoload_register, Es ist möglich, eine andere Funktion vom Autoloader aufzurufen, was wiederum die Ausnahme auswerfen würde.

class SPLAutoLoader{

    public static function autoloadDomain($className) {
        if(file_exists('test/'.$className.'.class.php')){
            require_once('test/'.$className.'.class.php');
            return true;
        }       
        self::throwFileNotFoundException();
    }

    public static function throwFileNotFoundException()
    {
        throw new Exception('File not found');
    }

} //end class

//start
spl_autoload_register( array('SPLAutoLoader', 'autoloadDomain') );

try{
    $domain = new foobarDomain();
}catch(Exception $c){
    echo 'File not found';
}

Hier ist ein vollwertiges Fabrikobjekt, das automatische Ladung, Namensunterstützung, Anruflinge aus nichtstatischen Instanzen (mit variablen Pfaden), Handhabung von Ladefehlern und benutzerdefinierten Ausnahmen zeigt.

abstract class AbstractFactory implements \ArrayAccess
{
    protected $manifest;
    function __construct($manifest)
    {
        $this->manifest = $manifest;
    }

    abstract function produce($name);

    public function offsetExists($offset)
    {
        return isset($this->manifest[$offset]);
    }

    public function offsetGet($offset)
    {
        return $this->produce($offset);
    }
    //implement stubs for other ArrayAccess funcs
}


abstract class SimpleFactory extends AbstractFactory {

    protected $description;
    protected $path;
    protected $namespace;

    function __construct($manifest, $path, $namespace = "jj\\") {
        parent::__construct($manifest);
        $this->path = $path;
        $this->namespace = $namespace;
        if (! spl_autoload_register(array($this, 'autoload'), false)) //throws exceptions on its own, but we want a custom one
            throw new \RuntimeException(get_class($this)." failed to register autoload.");
    }

    function __destruct()
    {
        spl_autoload_unregister(array($this, 'autoload'));
    }

    public function autoload($class_name) {
        $file = str_replace($this->namespace, '', $class_name);
        $filename = $this->path.$file.'.php';
        if (file_exists($filename))
            try {
                require $filename; //TODO add global set_error_handler and try clause to catch parse errors
            } catch (Exception $e) {} //autoload exceptions are not passed by design, nothing to do
    }

    function produce($name) {
        if (isset($this->manifest[$name])) {
            $class = $this->namespace.$this->manifest[$name];
            if (class_exists($class, $autoload = true)) {
                return new $class();
            } else throw new \jj\SystemConfigurationException('Factory '.get_class($this)." was unable to produce a new class {$class}", 'SYSTEM_ERROR', $this);
//an example of a custom exception with a string code and data container

        } else throw new LogicException("Unknown {$this->description} {$name}.");
    }

    function __toString() //description function if custom exception class wants a string explanation for its container
    {
        return $this->description." factory ".get_class($this)."(path={$this->path}, namespace={$this->namespace}, map: ".json_encode($this->manifest).")";
    }

}

und schließlich ein Beispiel:

namespace jj;
require_once('lib/AbstractFactory.php');
require_once('lib/CurrenciesProvider.php'); //base abstract class for all banking objects that are created

class CurrencyProviders extends SimpleFactory
{
    function __construct()
    {
        $manifest = array(
          'Germany' => 'GermanBankCurrencies',
          'Switzerland' => 'SwissBankCurrencies'
        );

        parent::__construct($manifest, __DIR__.'/CurrencyProviders/', //you have total control over relative or absolute paths here
       'banks\');
        $this->description = 'currency provider country name';
    }


}

mach jetzt

$currencies_cache = (new \jj\CurrencyProviders())['Germany'];

oder

$currencies_cache = (new \jj\CurrencyProviders())['Ukraine'];

Logicexception ("Unbekannter Währungsanbieter Ländername Ukraine")

Wenn es keine schweizerischen Datei in /CurrencyProviders /, gibt, /,,,

jj systemConfigurationException ('Factory JJ CurrencyProviders konnte keine neuen Klassenbanken Swisscurrencies produzieren. , Namespace = Banks , Karte: {"Deutschland": "GermanBankcurrencies", "Schweiz": "Swissbankcurrencies"} ')

Mit genügend Anstrengung kann diese Fabrik erweitert werden, um analysende Fehler zu fangen (Wie kann man einen Fehler von Request () oder include () in PHP fangen?) und Argumente an Konstruktoren weitergeben.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top