2010-12-12 18 views
18

En el siguiente ejemplo, si la clase no existe, quiero detectar el error y crear una clase Null en su lugar.¿Por qué PHP no detecta un error de "Clase no encontrada"?

Pero a pesar de mis declaraciones try/catch, PHP simplemente me dice Class 'SmartFormasdfasdf' not found.

¿Cómo puedo obtener PHP para detectar el error de "clase no encontrada"?

<?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(); 
?> 

Solución:

Gracias @Mchl, esto es cómo lo resolví a continuación:

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

Respuesta

36

Debido a que es un error fatal. Use la función class_exists() para verificar si existe clase.

También: PHP no es Java, a menos que haya redefinido el manejador de error predeterminado, generará errores y no arrojará excepciones.

+2

olvidé La función PHP try/get simplemente lo ayuda a construir su propio manejo de excepciones permitiéndole arrojar sus propios errores, pero no detecta los mismos errores como en C#/Java. –

+1

Consulte http://www.php.net/manual/en/class.errorexception.php, por ejemplo, sobre cómo 'reescribir' todos los errores (excepto los fatales) en excepciones. Además, como otros sugirieron, desde 5.3 es posible que desee utilizar el autocargador para lanzar una excepción cuando no se encuentre un archivo que contenga la clase dada. – Mchl

+2

@Edward - ciertamente le permite capturar * excepciones *, pero casi todo lo nativo de PHP no arroja excepciones, solo errores. Puede solucionar esto fácilmente definiendo su propio * error_handler * y haciendo que arroje Excepciones usando ErrorException (vea http://au.php.net/errorexception y el ejemplo allí). Esto fácilmente cambia el sistema de error nativo de PHP a un sistema basado en Exception que funciona muy bien con throw/try/catch etc. –

5

Debe usar class_exists para ver si la clase existe antes de intentar crear una instancia.

Por cierto, si está utilizando un autocargador de clase, asegúrese de establecer el segundo arg en verdadero.

0

Porque php emite un error fatal al escribir para crear un nuevo objeto de clase no existente. Para hacerlo funcionar necesitará la función php> = 5.3 y autoload, donde debería intentar buscar el archivo con definición de clase o lanzar su excepción personalizada.

+0

a) autocarga es la forma incorrecta de hacerlo - ver http: //au.php.net/manual/en/function.spl-autoload-register.php yb) no requiere PHP 5.3 –

+1

Lanzar excepciones en autocargador sí requiere 5.3. Y no hay nada "malo" al respecto, siempre que sepa lo que está haciendo (es decir, es un poco tonto hacer una excepción cuando hay más cargadores automáticos en la cola de autocarga). – Mchl

+0

@El Yobo - ¿Puedes explicar qué está mal con la carga automática?La función spl hace lo mismo, la única diferencia es que te permite proporcionar más funciones para ejecutar en la búsqueda del archivo correcto. Resp. En cuanto a b), como dijo Mchl, aún necesitarás php 5.3 para que arroje una excepción. –

10

Pregunta anterior, pero en PHP7 esta es una excepción atrapable. Aunque todavía creo que el class_exists($class) es una forma más explícita de hacerlo. Sin embargo, se podría hacer un bloque try/catch utilizando el nuevo tipo \Throwable excepción:

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

Alternativamente, si desea hacerse más específico con lo que está capturando, puede detectar el tipo \ Error en su lugar (probado para trabajar en PHP 7.1). Esto haría que tu código sea más frágil a los cambios en la evolución del lenguaje PHP, pero también es menos probable que atrape algo que no pretendías atrapar. Si tiene buenas pruebas automatizadas, debería poder salirse con la versión más específica porque sus pruebas fallarían si PHP repentinamente comenzara a lanzar un tipo diferente para esto. –

0

PHP> = 7.0

PHP puede coger 'clase no encontrado' como Throwable

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