PHP: оператор 'или' при ошибке инструкции: как создать новое исключение?

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

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

Или такая структура обязательна (я вообще не использую функцию 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.

person Strae    schedule 31.07.2009    source источник
comment
Вы имели в виду !$foo в последнем блоке кода?   -  person Dominic Rodger    schedule 31.07.2009


Ответы (7)


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

Обычная уловка

mysql_query() or die();

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

mysql_query() || die();

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

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

bar() or throw new Exception();

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

(boolean)throw new Exception();

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

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

person Peter Bailey    schedule 31.07.2009
comment
or не аналогичен ||. Первый имеет более низкий приоритет, чем присвоение и сравнение. У последнего выше. Это очень важное различие, потому что $f = one() or two() работает совсем не так, как $f = one() || two(). us3.php.net/manual/en/language.operators.precedence. php - person Explosion Pills; 12.07.2011
comment
Да, это. Аналогичный не означает идентичный. При этом ваше разъяснение приветствуется: D - person Peter Bailey; 12.07.2011
comment
Ошибка, которую вызывает неправильный синтаксис, - это ошибка анализа: синтаксическая ошибка, неожиданный T_THROW. - person Jeff Clemens; 05.06.2014

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

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

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

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

something() or toss(new Exception('something failed'));
person Dan Lugg    schedule 27.07.2018

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

function foo() {
    try {
        $bar = bar();
    } catch (BarException) {
        throw new FooException;
    }
}
person Ionuț G. Stan    schedule 31.07.2009
comment
Да, чувак, ты прав, но как насчет, например, функций базы данных? mysql_query () / pg_query ()? Для этого я должен использовать либо проверку if (), либо ужасную функцию ThrowMe. Я просто хочу знать, возможно ли выполнение id direclty без ThrowMe () - person Strae; 31.07.2009
comment
@DaNieL: вы можете использовать PDO для доступа к БД, который сам может генерировать исключения. - person Tom Haigh; 31.07.2009
comment
Что ж, это невозможно. Я сам пробовал некоторое время назад и без шансов. PHP - полезный инструмент, но он также имеет один из самых глупых парсеров и интерпретаторов в мире. - person Ionuț G. Stan; 31.07.2009
comment
В любом случае, если вы стремитесь абстрагироваться от своего приложения, у вас не должно быть много вызовов mysql_query() или чего-то еще. Вы должны создать свой собственный уровень утилит поверх PHP, чтобы вы могли замаскировать все его особенности. - person Ionuț G. Stan; 31.07.2009
comment
@Tom: Извините, я много пробовал PDO, и я не очень его обдумываю, это пример мотивации: stackoverflow.com/questions/833510/ Я создаю свою« облегченную, маленькую и быструю »интерпретацию PDO;) @lonut: значит, у нас есть еще кое-что, что нужно добавить в список пожеланий php6? - person Strae; 31.07.2009
comment
@DaNieL, в списке желаний PHP6 было бы много чего, но я не вижу внутренних компонентов, учитывая, что многие из них. В настоящее время во внутреннем списке рассылки обсуждается RFC, который предлагает замену ошибок исключениями во встроенных функциях / классах. И очень маловероятно, что его примут. - person Ionuț G. Stan; 31.07.2009

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

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

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

false or call_user_func(function(){throw new Exception("ERROR");});
person Harrison3000    schedule 09.03.2018

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

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

person Dominic Rodger    schedule 31.07.2009
comment
Нет, не хочу. Эхо просто, например, в реальной жизни никогда не повторяет сообщение об ошибке или код, а обрабатывает их по-другому. Я хочу точно избегать проверки if (! $ Foo) каждый раз. - person Strae; 31.07.2009

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

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

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

person Andrey Rudenko    schedule 12.04.2017