PHP:命令失敗の「または」ステートメント:新しい例外をスローする方法
-
06-07-2019 - |
質問
ここにいるすべての人は、通常はdie()コマンドに接着された「または」政治家を知っている必要があります:
$foo = bar() or die('Error: bar function return false.');
ほとんどの場合、次のように表示されます:
mysql_query('SELECT ...') or die('Error in during the query');
ただし、その 'or'ステートメントがどのように機能するかを理解できません。
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.
解決
または
は単なる論理演算子、および ||
に類似しています。
の一般的なトリック
mysql_query() or die();
同様に記述できます
mysql_query() || die();
ここで起こるのは、「論理的または」演算子(どちらを選択した場合でも)は、いずれかのオペランドがTRUEと評価されるかどうかを判断しようとしています。つまり、オペランドはブール値としてキャストできる式でなければなりません。
だから、理由
bar() or throw new Exception();
は違法です、理由は
(boolean)throw new Exception();
も違法です。本質的に、例外をスローするプロセスは、オペレーターがチェックする戻り値を生成しません。
ただし、関数を呼び出すと、する演算子がチェックする戻り値を生成します(明示的な戻り値がないため、関数は NULL
を返し、 FALSEとしてキャストします)
)これは、関数でスローする例外をラップするときに機能する理由です。
役立つこと。
他のヒント
なぜ bar()
と bb()
は例外をスローしないのですか? PHPでは例外が発生するため、 bar()
/ bb()
を呼び出す関数/メソッドで例外をスローする必要はありません。これらの例外は、 bar()
/ bb()
によってスローされる場合があります。別の例外をスローする場合は、次のようにします。
function foo() {
try {
$bar = bar();
} catch (BarException) {
throw new FooException;
}
}
" or die()"を置き換えることができる解決策どこでも、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';
}
コメントごと-1行で(つまり 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;
}
例外が constructed ( new
)スローされない( throw
)場合、ファイル/行/スタック情報がキャプチャされるためtは呼び出しスタックに干渉します。
これを行うことができます。
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()
に変更できます。PHP7以降では使用が許可されているためですメソッド名として予約済みのキーワード。