derasado
@derasado (Sado)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

複数分岐の際のエラー

Q&A

Closed

解決したいこと

ここに解決したい内容を記載してください。

例)
メモとTodoがセットになったようなWebアプリをテキストページからつくっています。
条件分岐をしてユーザーに登録してもらう(仮定)の段階でエラーが発生してしまいます。
恐らく、ifの使い方が違うのかもしれません。
ToDoの内容を登録、メモの内容の登録どちらをしようとしてもエラーが出てしまいます。
解決方法を教えて下さい。

発生している問題・エラー

出ているエラーメッセージを入力

[21-Feb-2021 16:38:41 Asia/Tokyo] PHP Notice: Undefined variable: todoListChoice in /var/www/html/memo-todo.php on line 72

Notice: Undefined variable: todoListChoice in /var/www/html/memo-todo.php on line 72
[21-Feb-2021 16:38:41 Asia/Tokyo] PHP Notice: Undefined variable: todoListChoice in /var/www/html/memo-todo.php on line 72

Notice: Undefined variable: todoListChoice in /var/www/html/memo-todo.php on line 72
[21-Feb-2021 16:38:41 Asia/Tokyo] PHP Notice: Undefined variable: todoListChoice in /var/www/html/memo-todo.php on line 80

Notice: Undefined variable: todoListChoice in /var/www/html/memo-todo.php on line 80
[21-Feb-2021 16:38:41 Asia/Tokyo] PHP Notice: Undefined variable: todoListChoice in /var/www/html/memo-todo.php on line 80

Notice: Undefined variable: todoListChoice in /var/www/html/memo-todo.php on line 80
[21-Feb-2021 16:38:41 Asia/Tokyo] PHP Notice: Undefined variable: todoListChoice in /var/www/html/memo-todo.php on line 87

Notice: Undefined variable: todoListChoice in /var/www/html/memo-todo.php on line 87
[21-Feb-2021 16:38:41 Asia/Tokyo] PHP Notice: Undefined variable: todoListChoice in /var/www/html/memo-todo.php on line 87

Notice: Undefined variable: todoListChoice in /var/www/html/memo-todo.php on line 87
[21-Feb-2021 16:38:41 Asia/Tokyo] PHP Notice: Undefined variable: todoListChoice in /var/www/html/memo-todo.php on line 97

Notice: Undefined variable: todoListChoice in /var/www/html/memo-todo.php on line 97
[21-Feb-2021 16:38:41 Asia/Tokyo] PHP Notice: Undefined variable: todoListChoice in /var/www/html/memo-todo.php on line 97

Notice: Undefined variable: todoListChoice in /var/www/html/memo-todo.php on line 97
[21-Feb-2021 16:38:41 Asia/Tokyo] PHP Notice: Undefined variable: todoListChoice in /var/www/html/memo-todo.php on line 105

Notice: Undefined variable: todoListChoice in /var/www/html/memo-todo.php on line 105
[21-Feb-2021 16:38:41 Asia/Tokyo] PHP Notice: Undefined variable: todoListChoice in /var/www/html/memo-todo.php on line 105

Notice: Undefined variable: todoListChoice in /var/www/html/memo-todo.php on line 105

NameError (uninitialized constant World)

または、問題・エラーが起きている画像をここにドラッグアンドドロップ

該当するソースコード

PHP
<?php

echo '-TOP MENU-' . PHP_EOL;
echo '1. メモを使う' . PHP_EOL;
echo '2. Todoを使う' . PHP_EOL;
echo '9. アプリケーションを終了' . PHP_EOL;
echo '番号を選択してください(1,2,9):';
$topMenuChoice = trim(fgets(STDIN));

//TOPMENUの分岐
if ('1' == $topMenuChoice || '1' == $topMenuChoice) {
    echo 'MEMOリスト' . PHP_EOL;
    echo '1. メモを登録' . PHP_EOL;
    echo '2. メモリストを表示' . PHP_EOL;
    echo '3. ToDoリストへ' . PHP_EOL;
    echo '4. TOP-MENUへ' . PHP_EOL;
    echo '9. アプリケーションを終了' . PHP_EOL;
    echo '番号を選択してください(1,2,3,4,9):';
    $memoListChoice = trim(fgets(STDIN));
} elseif ('2' === $topMenuChoice || '2' === $topMenuChoice) {
    echo 'ToDoリスト' . PHP_EOL;
    echo '1. やることを登録' . PHP_EOL;
    echo '2. やることリストを表示' . PHP_EOL;
    echo '3. MEMOリストへ' . PHP_EOL;
    echo '4. TOP-MENUへ' . PHP_EOL;
    echo '9. アプリケーションを終了' . PHP_EOL;
    echo '番号を選択してください(1,2,3,4,9):';
    $todoListChoice = trim(fgets(STDIN));
} elseif ('9' || '9' === $topMenuChoice) {
    //アプリケーションを終了
}

