質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

2回答

304閲覧

テキストファイルを配列に変換して出力する際のエラー

takakuni

総合スコア19

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2019/02/20 06:24

前提・実現したいこと

テキストファイルのデータを配列として読み込み、foreachを使い、explode関数も使い、画面に出力したいです。

ここに質問の内容を詳しく書いてください。

PHPで簡易的な掲示板を作っています。

投稿内容を別のテキストファイルに保存して、送信の下に出力する機能を実装中に以下のエラーメッセージが発生しました。

発生している問題・エラーメッセージ

Warning: Invalid argument supplied for foreach() in /home/◯◯◯.com/public_html/keijiban.php on line 36

該当のソースコード

<?php $filename = 'keiziban.txt'; // 変数filenameを宣言 function h($s) { return htmlspecialchars($s, ENT_QUOTES, 'UTF-8'); //phpの文字化け対策 }; if ($_SERVER['REQUEST_METHOD'] == 'POST') { $name = $_POST['name']; $comment = $_POST['comment']; $time = date('Y年m月d日 H時i分s秒'); if (file_exists($filename)) { $number = count(file($filename))+1; } else { $number = 1; } // ファイルがあれば、番号は+1した値を代入、なかったら、番号は1 $datalist = $number."<>". $name."<>".$comment."<>".$time."\n"; $fp = fopen($filename, 'a'); // 変数filenameを追記モードで開き、変数fpに代入 fwrite($fp, $datalist); // 変数fpに変数datalistに書き込まれたデータを代入 fclose($fp); // 変数をfpを閉じた。 } ?> <!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>keiziban</title> </head> <body> <form action="" method="post"> 名前: <input type="text" name="name"> コメント: <input type="text" name="comment"> <input type="submit" value="送信"> </form> <?php $datalists = file($datalist);// 変数datalistsを宣言し、変数datalistを配列に変換して代入している。 foreach ($datalists as $value) { //$datalistsのvalueがある分だけ次の処理を行う list($number, $name, $comment, $time) = explode("<>", $datalists); echo h($number); echo h($name); echo h($comment); echo h($time); } ?> </body> </html>

試したこと

explodeを使わず、implodeも試したのですが、ダメでした。
僕の憶測なのですが、$numberが既に配列化していてそれを配列にもう一度しようとしているのかなと思っています。
大変恐縮ですが$numberを並列化しない方法も踏まえて教えていただけると幸いです。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

$datalistに入っているのは、ファイル名ですか? 書き込んだ掲示板の内容ですか?
$datalists = file($datalist);とするとき必要なのはファイル名ですけど、多分適切にファイル名文字列を詰めている箇所がありません。
var_dump()を駆使してでも変数の中身を確認してください。

$datalists = file($filename); が正しいのではないですか?

