2009-07-31 11 views
15

Aquí todo el mundo debe conocer los 'o' statemens, generalmente pegados a un troquel() comando:PHP: la instrucción 'o' en la instrucción falla: ¿cómo lanzar una nueva excepción?

$foo = bar() or die('Error: bar function return false.'); 

La mayoría de las veces vemos algo como:

mysql_query('SELECT ...') or die('Error in during the query'); 

Sin embargo, no puedo entender cómo funciona exactamente esa declaración 'o'.

me gustaría lanzar una nueva excepción en lugar de die(), pero:

try{ 
    $foo = bar() or throw new Exception('We have a problem here'); 

no funciona, y tampoco

$foo = bar() or function(){ throw new Exception('We have a problem here'); } 

La única manera que he encontrado para hacerlo es este horrible pensamiento:

function ThrowMe($mess, $code){ 
    throw new Exception($mess, $code); 
} 
try{ 
    $foo = bar() or ThrowMe('We have a problem in here', 666); 
}catch(Exception $e){ 
    echo $e->getMessage(); 
} 

¿Pero hay una manera de lanzar una nueva excepción directamente después de la declaración 'o'?

O este tipo de estructura es obligatoria (i no liek la función ThrowMe en absoluto):

try{ 
    $foo = bar(); 
    if(!$foo){ 
     throw new Exception('We have a problem in here'); 
    } 
}catch(Exception $e){ 
    echo $e->getMessage(); 
} 

Editar: lo que quiero es realmente para evitar el uso de un if() comprobar cada potencial operación peligrosa que hago, por ejemplo:

#The echo $e->getMessage(); is just an example, in real life this have no sense! 
try{ 
    $foo = bar(); 
    if(!$foo){ 
     throw new Exception('Problems with bar()'); 
    } 
    $aa = bb($foo); 
    if(!$aa){ 
     throw new Exception('Problems with bb()'); 
    } 
    //...and so on! 
}catch(Exception $e){ 
    echo $e->getMessage(); 
} 

#But i relly prefer to use something like: 

try{ 
    $foo = bar() or throw new Exception('Problems with bar()'); 
    $aa = bb($foo) or throw new Exception('Problems with bb()'); 
    //...and so on! 
}catch(Exception $e){ 
    echo $e->getMessage(); 
} 

#Actually, the only way i figured out is: 

try{ 
    $foo = bar() or throw new ThrowMe('Problems with bar()', 1); 
    $aa = bb($foo) or throw new ThrowMe('Problems with bb()', 2); 
    //...and so on! 
}catch(Exception $e){ 
    echo $e->getMessage(); 
} 

#But i'll love to thro the exception directly instead of trick it with ThrowMe function. 
+0

¿Se refiere a '$ foo' en su último bloque de código? –

+0

Lo siento, sí ... mi mal – Strae

Respuesta

27

or es sólo un logical operator, y es análoga a ||.

El truco común de

mysql_query() or die(); 

podría muy bien ser escrito

mysql_query() || die(); 

Lo que sucede aquí es el operador "lógico o" (lo que usted elija) está tratando de determinar si alguno de los operandos evalúa a VERDADERO. Esto significa que los operandos deben ser expresiones que se pueden convertir como booleanos.

Por lo tanto, la razón

bar() or throw new Exception(); 

es ilegal, es porque

(boolean)throw new Exception(); 

también es ilegal. En esencia, el proceso de lanzar una excepción no genera un valor de retorno para que el operador lo compruebe.

Pero llamar a una función qué generar un valor de retorno para el operador comprobar (sin valor de retorno explícito dará como resultado int retorno de la función NULL lo que arroja como FALSE) por lo que funciona para usted cuando usted envuelve excepción tirar Una función.

Espero que ayude.

+0

Claro que me ayuda - explicó por qué eso no funciona;) – Strae

+1