//MEMOリストの分岐
if ('1' == $memoListChoice || '1' == $memoListChoice) {
    //メモの登録
    echo 'MEMOを登録してください。' . PHP_EOL;
    echo '1. メモのタイトル:';
    $memoTitle = trim(fgets(STDIN));
    echo '2. メモの詳細:';
    $memoBody = trim(fgets(STDIN));
    echo 'メモの登録が完了しました。' . PHP_EOL;
} elseif ('2' == $memoListChoice || '2' == $memoListChoice) {
    //メモのリスト表示
    echo '登録済みのMEMOを表示します。' . PHP_EOL;
    //ここの下に配列使って登録したメモ表示。
    echo '1. メモのタイトル:' . PHP_EOL;
    echo '2. メモの詳細:' . PHP_EOL;
    echo '----------' . PHP_EOL;   
} elseif ('3' == $memoListChoice || '3' == $memoListChoice) {
    //TODOリストに移動
    echo 'ToDoリスト' . PHP_EOL;
    echo '1. やることを登録' . PHP_EOL;
    echo '2. やることリストを表示' . PHP_EOL;
    echo '3. MEMOリストへ' . PHP_EOL;
    echo '4. TOP-MENUへ' . PHP_EOL;
    echo '9. アプリケーションを終了' . PHP_EOL;
    echo '番号を選択してください(1,2,3,4,9):';
    $todoListChoice = trim(fgets(STDIN));
} elseif ('4' == $memoListChoice || '4' == $memoListChoice) {
    //TOPMENUへ移動
    echo '-TOP MENU-' . PHP_EOL;
    echo '1. メモを使う' . PHP_EOL;
    echo '2. Todoを使う' . PHP_EOL;
    echo '9. アプリケーションを終了' . PHP_EOL;
    echo '番号を選択してください(1,2,9):';
    $topMenuChoice = trim(fgets(STDIN));
} elseif ('9' == $memoListChoice || '9' == $memoListChoice) {
    //アプリケーションを終了
}

//TODOリストの分岐
if ('1' == $todoListChoice || '1' == $todoListChoice) {
    //TODOの登録
    echo 'やることを登録してください。' . PHP_EOL;
    echo '1. やることのタイトル:';
    $todoTitle = trim(fgets(STDIN));
    echo '2. やることの詳細:';
    $todoBody = trim(fgets(STDIN));
    echo 'メモの登録が完了しました。' . PHP_EOL;
} elseif ('2' == $todoListChoice || '2' == $todoListChoice) {
    //TODOのリスト表示
    echo '登録済みのやることリストを表示します。' . PHP_EOL;
    //ここの下に配列使って登録したTODO表示。
    echo '1. やることのタイトル:' . PHP_EOL;
    echo '2. やることの詳細:' . PHP_EOL;
    echo '----------' . PHP_EOL;
} elseif ('3' == $todoListChoice || '3' == $todoListChoice) {
    //MEMOリストに移動
    echo 'MEMOリスト' . PHP_EOL;
    echo '1. MEMOを登録' . PHP_EOL;
    echo '2. MEMOリストを表示' . PHP_EOL;
    echo '3. ToDoリストへ' . PHP_EOL;
    echo '4. TOP-MENUへ' . PHP_EOL;
    echo '9. アプリケーションを終了' . PHP_EOL;
    echo '番号を選択してください(1,2,3,4,9):';
    $todoListChoice = trim(fgets(STDIN));
} elseif ('4' == $todoListChoice || '4' == $todoListChoice) {
    //TOPMENUへ移動
    echo '-TOP MENU-' . PHP_EOL;
    echo '1. メモを使う' . PHP_EOL;
    echo '2. Todoを使う' . PHP_EOL;
    echo '9. アプリケーションを終了' . PHP_EOL;
    echo '番号を選択してください(1,2,9):';
    $topMenuChoice = trim(fgets(STDIN));
} elseif ('9' == $todoListChoice || '9' == $todoListChoice) {
    //アプリケーションを終了
}

自分で試したこと

ここに問題・エラーに対して試したことを記載してください。
分岐によって使わないまったく使わないif文が出てきてしまうとエラーになるのが問題かもしれません。

0

4Answer

エラーは変数が定義されていないことが原因です。

「1. メモを使う」場合は$todoListChoiceが、「2. Todoを使う」の場合は$memoListChoiceが、
それぞれ初期化されないので、その変数を使用しているところでエラーが発生するのだと思います。

