2010-12-12 13 views
18

Nell'esempio seguente, se la classe non esiste, voglio rilevare l'errore e creare invece una classe Null.Perché PHP non rileva un errore "Classe non trovata"?

Ma nonostante le mie dichiarazioni try/catch, PHP mi dice semplicemente Class 'SmartFormasdfasdf' not found.

Come posso ottenere PHP per rilevare l'errore "classe non trovata"?

<?php 
class SmartFormLogin extends SmartForm { 
    public function render() { 
     echo '<p>this is the login form</p>'; 
    } 
} 

class SmartFormCodeWrapper extends SmartForm { 
    public function render() { 
     echo '<p>this is the code wrapper form</p>'; 
    } 
} 

class SmartFormNull extends SmartForm { 
    public function render() { 
     echo '<p>the form "' . htmlentities($this->idCode) . '" does not exist</p>'; 
    } 
} 

class SmartForm { 

    protected $idCode; 

    public function __construct($idCode) { 
     $this->idCode = $idCode; 
    } 

    public static function create($smartFormIdCode) { 
     $className = 'SmartForm' . $smartFormIdCode; 
     try { 
      return new $className($smartFormIdCode); 
     } catch (Exception $ex) { 
      return new SmartFormNull($smartformIdCode); 
     } 
    } 
} 

$formLogin = SmartForm::create('Login'); 
$formLogin->render(); 
$formLogin = SmartForm::create('CodeWrapper'); 
$formLogin->render(); 
$formLogin = SmartForm::create('asdfasdf'); 
$formLogin->render(); 
?> 

Soluzione:

Grazie @Mchl, questo è come ho risolto allora:

public static function create($smartFormIdCode) { 
    $className = 'SmartForm' . $smartFormIdCode; 
    if(class_exists($className)) { 
    return new $className($smartFormIdCode); 
    } else { 
    return new SmartFormNull($smartFormIdCode); 
    } 
} 

risposta

36

Perché è un errore fatale. Utilizzare la funzione class_exists() per verificare se la classe esiste.

Inoltre: PHP non è Java, a meno che non si sia ridefinito il gestore degli errori di default, esso genera errori e non genera eccezioni.

+2

ho dimenticato La funzionalità PHP try/get ti aiuta semplicemente a creare la tua gestione delle eccezioni, consentendo di lanciare i tuoi errori, ma di conseguenza non cattura gli stessi errori come in C#/Java. –

+1

Vedere http://www.php.net/manual/en/class.errorexception.php per esempio su come "riscrivere" tutti gli errori (tranne quelli fatali) nelle eccezioni. Inoltre, come suggerito da altri, dal 5.3 potrebbe essere utile utilizzare il caricatore automatico per generare un'eccezione quando non viene trovato un file contenente una determinata classe. – Mchl

+2

@Edward - certamente ti permette di catturare * le eccezioni *, ma quasi tutto ciò che è nativo di PHP non genera eccezioni, solo errori. Puoi ovviare a questo problema definendo il tuo * error_handler * e facendo in modo di lanciare Eccezioni usando ErrorException (vedi http://au.php.net/errorexception e l'esempio lì). Questo cambia facilmente il sistema di errore nativo di PHP in un utile sistema basato su Eccezione che funziona molto bene con throw/try/catch ecc. –

5

È necessario utilizzare class_exists per verificare se la classe esiste prima di provare e istanziarla.

Per inciso, se si utilizza un caricatore automatico di classe, assicurarsi di impostare il secondo arg su true.

0

Perché php emette un errore fatale quando si cerca di creare un nuovo oggetto di una classe non esistente. Per farlo funzionare avrai bisogno della funzione php> = 5.3 e autoload, dove dovresti cercare di cercare il file con la definizione della classe o lanciare l'eccezione personalizzata.

+0

a) autoload è il modo sbagliato per farlo - vedi http: //au.php.net/manual/en/function.spl-autoload-register.php eb) non richiede PHP 5.3 –

+1

Le eccezioni di lancio nel caricatore automatico richiedono effettivamente 5.3. E non c'è nulla di "sbagliato" a questo proposito finché sai cosa stai facendo (cioè è un po 'sciocco lanciare un'eccezione quando ci sono più autoloader nella coda del caricamento automatico). – Mchl

+0

@El Yobo - puoi elaborare cosa c'è di sbagliato nel caricamento automatico?la funzione spl fa lo stesso, unica differenza è che ti permette di fornire più funzioni da eseguire nella ricerca del file corretto. Ans come per b), come ha detto Mchl, avrai comunque bisogno di php 5.3 per lanciare un'eccezione. –

10

Vecchia domanda, ma in PHP 7 questa è un'eccezione intercettabile. Anche se continuo a pensare che lo class_exists($class) sia un modo più esplicito per farlo. Tuttavia, si potrebbe fare un blocco try/catch utilizzando il nuovo tipo di \Throwable eccezione:

$className = 'SmartForm' . $smartFormIdCode; 
try { 
    return new $className($smartFormIdCode); 
} catch (\Throwable $ex) { 
    return new SmartFormNull($smartformIdCode); 
} 
+1

In alternativa, se vuoi essere più specifico con ciò che stai catturando, puoi invece prendere il tipo \ Error (testato per funzionare in PHP 7.1). Ciò renderebbe il tuo codice più fragile per cambiare il modo in cui il linguaggio PHP si evolve, ma anche meno probabilità di catturare qualcosa che non avevi intenzione di catturare. Se hai dei buoni test automatici, dovresti essere in grado di farla franca con la versione più specifica perché i tuoi test fallirebbero se PHP improvvisamente iniziasse a lanciare un tipo diverso per questo. –

0

php> = 7,0

php può prendere 'classe non trovata' come Throwable

try { 
     return new $className($smartFormIdCode); 
} catch (\Throwable $ex) { 
     return new SmartFormNull($smartformIdCode); 
}