'o' no es análogo a' || '. El primero tiene una prioridad menor que la asignación y la comparación. Este último tiene más alto. Esta es una distinción muy importante porque '$ f = one() o two()' funciona de forma muy diferente a '$ f = one() || dos() '. http://us3.php.net/manual/en/language.operators.precedence.php –

+1

Sí lo es. "Análogo" no significa "idéntico". Dicho esto, su aclaración es bienvenida: D –

1

creo que desea utilizar algo así como la última estructura, aunque no hay realmente ningún punto en el uso de excepciones para ello:

$foo = bar(); 
if(!$foo){ 
    echo 'We have a problem in here'; 
} 

Por comentario: no creo que pueda hacer eso en una sola línea (es decir sin el cheque if(!$foo)), y estoy de acuerdo en que el método de lanzamiento de excepción es bastante horrible. Personalmente, prefiero la explicitud de:

$foo = bar(); 
if(!$foo){ 
    throw new Exception('We have a problem in here'); 
} 

pero eso es una preferencia personal. Si quieres algo de una sola línea, creo que tendrás que ir con tu opción de función de lanzamiento de excepción.

Supongo que esta limitación probablemente se deba a las características de tipado dinámico de PHP, puede convertir los resultados de una llamada de función en un condicional, pero no los resultados de un throw.

+0

No, no quiero. El eco es solo por ejemplo, en la vida real nunca se hace eco del mensaje de error o el código, pero los maneja de manera diferente. Lo que quiero es exactamente evitar el control if (! $ Foo) cada vez. – Strae

+0

OK, he actualizado mi respuesta. –

2

¿Por qué no bar() y bb() arrojan las excepciones? En PHP, las excepciones aumentan, por lo que no es necesario lanzar la excepción en la función/método al que llama al bar()/bb(). Estas excepciones pueden ser lanzadas por bar()/bb(). En caso de que quiera lanzar otra excepción, sólo tiene que hacer:

function foo() { 
    try { 
     $bar = bar(); 
    } catch (BarException) { 
     throw new FooException; 
    } 
} 
+0

Sí, hombre, tienes razón, pero ¿qué tal, por ejemplo, las funciones de la base de datos? mysql_query()/pg_query()? Para estos debo usar o la comprobación if(), o la función ThrowMe horrible ... solo quiero saber si es posible hacer la instrucción id sin ThrowMe() – Strae

+1

@DaNieL: Podría usar PDO para acceso a bases de datos que pueda arrojar excepciones . –

+1

Bueno, no es posible. Lo intenté hace un tiempo y no tuve oportunidad. PHP es una herramienta útil, pero también tiene uno de los intérpretes y analizadores más estúpidos del mundo. –

1

Aquí es una solución de una sola línea y sin la función adicional:

if (!($foo = bar())) throw new Exception('We have a problem here'); 
0

También puede crear una clase de excepción personalizada y utilizar su método constructor estático en lugar de throw new Exception() construcción. clase

Excepción:

class CustomException extends Exception { 
    static public function doThrow($message = "", $code = 0, Exception $previous = null) { 
    throw new Exception($message, $code, $previous); 
    } 
} 

Uso:

try { 

    $foo = bar() or CustomException::doThrow('Problems with bar()'); 
    $aa = bb($foo) or CustomException::doThrow('Problems with bb()'); 

} catch(Exception $e){ 
    echo $e->getMessage(); 
} 

Note

If you are using PHP 7 and higher - you can rename static method doThrow() to simply throw() , since in PHP 7 and higher it's allowed to use reserved keywords as method names.

1

Una solución que encontré que puede reemplazar "o morir()" en todas partes es envolver de banda con una función anónima que se llama inmediatamente por call_user_func:

call_user_func(function(){ 
    throw new Exception("ERROR"); 
}); 

Se puede ver que funciona mediante la ejecución de este en un guión ficticio:

false or call_user_func(function(){throw new Exception("ERROR");}); 
Cuestiones relacionadas