if ($_SERVER['REQUEST_METHOD'] == 'POST') {に対する閉じかっこがない?かと思ったけどインデントの都合だったようで問題なし。

投稿2019/02/20 06:29

編集2019/02/20 06:43
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

takakuni

2019/02/20 06:39

var_dump($datalist)を実行したところ ``` string(63) "19<>入力した名前<>入力したコメント<>時間(2019年02月20日 15時33分33秒 " ) ``` と表示されました。 ``` $datalists = file($filename); ``` に書き換えてみるとArrayが20個くらい表示されていました。
退会済みユーザー

退会済みユーザー

2019/02/20 06:40

$datalist と $datalists っていう一文字違うの変数を使うところも、デバッグしづらくなる危険要素なので改めるべき。
退会済みユーザー

退会済みユーザー

2019/02/20 06:44

エラーが解消されたのか、それとも別のエラーを誘発したのかを知りたい。 var_dump()はあくまでデバッグ用なので、中身を確認できたらコメントアウトするといい。
takakuni

2019/02/20 06:49

$datalistsは$arraydatalistに変更しました! $datalists = file($filename);では、エラー表記は消えました!が先ほどのようにArrayがたくさん出ています。
m.ts10806

2019/02/20 06:59

そこまでしなくても正しく動きますよ(私の回答参照)
退会済みユーザー

退会済みユーザー

2019/02/20 09:32

最後まで面倒見なくてすみません
guest

0

ベストアンサー

何も無く実行しただけでNotice: Undefined variableだったりWarning: file(): Filename cannot be emptyだったりが出てます。
エラー表示Onにして確かめていますか?

エラーについてはよくあるエラーなのでエラーメッセージそのままか、Google翻訳で調べましょう。

Invalid argument supplied for foreach()

foreach()に無効な引数が指定されました

そしたら次はマニュアルです。

foreach は、配列を反復処理するための便利な方法です。 foreach が使えるのは配列とオブジェクトだけであり、 別のデータ型や初期化前の変数に対して使うとエラーになります。 この構造には二種類の構文があります。

つまり「配列とかオブジェクトが必要なのにそうではない変数が情報がきたよ」ということですね。

では元となる変数がきているところを見てください。

php

1 $datalists = file($datalist);// 変数datalistsを宣言し、変数datalistを配列に変換して代入している。 2 foreach ($datalists as $value) {

file()が実行されています。
file — ファイル全体を読み込んで配列に格納するが仕様ですが、引数を見てみてください。

file ( string $filename [, int $flags = 0 [, resource $context ]] ) : array

1つ目、「$filename」 つまりファイル名のパスですね。

与えられている引数はどこからきていますか?

$datalists = file($datalist);
$datalistは下記で定義されていますね。

php

1if ($_SERVER['REQUEST_METHOD'] == 'POST') { 2//中略 3 $datalist = $number."<>". $name."<>".$comment."<>".$time."\n";

ファイル名ではなく、ファイルに保管するデータです。
しかもPOSTで送信されたときしか実行されません。

では、本来使うべきファイル名は実際どこでどう定義していますか?

下記ですね。冒頭です。

php

1$filename = 'keiziban.txt'; // 変数filenameを宣言

つまり、下記のようにすれば良い、ということになります。

php

1$datalists = file($filename);

ただ、これだけではいけません。
なぜか?

file()は「指定されたファイルが存在する前提」で動作します。
このままですとまたエラーが出ます。
Warning: file(keiziban.txt): failed to open stream: No such file or directory in XXX.php line NN

「そんなファイル存在しないよ」ですね。

ファイルを作っているのは下記ですね。

php

1if ($_SERVER['REQUEST_METHOD'] == 'POST') { 2//中略 3 4 $fp = fopen($filename, 'a'); // 変数filenameを追記モードで開き、変数fpに代入 5 fwrite($fp, $datalist); // 変数fpに変数datalistに書き込まれたデータを代入 6 fclose($fp); // 変数をfpを閉じた。

ではどうするか?

file_exists()で存在チェックをして、存在すれば読み込むようにすれば良いでしょう。

php

1 if (file_exists($filename)) { 2 $datalists = file($filename); 3 foreach ($datalists as $value) { 4 list($number, $name, $comment, $time) = explode("<>", $value); 5 echo h($number); 6 echo h($name); 7 echo h($comment); 8 echo h($time); 9 } 10 }else{ 11 echo "コメントが1件もありません"; 12 } 13

以下、細かなツッコミ。

explodeを使わず、implodeも試したのですが、ダメでした。

implodeは配列を文字列としてつなげるものですね。
そもそもが配列ではなかったら意味がありません。

僕の憶測なのですが、$numberが既に配列化していてそれを配列にもう一度しようとしているのかなと思っています。

確かに憶測ですね。
元々がfile()の引数が正しく指定されていないことから起きているので、
foreachの中にすら入っていない状態なので$numberは関係ありません。


Eclipseなどの構文チェック機能やフォーマット機能があるIDEの利用を強くすすめます。

エラーの調べ方については下記の記事が非常に参考になります。

投稿2019/02/20 06:45

編集2019/02/20 07:13
m.ts10806

総合スコア80765

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

takakuni

2019/02/20 07:17

出来ました!こちら、何も書かずに送信ボタン押しても表示されているのですがエラー表示は出来ていますか? ファイル上部に ``` <?php // エラーを出力する ini_set('display_errors', "On"); ?> ``` を追加しただけなのですが。。。
m.ts10806

2019/02/20 07:23

そういえば元々エラー出てたから質問したわけでしたね。失礼しました。 ただ、一番最初って、データはなにもないし、ファイルも存在しない状態から始まるので、レイアウト以外ができてきたら、ファイルを削除するか別の場所に控えるとか名前変えるとかでまっさらな状態から確認するようにすると良いです。 「○○がある前提」で作ってると、その前提が崩れて動作させたときに戸惑いが大きくて簡単には対処しきれなくなります。
takakuni

2019/02/20 07:24

解決です! ありがとうございました!
m.ts10806

2019/02/20 07:28

解決されようで何よりです
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問