仕事で開発やっていて、phpの仕様について誤解していたので反省がてら。
とりあえずコード。
下は、try内容がエラーになった時、3回は再実行し
それ以降は対応できなかったとアラートを出して終了するという処理だ。
//変数宣言と初期化
$i = 0;
repeat:
try {
//try内の内容
echo (12/0);
} catch ( Exception $e ) {
//エラーしたら行われる処理
//4回以下なら上に戻る
if ($i <= 2){
$i++;
print($i.'回目の再実行をします');
goto repeat;
} else {
print('3回再実行をしましたが、対応できませんでした');
exit;
}
} finally {
//エラーしてもしなくても実行される処理のはず
//エラー処理の場合は、exitされるはずなので、ここは正常処理で考えてた
print('正常終了しました');
}
この結果、どうなったか。
1回めの再実行をします
正常終了しました
となった。
さてなぜこうなったのか?
ちなみに私はマクロ屋出身で、VBAが得意。
VBAだと、こういうgotoの使い方は問題ない。(書き方は大いに問題あるが)
しかし、phpは、ダメである。
下記を読んでみると
https://www.php.net/manual/ja/control-structures.goto.php
関数やメソッドの外に飛び出したり 関数やメソッドの中に突入したりすることはできない
とある。
try構文は関数だっただろうか。。。
しかし上のページを読んでも、gotoが飛び先より前にあるものはない。
ということは、おそらく、後ろしか飛べないのだろう、と推測した。
もし、前には飛べない旨の説明が書かれている箇所があったら教えてほしい。
さて、これを直してみた。
再実行処理をfor文で構成したものだ。
機能は先ほどと同じ。
for ($i=1; $i<4; $i++){
try {
//try内の内容
echo (12/0);
} catch ( Exception $e ) {
//エラーしたら行われる処理
//次が3回以下なら再実行
if ($i + 1 <= 3){
$i++;
print($i.'回目の再実行をします');
continue;
} else {
print('3回再実行をしましたが、対応できませんでした');
exit;
}
} finally {
//エラーしてもしなくても実行される処理のはず
//エラー処理の場合は、exitされるはずなので、ここは正常処理で考えてた
print('正常終了しました');
}
}
結果は。
1回めの再実行をします
正常終了しました
ええええええ。
continueがあるのに。。。
continueって普通にループの最後までスキップするんじゃなかったんか?
finallyに飛んでしまってるやん。。。
という。
で、よく考えたら、正常処理は、普通にtry内に書けばfinallyがいらないやん、
と考え直して、
こう書けば、continueもいらない。
for ($i=1; $i<4; $i++){
try {
//try内の内容
print(12/0);
print('正常終了しました');
} catch ( Exception $e ) {
//エラーしたら行われる処理
//次が3回以下なら再実行
if ($i + 1 <= 3){
$i++;
print($i.'回目の再実行をします');
} else {
print('3回再実行をしましたが、対応できませんでした');
exit;
}
}
}
finallyの内容をtry内に書いた。
そしたら、
1回目の再実行をします
2回目の再実行をします
3回目の再実行をします
3回再実行をしましたが、対応できませんでした
とイメージ通りのものが出力された。
ちなみに、print内を正しい割算にすれば、正しく正常終了しました、とだけでる。
gotoはまあわかるとしても、
continueからのこの不思議な処理は一体なんなのだろうか。。。
とりあえず解決できたので、まとめとしてカキコ。