20

or diePHP では、次のような特定のエラーが発生したときに exit を呼び出すことで、エラーを処理できます。

$handle = fopen($location, "r") or die("Couldn't get handle");

を使用するdie()ことは、エラーを処理する優れた方法ではありません。スクリプトを不当に終了してユーザーにエラーを表示するのではなく、親関数が何をすべきかを決定できるように、エラー コードを返したいと思います。

ただし、次のように に置き換えようとすると、PHP でエラーが表示されますor dieor return

$handle = fopen($location, "r") or return 0;

なぜ機能するのに機能しor die()ないのor return 0ですか?

4

3 に答える 3

27

or returnPHPで実行できないとは知らなかったので、この質問をしてくれてありがとう。私がそれをテストしたとき、私はあなたと同じくらい驚いた. この質問は、私が PHP の内部について調べたり、いじったりするいいきっかけになりました。ただし、私は PHP の内部構造の専門家ではないので、以下は PHP の内部構造に関する素人の見解ですが、かなり正確だと思います。


or returnreturn言語パーサーによって「式」と見なされないため、機能しません-それは簡単です。

キーワードorは PHP 言語で と呼ばれるトークンとして定義されており、T_LOGICAL_ORそれが定義されているように見える唯一の式は次のようになります

 expr T_LOGICAL_OR { zend_do_boolean_or_begin(&$1, &$2 TSRMLS_CC); } expr { zend_do_boolean_or_end(&$$, &$1, &$4, &$2 TSRMLS_CC); }

中括弧内のビットについて心配する必要はありません。これは、実際の「または」ロジックの処理方法を定義するだけです。残っているのは です。これは、式の後にトークンが続き、別の式がexpr T_LOGICAL_OR expr続くことが有効な式であることを示しているだけです。T_LOGICAL_OR

ご想像のとおり、 anexprもパーサーによって定義されます。r_variable読み取りが許可されている変数であることを意味する 、またはexpr_without_variable式が他の式から作成できることを示す派手な方法である のいずれかです。

or die()言語構造(関数ではありませdieん!) とそのエイリアスは両方とも tokenでexit表され、有効と見なされますが、ステートメント - token - はそうではありません。T_EXITT_EXITexpr_without_variablereturnT_RETURN

では、なぜT_EXIT式と見なされるのにそうT_RETURNではないのでしょうか。正直なところ、私には手がかりがありません。or die()おそらく、あなたが求めている構造を許可するためだけに行われた設計上の選択でした. これが非常に広く使用されていたという事実 (少なくともチュートリアルなどでは、大量の製品コードについて話すことができないため) は、これが意図的な選択であった可能性があることを暗示しているようです。確実に知るには、言語開発者に尋ねる必要があります。


とはいえ、これは問題ではありません。このor die()構文は、数年前のチュートリアル (上記参照) ではどこにでもあるように見えましたが、「賢いコード」の例であるため、実際には推奨されていません。or die()は独自の構造ではなく、or演算子の 2 つの副作用 (乱用と言う人もいるかもしれません) を使用するトリックです。

  • 演算子の優先順位リストでは非常に低いため、実際には他のすべての式が評価される前に評価されます。
  • これは短絡演算子です。つまり、最初のオペランドが を返した場合、2 番目のオペランド ( の後のビット)orは実行されませTRUEん。TRUEor

一部の人々は、この種の策略を好ましくないと考えています。なぜなら、プログラマーが読むのは難しくなりますが、ソース コード内の数文字のスペースしか節約できないからです。プログラマーの時間は高く、ディスク容量は安いので、人々がこれを好まない理由がわかります。

代わりに、コードを本格的なifステートメントに展開して、意図を明示する必要があります。

$handle = fopen($location, "r");
if ($handle) {
  // process the file
} else {
  return 0;
}

ifステートメント内で変数の割り当てを行うこともできます。これをまだ読めない人もいますが、ほとんどの人 (私自身を含む) は同意しません。

if ($handle = fopen($location, "r")) {
  // process the file
} else {
  return 0;
}

最後に 1 つ: ステータス コードとして返された場合は成功を示すのが慣習である0ため、ファイルを開くことができなかったことを示すために別の値を返したい場合があります。

于 2013-01-18T07:43:23.673 に答える
1

return はかなり特殊です。関数を終了するためのツールであるため、関数のようなものにすることはできません。これを想像してください:

if(1==1) return();  // say what??

このような場合、returnは「二重終了」を行う関数である必要があり、それ自体のスコープだけでなく、呼び出し元のスコープも残します。したがって、return は式のようなものではなく、そのようには機能しません。

理論的には、return は (たとえば) false に評価されてから関数終了する式になる可能性があります。おそらく、それ以降の php バージョンでこれが実装されるでしょう。

同じことがgotoにも当てはまり、フォールバックとして機能するのは魅力的です。はい、フォールバックが必要であり、多くの場合、コードを読みやすくするため、誰かが「賢いコード」について不満を言う場合 (これは確かに良い点です)、おそらく php はそのようなことを行うための「公式の」方法を持っている必要があります:

connectMyDB() fallback return false;

try...catch のようなものです。そして個人的には、「接続または失敗を報告する」という英語の文法でうまく機能するため、「または」がこの仕事をすることにもっと満足しています。

TLDR:あなたの言う通りです。return、goto、break - どれも機能しません。理由は簡単に理解できますが、それでも面倒です。

于 2016-01-15T15:55:45.710 に答える
0

私も一度それを思いついたことがあります。私が見つけることができたのはこれだけでした:

https://bugs.php.net/bug.php?id=40712

下のコメントを見てください。

これはバグではありません

私はドキュメントを検索しましたが、それはreturn 0ステートメントであるのに対し、die()本質的に式であるという事実によるものだと思います。実行できませんが$handle = return 0;$handle = fun();有効なコードです。

エラー処理に関しては、カスタム コードを使用するか、カスタム ハンドラーとトリガーを使用することをお勧めします。後者は、例としてここで説明されています。

于 2013-01-18T06:11:33.990 に答える