Pregunta

Todos aquí deberían conocer los estados 'o', generalmente pegados a un comando die ():

$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 ninguno

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

La única forma de 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 (no me gusta la función ThrowMe):

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

Editar : lo que realmente quiero es evitar el uso de un if () compruebo cada operación peligrosa potencial 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.
¿Fue útil?

Solución

o es solo un operador lógico , y es análogo a || .

El truco común de

mysql_query() or die();

también podría escribirse

mysql_query() || die();

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

Entonces, 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 verifique.

Pero llamar a una función genera un valor de retorno para que el operador lo verifique (no se generará ningún valor de retorno explícito en la función que devuelve NULL que se convierte como FALSE ) por lo que funciona para ti cuando envuelves la excepción lanzando una función.

Espero que eso ayude.

Otros consejos

¿Por qué bar () y bb () no arrojan las excepciones? En PHP, las excepciones aparecen, por lo que no es necesario lanzar la excepción en la función / método donde se llama bar () / bb () . Estas excepciones pueden ser lanzadas por bar () / bb () . En caso de que desee lanzar otra excepción, simplemente puede hacer:

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

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

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

Puede ver que funciona ejecutando esto en un script ficticio:

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

Creo que quieres usar algo como la última estructura, aunque realmente no tiene sentido usar excepciones para eso:

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

Por comentario: no creo que pueda hacerlo en una sola línea (es decir, sin la verificación if (! $ foo) ), y estoy de acuerdo en que el método de lanzamiento de excepciones es bastante horrible . Personalmente, prefiero lo explícito de:

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

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

Supongo que esta limitación probablemente se deba al tipo de escritura dinámica de PHP, puede convertir los resultados de una llamada de función a condicional, pero no los resultados de un throw .

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

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

Simplemente he definido la función toss para esto.

function toss(Exception $exception): void
{
    throw $exception;
}

Debido a que la información de archivo / línea / pila se captura cuando la excepción se construye ( new ) no se lanza ( throw ) esto no ' t interferir con la pila de llamadas.

Entonces puedes hacer esto.

something() or toss(new Exception('something failed'));

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

Clase de 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();
}
  

Nota

     

Si está utilizando PHP 7 y superior, puede cambiar el nombre del método estático doThrow () para simplemente throw () , ya que en PHP 7 y superior está permitido usar palabras clave reservadas como nombres de métodos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top