PHP: инструкция "или" при сбое инструкции: как выбросить новое исключение?

Все здесь должны знать "или" statemens, обычно приклеенные к команде die():

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

В большинстве случаев мы видим что-то вроде:

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

Однако я не могу понять, как работает этот оператор или.

Я хотел бы создать новое исключение вместо die(), но:

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

Не работает, и ни

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

Единственный способ, которым я нашел это, - это ужасная мысль:

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

Но есть ли способ выбросить новое исключение непосредственно после оператора 'или'?

Или этот тип структуры является обязательным (я вообще не выполняю функцию ThrowMe):

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

Изменить: я хочу, чтобы избежать использования проверки if() каждой потенциально опасной операции, например:

#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.

Ответы

Ответ 1

or - это просто логический оператор, и он аналогичен ||.

Общий трюк

mysql_query() or die();

можно было бы также написать

mysql_query() || die();

Что здесь происходит, так это оператор "логический" или "(какой бы вы ни выбрали) пытается определить, оценивает ли операнд TRUE. Это означает, что операнды должны быть выражениями, которые могут быть выбраны как логические.

Итак, причина

bar() or throw new Exception();

является незаконным, потому что

(boolean)throw new Exception();

также является незаконным. По сути, процесс выброса исключения не генерирует возвращаемое значение для проверки оператора.

Но вызов функции генерирует возвращаемое значение для проверки оператора (никакое явное возвращаемое значение не приведет к возврату функции NULL, возвращающей FALSE), поэтому она работает для вас, когда вы включаете исключение в функции.

Надеюсь, что это поможет.

Ответ 2

Почему bar() и bb() не исключают исключения? В PHP Exceptions bubble up, поэтому нет необходимости бросать исключение в функцию/метод, где вы вызываете bar()/bb(). Эти исключения могут быть выбраны bar()/bb(). Если вы хотите сделать другое исключение, вы можете просто сделать:

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

Ответ 3

Я думаю, вы хотите использовать что-то вроде последней структуры, хотя на самом деле нет смысла использовать исключения для этого:

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

За комментарий - я не думаю, что вы можете сделать это в одной строке (т.е. без проверки if(!$foo)), и я согласен с тем, что метод исключения исключений довольно ужасен. Лично я предпочитаю объяснение:

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

но это личное предпочтение. Если вам нужна однострочная вещь, я думаю, вам придется пойти с опцией функции исключения исключений.

Я предполагаю, что это ограничение, вероятно, связано с PHP-динамической типизацией, оно может передавать результаты вызова функции в условное, но не из результатов throw.

Ответ 4

Здесь однострочное решение без дополнительной функции:

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

Ответ 5

Вы также можете создать собственный класс исключений и использовать его вместо статического конструктора вместо throw new Exception().

Класс исключений:

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

Использование:

try {

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

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

Примечание

Если вы используете PHP 7 и выше, вы можете переименовать статический метод doThrow() просто throw(), поскольку в PHP 7 и выше разрешено использовать зарезервированные ключевые слова в качестве имен методов.