//TOPMENUの分岐
if ('1' == $topMenuChoice || '1' == $topMenuChoice) {
    // $todoListChoiceは初期化されない
    $memoListChoice = trim(fgets(STDIN));
} elseif ('2' === $topMenuChoice || '2' === $topMenuChoice) {
    // $memoListChoiceは初期化されない
    $todoListChoice = trim(fgets(STDIN));
}

//MEMOリストの分岐
if ('1' == $memoListChoice || '1' == $memoListChoice) { // TODOの場合エラー
}

//TODOリストの分岐
if ('1' == $todoListChoice || '1' == $todoListChoice) { // MEMOの場合エラー
}

単純にエラーを回避する方法としては、とりあえずnullなどで初期化しておく方法はあります。

$memoListChoice = null;
$todoListChoice = null;

//TOPMENUの分岐
if ('1' == $topMenuChoice || '1' == $topMenuChoice) {
}

しかしこの場合は、次のようにする方が条件に合っているのだと思います。

//TOPMENUの分岐
if ('1' == $topMenuChoice || '1' == $topMenuChoice) {
    $memoListChoice = trim(fgets(STDIN));

    // MEMOリストの分岐
    if ('1' == $memoListChoice || '1' == $memoListChoice) {
    }
} elseif ('2' === $topMenuChoice || '2' === $topMenuChoice) {
    $todoListChoice = trim(fgets(STDIN));

    //TODOリストの分岐
    if ('1' == $todoListChoice || '1' == $todoListChoice) {
    }
}

ただし、このように条件文などがネストしていくと分かりにくくなってしまうので、
慣れてきたら関数、クラス、ファイルに分離していくことを考えると良いと思います。

1Like

Comments

  1. @derasado

    Questioner

    blueさん
    再度ご回答いただきましてありがとうございます。

    nullとすることができるのですね。
    初めて知りました。ありがとうございます。

    最後に頂いたコードの部分イマイチ理解できないのですが、やはり関数をベースに作り上げていくようにした方がいいですよね?
  2. 関数でもいいですし、ファイルを別にする方法もあると思います。
    何が正解なのかはケース・バイ・ケースなので、自分でいろいろ試したり、人のコードを読んだりして、模索していくしかないですね。

    // TOPMENUの分岐
    if ('1' == $topMenuChoice || '1' == $topMenuChoice) {
    $memoListChoice = trim(fgets(STDIN));

    require_once './memoActions.php'; // MEMOリストの分岐
    }
  3. @derasado

    Questioner

    ファイルを別にすると確かに読まれないif文があってもエラーは出ないですよね。

    ありがとうございます!”

だいぶ回答が出てるので、もう解決してるかなと思いつつ…
Notice: Undefined variableは「変数が定義されてないよ!」というエラーです。
怒られないようにプログラムの頭の方で使う変数を予め定義しておくという方法もあります。

$memoListChoice = 0;
$todoListChoice = 0;

こうしておくと通らないルートの変数でも値を持っているので、
if文で比較することができ、条件に合わないためスルーされて終わります。
致命的なエラーを回避するために設定する感じです。

1Like

Comments

  1. @derasado

    Questioner

    とてもわかりやすいです。
    理解できました。
    再度ありがとうございます!

このようにユーザーの選択によって複数の分岐で進める際、なにかいい方法があれば教えて頂けると幸いです。

0Like

この例ならTODO/MEMOとその内部を関数で分けるのがいいんじゃないかなと思います。

0Like

Comments

  1. @derasado

    Questioner

    ありがとうございます!
    このエラーの原因はif文が使われないことによるでしょうか?
  2. そうですね、ざっくり不要なif文の評価も走っているのが原因になると思います。
    MEMOリストを選択したのであれば後半のtodoListChoiceに関するifは必要なくなるので、関数で分けて後半のifが実行されなくなるようにすれば良いです。
  3. @derasado

    Questioner

    わざわざご丁寧にありがとうございます!
    挑戦してみます!
  4. ちなみに関数に分けず下で書かれているようにifのネストで解決する方法もありますが、一般的に深いネストは読みづらいものとして避けられているので関数化するほうが今回は合っているかと思います(もちろんネストさせるほうが良い場面もあります)。言語にもよりますが、特に3〜4段ほどにもなると強く避けられる傾向にあると思います。
    「全く別の機能を作りたくなったら関数化する」と捉えられるとうまく関数にする/しないを判別できるようになるかなと思います。
  5. @derasado

    Questioner

    関数で一度試してみることにします。
    ご回答いただきましてありがとうございます。

Your answer might help someone💌