84669 人が学習中
152542 人が学習中
20005 人が学習中
5487 人が学習中
7821 人が学習中
359900 人が学習中
3350 人が学習中
180660 人が学習中
48569 人が学習中
18603 人が学習中
40936 人が学習中
1549 人が学習中
1183 人が学習中
32909 人が学習中
いくつかの PHP コードをファイルに保存し、それをロードして再度実行する次のコードがありますが、require メソッドが int を返す場合があります。これはなぜ発生しますか?
再現方法は? 2 つの PHP プロセスを使用して上記のコードを実行します phpdemo.php
2 つの PHP プロセスを使用して上記のコードを実行します
phpdemo.php
これはrequireの標準の動作であり、includeの動作も同じです:
require
include
ご覧のとおり、戻り値が上書きされない場合、ハッピー パスでは整数 (1) が返されます。
これはあなたの例では理にかなっています。これまでのところファイルは存在します(したがって致命的なエラーはありません)が、ファイルは作成されたばかりなので、単に切り捨てられているだけ、つまり空である可能性があります。 p>
したがって、戻り値は上書きされず、int(1) が表示されます。
もう 1 つの説明は、当然、整数で上書きしたということです。複数のプロセスが同じファイルに書き込むことができるため、これも可能ですが、例を書いた方法ではその可能性は低くなります。私がこれに言及したのは、それが別の有効な説明だからです。
ファイルが存在するとき (のみ) ではなく、$resultを検索するときに競合状態を一時停止する方法の例:
$result
その背後にある考え方は、ファイルが存在するかどうかのチェックなどのエラー処理をほとんど行わず、そうでない場合はインクルードできない(include() は警告を発し、それを $result = false で渡すだけ)、そしてその後に行うというものです。 if $result ロードは is_array() テストで機能します。
これはエラーに関するものですが、何を探しているのかはわかっています。つまり、$result は配列です。
これは、トランザクションまたはトランザクション操作と呼ばれることがよくあります。
この新しい例では、$result 配列が空の場合、つまりデータが含まれていない場合には、if-body も入力しません。
プログラム処理レベルでは、これは私たちにとって興味深いかもしれません。ファイルの有無、空であるか空ではない、さらには間違って書き込まれていることさえも、すべて「食べて」$result を無効にする必要があるエラー状態です。
定義エラーは存在しません。
PHP 7.0 以降、include() を使用できるようになりました。残念ながら、返されたインクルード ファイルが半分しか書かれていない場合は、PHP 解析エラーが表示され、これを捕捉できます:リーリー
PHP try-catch-finallyを参照してください。この例では、assert() を使用して入力パラメータ $cachePath の意味を記録しています。
for ループを使用して再試行回数をカウントして保護してみてはいかがでしょうか?
スクリプトに常に 1 つのエグゼキュータしかない場合、この問題は再現できません。
このスクリプトを並行して実行することについて話している場合、問題は、排他モードでファイルを書き込んでも、後の書き込みプロセス中にファイルを読み取ることが保護されないことです。
プロセスはファイルに書き込んでいる (そしてロックを所有している) 可能性がありますが、requireはロックを尊重しません (ファイルシステムのロックは強制ではなく勧告です)。
したがって、正しい解決策は次のとおりです:
別のプロセスがファイルの上書きを待機している可能性があるため、書き込み後にロックは解放されず、再取得されないことに注意してください。
リリースしないのは、書かれた同じコードもrequired になるようにするためです。
しかし、このこと自体は最初から疑問でした。
後で戻せるようにファイルに書き込む必要があるのはなぜですか?require?
これは
require
の標準の動作であり、include
の動作も同じです:ご覧のとおり、戻り値が上書きされない場合、ハッピー パスでは整数 (1) が返されます。
これはあなたの例では理にかなっています。これまでのところファイルは存在します(したがって致命的なエラーはありません)が、ファイルは作成されたばかりなので、単に切り捨てられているだけ、つまり空である可能性があります。 p>
したがって、戻り値は上書きされず、int(1) が表示されます。
もう 1 つの説明は、当然、整数で上書きしたということです。複数のプロセスが同じファイルに書き込むことができるため、これも可能ですが、例を書いた方法ではその可能性は低くなります。私がこれに言及したのは、それが別の有効な説明だからです。
存在する場合は含む
ファイルが存在するとき (のみ) ではなく、
リーリー$result
を検索するときに競合状態を一時停止する方法の例:その背後にある考え方は、ファイルが存在するかどうかのチェックなどのエラー処理をほとんど行わず、そうでない場合はインクルードできない(include() は警告を発し、それを $result = false で渡すだけ)、そしてその後に行うというものです。 if $result ロードは is_array() テストで機能します。
これはエラーに関するものですが、何を探しているのかはわかっています。つまり、$result は配列です。
これは、トランザクションまたはトランザクション操作と呼ばれることがよくあります。
この新しい例では、$result 配列が空の場合、つまりデータが含まれていない場合には、if-body も入力しません。
プログラム処理レベルでは、これは私たちにとって興味深いかもしれません。ファイルの有無、空であるか空ではない、さらには間違って書き込まれていることさえも、すべて「食べて」$result を無効にする必要があるエラー状態です。
定義エラーは存在しません。
解析エラーの処理 (Include-If-Exists の場合)
PHP 7.0 以降、include() を使用できるようになりました。残念ながら、返されたインクルード ファイルが半分しか書かれていない場合は、PHP 解析エラーが表示され、これを捕捉できます:リーリー
例外をスローする方法/例外処理作業の詳細については、PHP try-catch-finallyを参照してください。この例では、assert() を使用して入力パラメータ $cachePath の意味を記録しています。
2 番目の例では、抑制操作「@」を使用していません。その理由は、これが前の例のように使用され、インクルードされるファイルに実際の致命的なエラーが含まれる場合、致命的なエラーが沈黙するためです。現在、最新の PHP では、これは大きな問題ではありませんが、file_exists() include() の使用は、チェック時間と使用時間の関係で競合状態が発生しますが、安全であり (警告のみ)、非プロシージャにとっては致命的です。存在するファイルのエラーは非表示になりません。 ご覧のとおり、詳細を知れば知るほど、可能な限り将来性のあるコードを書くのが難しくなります。エラー処理自体に惑わされず、結果に焦点を当て、これらのエラーが存在しないことを定義する必要があります。 そうは言っても、 include() は依然としてデータをメモリにロードさせます。 file_exists() は警告を「抑制」するためにのみ使用されます。それにもかかわらず、 include() は警告を発行し、整数を返す可能性があることがわかっています。 、一方、配列ではありません。さて、プログラミングは難しいので、たとえば、ループでラップして 3 回再試行するとします。
for ループを使用して再試行回数をカウントして保護してみてはいかがでしょうか?
スクリプトに常に 1 つのエグゼキュータしかない場合、この問題は再現できません。
このスクリプトを並行して実行することについて話している場合、問題は、排他モードでファイルを書き込んでも、後の書き込みプロセス中にファイルを読み取ることが保護されないことです。
プロセスはファイルに書き込んでいる (そしてロックを所有している) 可能性がありますが、
require
はロックを尊重しません (ファイルシステムのロックは強制ではなく勧告です)。したがって、正しい解決策は次のとおりです:
リーリー別のプロセスがファイルの上書きを待機している可能性があるため、書き込み後にロックは解放されず、再取得されないことに注意してください。
リリースしないのは、書かれた同じコードも
require
d になるようにするためです。しかし、このこと自体は最初から疑問でした。
後で戻せるようにファイルに書き込む必要があるのはなぜですか?
require
?