PHP: 'or' statement on instruction fail: how to throw a new exception?

天涯浪子 提交于 2019-11-27 22:47:31

or is just a logical operator, and it's analogous to ||.

The common trick of

mysql_query() or die();

could just as well be written

mysql_query() || die();

What happens here is the "logical or" operator (whichever you choose) is trying to determine if either operand evaluates to TRUE. This means the operands must be expressions that can be cast as a boolean.

So, the reason

bar() or throw new Exception();

is illegal, is because

(boolean)throw new Exception();

is also illegal. In essence, the process of throwing an exception doesn't generate a return value for the operator to check.

But calling a function does generate a return value for the operator to check (no explicit return value will result int the function returning NULL which casts as FALSE) which is why it works for you when you wrap exception throwing in a function.

Hope that helps.

Why don't bar() and bb() throw the exceptions? In PHP Exceptions bubble up, so there's no need to throw the exception in the function/method where you call bar()/bb(). These exceptions may be thrown by bar()/bb(). In case you want to throw another exception, you can simply do:

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

A solution I found that can replace "or die()" everywhere is to wrap the throw with a anonymous function that gets called immediately by call_user_func:

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

You can see that it works by executing this on a dummy script:

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

I think you want to use something like the last structure, although there's really no point in using exceptions for that:

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

Per comment - I don't think you can do that in a single line (i.e. without the if(!$foo) check), and I agree that the exception throwing method is pretty horrible. Personally, I prefer the explicitness of:

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

but that's a personal preference. If you want the single-line thing, I think you'll have to go with your exception-throwing function option.

I guess this limitation is probably down to PHP's dynamic-typing stuff, it can cast the results of a function call to a conditional, but not the results of a throw.

Here's a single-line solution without the extra function:

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

I've simply defined the function toss for this.

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

Because the file/line/stack information is captured when the exception is constructed (new) not thrown (throw) this doesn't interfere with the call stack.

So you can just do this.

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

You can also create a custom exception class and use it's static constructor method instead of throw new Exception() construction.

Exception class:

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

Usage:

try {

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

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

Note

If you are using PHP 7 and higher - you can rename static method doThrow() to simply throw(), since in PHP 7 and higher it's allowed to use reserved keywords as method names.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!