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

StackOverflow https://stackoverflow.com/questions/1211237

Вопрос

Каждый здесь должен знать операторы «или», обычно прикрепляемые к команде 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.
Это было полезно?

Решение

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

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

mysql_query() or die();

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

mysql_query() || die();

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

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

bar() or throw new Exception();

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

(boolean)throw new Exception();

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

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

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

Другие советы

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top