質問: explode("<>", $_POST); echo h($num); echo h($userName); echo h($comment); echo h($time)."\n"; } function h($s) { return htmlspecialchars($s, ENT_QUOTES, "UTF-8", true); } ?> ``` ### 試したこと あのエラー文に対する他の方々の回答を基にコードを変えたりしたのですが、できませんでした。
回答: どのような質問や回答を参考にしたのか分かりませんが、 エラー自体はよくあるものとはいえ、コピペで解決するようなことはそうそうありませんので、そこだけ認識してください。 まずはエラーは「現在のコードにおける指摘事項」と思ったら良いです。 つまり、何が問題であるかときちんと教えてくれているわけです。 なので、まずはエラーを読みましょう。 エラーメッセージの読み方と対処, 検索や質問の原則 エラーを読んだら、あとはそのエラーへの理解です。 例えば今回ですと1つ目はこうなっていますね。 > > Notice: Undefined index: editNo > > Notice:未定義のインデックス:editNo > > > 「インデックス」という単語に馴染みがなくて混乱しているかもしれませんが、 再現できるコードは、例えば下記です。 ``` $ar = ]; $ar["a"] = "hoge"; echo $ar["b"]; ``` `$ar`という変数を配列で定義して`a`というキーに`hoge`という文字列を代入しているにも関わらず`b`というキーで出力しようとしている。 つまり、存在していないキーを指定したときに出るNoticeであることが分かります。 これについてはteratail内でも結構投稿されています。 teratail: [Undefined index] の検索結果: 1240件 ということで今回Noticeが出ている箇所を確認してみてください。 で、そのNoticeが出ている配列の変数が特定出来たら、直前で `var_dump(対象の変数);`を入れてみましょう。 そうすることで、「その配列にどのような情報が格納されているか」が確認できます。 そこからは地道に「なぜこのキーが入っていないか」を見ていくしかありません。 他のエラーについても同様です。 このように「変数にどのようなデータが入っているか」「どの処理を通っているか」を確認する作業を「デバッグ」と言います。 場合により、PHPの標準関数にエラーが出ているときがあります(今回の1点出ていますね) その場合は、`PHP 関数名`で検索してPHPマニュアルを確認します。 そこで関数の仕様を確認し、エラーと照らし合わせ、整合性を確認します。 PHPマニュアルを辞書代わりに使うということですね。それができるようになるだけで成長が著しくなると思います。 「読み方が分からないんだよ!」という場合は 関数の定義(プロトタイプ)を読むにはを確認して「どのように読むのか」を確認しておきましょう。 基本は「どういう情報を与えたら」「どういう結果が得られるか」という2点を見ておけば殆ど読めます。 公式のドキュメントであるため、確実な情報が書いてありますし、対応しているPHPのバージョンまで確認することで最新の仕様であることが分かると思います。 つまり、現状出ているような問題に対しては下記の3本柱をきっちり行うことができるようになれば、初心者であっても自己解決が可能となるということです。 * エラー文をきちんと読むこと * デバッグを行うこと * PHPマニュアルを活用すること 特に今回はPHPでよく使われる機能であるforeach()の使い方を大きく間違えています(エラーも出てますね)。 PHPマニュアルを確認し、そこにあるサンプルコードも確認し、理解を深めましょう。 蛇足: 他にも気になった点があるので幾つか。 ・ インデントはしっかり付けましょう。 下記A,Bはどちらが読みやすい? ``` //A if($a){ echo "aaaa";} //B if($a){ echo "aaaa"; } ``` どのような開発環境で行っているか分かりませんが、 もしメモ帳を含めた汎用的なテキストエディタであれば今すぐ変更を検討してください。 プログラミングに特化したエディタ、できればPHPに特化したものが望ましいですし、ある程度のスペックのあるPCをお使いであればIDE(Eclipseなど開発統合環境)を導入しましょう。 ソースコードのフォーマット機能もありますし、実行しなくとも構文エラーは拾ってくれます。 未定義の変数、定義されながら使われていない変数も警告してくれます。 以下はEclipseでフォーマット機能を使った例。 ※個人の開発環境ゆえにエディタ側のみキャプチャし切り取っています。 ![イメージ説明 ・処理の順番を理解しよう コードは確かに上から流れていきますが、ブラウザで表示させる場合、 表示時点ではPHP側の処理は全て終わっています。 PHPはあくまでサーバーサイドで動作する言語であるため、ブラウザが解析しようとするのはあくまで出力されている部分のみとなります。 ですので、「出力がなくて処理だけで終わっている部分」をHTMLの中に含む必要はありませんし、関数の定義は余計に含んではいけません。 非常に読みづらいコードとなります。 関数定義だけでも別ファイルに切り出した方が良いのですが(共通化することで別のプログラムからも使えるから)どうしても1ファイルにまとめたいのでしたら下記のような順番で書くと良いです。 用語的には「ロジックとビュー(テンプレート)の区別」と言ったところでしょうか。 ``` 関数の定義 出力を伴わない処理 出力するデータを取得する処理 html PHPで取得したデータ(場合によりここでループなどPHPの処理を入れる) /html ``` ・htmlspecialchars()は画面出力するときに利用する データ保存時に使ってはいけません。入力チェックなどで弾くことはあっても、そこを通ったユーザーから入力されたデータはそのまま何も加工せずに保存すべきです。 ・何度も使い、変更がない情報なら定数を利用する `mission_3-4.txt`というファイル名。固定ですよね。 これはコピペですら何度も出すのはよろしくありません。 ファイル名が変更になった時に置き換えていくことになりますしね。 もし今後システムとして大きくなってきて1プログラムファイルだけで収まらない内容になってきたら「間違いなく置き換えていく作業」をしなければなりません。結構手間です。 今回変数使われてますが、定義する場所が定義する場所なので後半出てくる場所では使えない可能性もあります。 冒頭で定数として定義して全部に適用すると良いです。 ・できれば$_POST直接参照ではなくfilter_input()を使おう 「フィルター」と名がついている通り、単体の入力チェックにも使えますし、もし参照しようとしているキーが定義されてなければnullが返って来ますので、今回のような`Undefined index`は発生しません。 返却値がnullかどうかを見れば良いのでコードも分かりやすくなります。 ・コメントは最低限つけよう。 こういうのがあるだけでも何日か見なかった自分に向けたメッセージにもなります。 ``` //htmlspecialchars()のラッパー関数。変数を画面出力する際に使う function h($s) { return htmlspecialchars($s, ENT_QUOTES, "UTF-8", true); } //削除処理 if (isset($_POST['delete'])) { //編集処理 if (isset($_POST['edit'])); { ``` 色々書いてはいますが、1つ1つ見ていけばおかしい点って結構出てくると思います。 何のために定義した変数か?何のために入れたifの分岐か? ==と=を間違っていないか? 変数名を大文字小文字間違っていないか?など。 自身で理解しているところをコメントつけていくと、自身の理解度も把握でき、全容も分かってきて問題の切り分けも出来るのではないかと思います。