【PHP】goto構文の使い方と注意点

エディタPHP

こんにちは。いっとくです!

プログラミング界において、可読性を落とす危険性があることから嫌われ者であるgoto構文

あまりの嫌われっぷりに実際の現場で使っているのは見たことがないので、今まで存在自体知らなかったし具体的な使い方もわからなかったのですが、使い道がないわけでもないので紹介したいと思います

スポンサーリンク

goto構文の基本的な使い方

PHPは通常であれば上から下へと順番に処理をしていきますが、goto構文を使うと任意の場所に処理を飛ばすことができるようになります。

まずは実際のコードで見てみましょう。

<?php

$a = 'aaaaa!';

goto output;

echo 'B!'; // 出力されない

output:
    echo $a; // aaaaa!

gotoの後に任意のラベル名を書き、それに対応するラベルに処理を書きます。

上記の例ではgoto outputが読み込まれた後に、変数aの値をechoで出力しています。

関数やメソッドと違って、ジャンプした先から処理が再開されるため、途中にあるB!を出力するためのechoは処理されません。

gotoより上に処理があってもジャンプできてしまうため、gotoより上に処理内容を記述すると無限ループに突入するので気をつけましょう!

またgotoはどこにでも飛べるというわけではなく、範囲に制約があります。

例えば以下のように別の関数やメソッドに飛ぶとUndefinedエラーが発生します。

<?php

run();

goto fullPower; //Fatal error: 'goto' to undefined label 'fullPower'

function run() {
    echo 'run';

    fullPower:
        'うおおおおー!';
}

またループ処理の中に飛ばすこともできません。

<?php

goto jump; //Fatal error: 'goto' into loop or switch statement is disallowed

for ($i = 0; $i < 10; $i++) {
    if ($i === 5) {
        echo 'あと半分!';
    }
    jump:
        echo 'ここには飛べないぞよ';
}

ループ処理の中には飛ばせませんが、ループから脱出することはできます。

またif文の中に飛ばすこともできます(条件分岐の意味がなくなるのでif文の中には絶対に飛ばして欲しくないけど!笑)

goto構文が嫌われる理由

基本的な使い方をみただけでわかると思いますが、goto構文は任意の場所に飛ばすことができるため、書いた本人以外の人にかなりわかりにくい処理の流れになってしまいます。

つまり可読性を著しく損ねる可能性があるわけです。

これでラベルが離れた所に書かれたら読むのも面倒臭くてたまりません!

また、書き方によっては無限ループに陥ることもあったり、goto構文とラベルの間の処理がスキップされたりと、一つの構文でループ処理や条件分岐みたいな性質の動きをすることがあります。

これは確かに現場で発見したらブチ切れる人もいるかもしれん。

じゃあgoto構文はいつ使うん?

そんなgoto構文ですが、使い道が全くないというわけでもありません。

PHPマニュアルによるとネストしているループ処理を抜け出す際に使えるんだとか。

具体例はこんな感じです。

<?php

for ($i = 0; $i < 10; $i++) {
    for ($j = 0; $j < 10; $j++) {
        for ($k = 0; $k < 10; $k++) {
            echo $i . $j . $k . '<br>';
            if ($i . $j . $k === '030') {
                goto end;
            }
        }
    }
}

end:
    echo '30個出したからおしまい';

上記の例では0順番に3つの数字が足し算され、合計が30に到達するとgoto構文が動きループ処理を脱出するようになっています。

ループ処理の直後にラベルの内容を記述しておけばそこまで可読性にも影響はなさそう。

ただ実はこれbreak構文でオプション引数を指定すれば同じことができます。

<?php

for ($i = 0; $i < 10; $i++) {
    for ($j = 0; $j < 10; $j++) {
        for ($k = 0; $k < 10; $k++) {
            echo $i + $j + $k . '<br>';
            if ($i + $j + $k === 15) {
                break 3; //ループが3つあるので引数で3を指定すると一発で抜け出せる
            }
        }
    }
}

echo '合計が15になったのでおしまい';

う〜ん、こっちの方が見慣れているのでわかりやすいですね!笑

上記の使い方ならどっちでも可読性変わらないと思いますが、goto構文は現場によっては禁止されていることもあるため、breakを使った方が「なんだコイツ!?」と思われずに済む確率が上がる気がするので精神衛生的にもいい気がする。

以上、PHPのgoto構文についてまとめてみました!

さようなら!

コメント

タイトルとURLをコピーしました