PHP: оператор 'или' в инструкции завершается неудачно: как вызвать новое исключение? - PullRequest
17 голосов
/ 31 июля 2009

Каждый здесь должен знать «или» государственных деятелей, обычно приклеенных к команде 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();
}

Edit : я действительно хочу избежать использования 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.

Ответы [ 7 ]

31 голосов
/ 31 июля 2009

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

Общая хитрость

mysql_query() or die();

с таким же успехом можно написать

mysql_query() || die();

Здесь происходит то, что «логический» или «оператор» (какой бы вы ни выбрали) пытается определить, оценивает ли какой-либо из операндов значение ИСТИНА. Это означает, что операнды должны быть выражениями, которые могут быть приведены как логические значения.

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

bar() or throw new Exception();

незаконно, потому что

(boolean)throw new Exception();

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

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

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

2 голосов
/ 09 марта 2018

Решение, которое я нашел, которое может заменить "or die ()" везде, состоит в том, чтобы обернуть бросок анонимной функцией, которая вызывается немедленно call_user_func:

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

Вы можете увидеть, что это работает, выполнив это на фиктивном скрипте:

false or call_user_func(function(){throw new Exception("ERROR");});
2 голосов
/ 31 июля 2009

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

function foo() {
    try {
        $bar = bar();
    } catch (BarException) {
        throw new FooException;
    }
}
1 голос
/ 27 июля 2018

Я просто определил функцию toss для этого.

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

Поскольку информация о файле / строке / стеке собирается, когда исключение составляет , сконструировано (new), а не выброшено (throw), это не влияет на стек вызовов.

Так что вы можете просто сделать это.

something() or toss(new Exception('something failed'));
1 голос
/ 27 ноября 2015

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

if (!($foo = bar())) throw new Exception('We have a problem here');
1 голос
/ 31 июля 2009

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

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

0 голосов
/ 12 апреля 2017

Вы также можете создать собственный класс исключений и использовать его метод статического конструктора вместо 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 и выше разрешено использовать зарезервированные ключевые слова в качестве имен методов.

...