Domanda

Esiste un modo per generare eccezioni da un caricatore automatico SPL in PHP nel caso in cui fallisca?Non sembra funzionare con PHP 5.2.11.

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';
}

Quando viene chiamato il codice precedente, non vi è alcun segno di eccezione, invece ottengo un "Errore irreversibile:Classe 'foobarDomain' non trovata in bla".E l'esecuzione dello script termina.

È stato utile?

Soluzione

Questo non è un bug, lo è una decisione progettuale:

Nota:Eccezioni inserite __autoload la funzione non può essere catturata in catch si blocca e genera un errore fatale.

Il motivo è che potrebbero esserci più gestori di caricamento automatico, nel qual caso non si desidera che il primo gestore lanci un'eccezione e ignori il secondo gestore.Vuoi che il tuo secondo gestore abbia la possibilità di caricare automaticamente le sue classi.Se utilizzi una libreria che fa uso della funzione di caricamento automatico, non vuoi che ignori il gestore di caricamento automatico perché genera eccezioni all'interno del caricatore automatico.

Se vuoi verificare se puoi istanziare o meno una classe, usa class_exists e passare true come secondo argomento (o lasciarlo fuori, true è l'impostazione predefinita):

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

Altri suggerimenti

Secondo i commenti in la documentazione per spl_autoload_register , è possibile chiamare un'altra funzione dal caricatore automatico, che a sua volta generare l'eccezione.

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';
}

Ecco un oggetto vero e proprio stabilimento che dimostra auto-caricamento, i namespace supporto, callable dalle istanze non statici (con percorsi variabili), la gestione degli errori di carico e eccezioni personalizzate.

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).")";
    }

}

e, infine, un esempio:

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';
    }


}

fare ora

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

o

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

LogicException ( "moneta sconosciuta fornitore Paese Nome Ucraina")

Se non ci sono file SwissCurrencies.php in / CurrencyProviders /,

  

\ jj \ SystemConfigurationException ( "JJ \ CurrencyProviders fabbrica è stata in grado di produrre una nuova classe di banche \ SwissCurrencies dati Debug:. Nome del provider moneta paese fabbrica jj \ CurrencyProviders (path = / var / www / hosting / sito / ... / CurrencyProviders /, namespace = banche \, mappa: { "Germania": "GermanBankCurrencies", "Svizzera": "SwissBankCurrencies"} ')

Con uno sforzo sufficiente questa fabbrica può essere esteso per la cattura di analizzare gli errori ( Come catturare l'errore di require () o includere () in PHP? ) e passare gli argomenti per i costruttori.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top