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

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

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

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

Q&A

解決済

3回答

3667閲覧

php 入力フォーム 表示が一回遅れる

IOError

総合スコア25

PHP

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

0グッド

0クリップ

投稿2017/08/19 03:05

最近phpの学習を始めました。
そこで入力フォームを作成し、送信ボタンを押すと、入力フォームの下に順次送信内容が表示されていくというものを作っています。

詳細:
・入力フォームのphpファイルを開くと、最初にtxtファイル(送信内容[番号、名前、コメント、時間]が一行ずつ履歴として残されている)から履歴を読み込み、入力フォームの下に一行ずつ表示する。
・送信ボタンを押すと、送信した内容がtxtファイルに"//"区切りで追加され、変更後のtxtファイルの内容を入力フォームの下に順次表示していく。

現状の問題点:
・初回phpファイル実行時に、txtファイルの内容が表示されない(リロードすれば表示される)。
・送信ボタンを押した時、txtファイルには今送信した内容が書き込まれているが、そのデータをphpで表示すると、たった今送信した内容が表示されずに前回分が一回遅れで表示されてしまう。

目標:
・初回phpファイル実行時に、txtファイルから読み取った内容を表示したい(リロードしなくても)。
・送信ボタンを押したら、たった今送信された内容が追加でphpで表示されるようにしたい。

色々と調べてはみたのですが、初学者の私には解決することができませんでした。
どなたかわかる方がいらっしゃいましたら、ご教授ください。

参考までに、現状のプログラムを記載します。

php

1<!-- 投稿番号を求める --> 2<?php 3 $filename = "sample.txt"; 4 5 // データ格納ファイルが存在するならば、最終行の数字を読み込み、存在しなければ1から始める 6 if (file_exists("sample.txt")==true){ 7 // $num = $_GET["num"] + 1; 8 $fp = fopen($filename, "r"); 9 $data = file($filename); 10 $data_explode = explode("//", $data[count($data)-1]); 11 // ファイルの中に過去のデータが存在する場合、ファイル内の最新データの番号+1が今回の番号 12 if (intval($data_explode[0])>0) { 13 $num = intval($data_explode[0])+1; 14 } else { // ファイル内に過去のデータが存在しない場合、1から番号を始める 15 $num = 1; 16 } 17 fclose($fp); 18 } else { // ファイルが存在しない場合、1から番号を始める 19 $num = 1; 20 } 21?> 22 23 24<!DOCTYPE html> 25<html> 26 <head> 27 <meta charset="utf-8"> 28 <title>mission_2-3</title> 29 </head> 30 <body> 31 <form action="sample.php", method="get"> 32 <h3 class="input_form_text">入力フォーム</h3> 33 <!-- border : 枠線の太さ --> 34 <table border=0> 35 <tr> 36 <td>番号:</td> 37 <td><?php echo $num; ?></td> 38 <input type="hidden" name="num" value="<?php echo $num; ?>"> 39 </tr> 40 <tr> 41 <td>名前:</td> 42 <td><input class="textbox_name", type="text", name="input_name"></td> 43 </tr> 44 <tr> 45 <td>コメント:</td> 46 <td> 47 <textarea class="textbox_comment", name="input_comment", cols="30", rows="5"></textarea> 48 </td> 49 </tr> 50 </table> 51 <br> 52 <?php 53 if(htmlspecialchars($_GET["input_name"])=="" || htmlspecialchars($_GET["input_comment"])){ 54 echo "Error!"; 55 } 56 ?> 57 <input type="submit"> 58 </form> 59 <br> 60 </body> 61</html> 62 63<!-- 投稿履歴の表示 / txtファイルに入力情報登録 --> 64<?php 65 66 // 改行コード挿入関数 67 function br(){ 68 echo nl2br("\n"); 69 } 70 71 $filename = 'sample.txt'; 72 73 74 $fp = fopen($filename, 'a+'); 75 $data = file($filename); // ファイル内容 76 77 // 入力データ取得 78 $textbox_name = htmlspecialchars($_GET["input_name"]); 79 $textbox_comment = htmlspecialchars($_GET["input_comment"]); 80 81 // データの書き込み 82 $fp = fopen($filename, "a"); 83 $slice = '//'; 84 fwrite($fp, $num.$slice.$textbox_name.$slice.$textbox_comment.$slice.date("Y年m月d日 H時i分s秒", time())."\n"); 85 86 fclose($fp); 87 // // テキストデータを2次元配列に格納 88 for($i=0; $i<count($data); $i++){ 89 $data_explode[$i] = explode('//', $data[$i]); 90 } 91 92 93 94 // 2次元配列に格納されているファイルデータを表示 95 for($i=0; $i<count($data_explode); $i++) { 96 for($j=0; $j<count($data_explode[$i]); $j++){ 97 echo $data_explode[$i][$j]; 98 } 99 br(); 100 } 101?> 102

下が、sample.txtです。

txt

11//test1//test1//2016年08月13日 15時18分41秒 22//test2//test2//2016年08月13日 15時18分42秒 33//test3//test3//2016年08月13日 15時18分43秒

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

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

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

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

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

guest

回答3

0

ベストアンサー

まず明らかにバグってる部分から直していきましょう。

一番気になるのは、リロードするたびに空の投稿や以前の投稿がどんどん記録されてしまう不具合です。これは次の2点を修正すれば改善します。

  1. メッセージの投稿は一般的に GET ではなく POST メソッドを使う
  2. メッセージが送信されてきた時だけ投稿処理を行う

1つは単純にフォームの method="get"method="post" にし、PHP側の変数を $_GET[...]$_POST[...] にするだけです。2つめは if 文を使ってメッセージ(名前+コメント)が送られてきたかをチェックすればよいと思います。

php

1// 名前とコメントが入力されていたらファイルに書き込む 2if (!empty($_POST["input_name"]) && !empty($_POST["input_comment"])) { 3 // ここに投稿処理を書く 4}

次に表示されるデータにゴミが混じる不具合です。これは $data_explode を使い回しているために起きます。データを読み込む処理のところで初期化してあげましょう。

php

1 // テキストデータを2次元配列に格納 2 $data_explode = []; // 配列を初期化 3 for($i=0; $i<count($data); $i++){ 4 $data_explode[$i] = explode('//', $data[$i]); 5 }

バグが直ったところで本題に移りましょう。

初回phpファイル実行時に、txtファイルから読み取った内容を表示したい

事象がそもそも理解できませんでした (こちらで実行したところ常に最新の内容が表示されています)

たった今送信された内容が追加でphpで表示されるようにしたい

単純にデータを書き込むまえに、データを読んでしまっているのが原因です。データの書き込み(投稿内容があれば)→ データの読み込み の順番にしましょう。

php

1 // テキストデータを2次元配列に格納 2 $data = file($filename); // データの読み込み処理をここに持ってくる 3 $data_explode = [] 4 for($i=0; $i<count($data); $i++){ 5 $data_explode[$i] = explode('//', $data[$i]); 6 }

最後にいくつか気になった点を。

1つめ。このプログラムは改行を含んだコメントを投稿すると破綻します。また コメントに // を含めた場合も不具合が起きる可能性があります。対処が必要です。

2つめ。このプログラムはほぼ同時に書き込みが合った場合、一方の書き込みが反映されなかったり、ファイルが破損する可能性があります。もし実用的なWebアプリケーションを作っていきたいなら、ファイルのロック処理や、データベース(SQLiteなど)の導入を検討してみてください

3つめ。このプログラムは何度もファイルにアクセスした読んだり書いたりしていますね。できれば一度にまとめられると処理速度が上がりますし、コードもすっきりして読みやすくなると思います。

がんばってください。

投稿2017/08/19 07:21

編集2017/08/19 07:24
miyahan

総合スコア3095

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

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

IOError

2017/08/20 04:13

ご回答いただきありがとうございました。 データの書き込みと読み込みのタイミングが間違っていたのですね。 また、リロードによる二重送信やデータにゴミが入る問題について、今後プログラムを書いていく上で対策しなければならない課題についてもご指摘いただけたので、非常に勉強になりました。 今後は、データベースとの連携も勉強していこうと思います。 ありがとうございました。
guest

0

###送信ボタンを押したら、たった今送信された内容が追加でphpで表示されるようにしたい。

GETのデータがあれば$data_explodeにfwriteで入れているデータをpushすればいいのではと思いました。

あと、今は勉強中のとりあえずのコードですよね?
値の空判定や型チェックをしていなかったり、GETで簡単にファイルに書き込ませてしまうのは不安に思いました。今のコードだと外部から好きに書き込めてしまいますし、sample.txtの中身を簡単に参照されてしまいます。自分の(プログラマー)の意思がなければ書き込ませないし、参照もさせないように設計し外部からはURLを開くことでしか見れない。テキストボックスの入力もプログラマーが認めた範囲のデータのみ送信ボタンを押すことで書き込みができる設計にするのが後々のためにも良いかと思いました。。参考になりますと幸いです。

投稿2017/08/19 07:33

IShix

総合スコア1724

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

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

0

現在の処理の流れを見ると、
0. ファイルを読み込んで行数を取得
0. html出力開始
0. ファイル読み込み
0. ファイルにデータを書き込み
0. 読み込んだファイルの内容を出力

となっています。
ファイルの内容を読み込んだ後にデータを書き込んでいるため、読み込んだ内容は古いままとなっています。
正しい流れとしては
0. ファイルを読み込んで行数を取得
0. ファイルにデータを書き込み
0. 再度ファイルを読み込む
0. html出力開始
0. 読み込んだファイルの内容を出力

とするのが良いと思います。
(本当ならファイルの読込は1度の方が良いですが、質問からは逸れてしまうので)

参考までに修正したソースを記述します。

php

1<!-- 投稿番号を求める --> 2<?php 3 // 値が変わらないのであれば、変数ではなく定数を使用した方が良いです。 4 define( '_SAMPLE_FILENAME', "sample.txt" ); 5 define( '_SAMPLE_SLICE', '//' ); 6 7 // デフォルトの行数 8 $num = 1; 9 10 if ( file_exists( _SAMPLE_FILENAME ) === true ){ 11 // ファイルの行数を取得 12 $num = count( file( _SAMPLE_FILENAME ) ) + 1; 13 14 // 入力値があれがファイル更新 15 if( isset( $_GET[ 'input_name' ] ) && isset( $_GET[ 'input_comment' ] ) ){ 16 $textbox_name = htmlspecialchars( $_GET[ "input_name" ] ); 17 $textbox_comment = htmlspecialchars( $_GET[ "input_comment" ] ); 18 $fp = fopen( _SAMPLE_FILENAME, 'a+'); 19 fwrite( $fp, $num. _SAMPLE_SLICE. $textbox_name. _SAMPLE_SLICE. $textbox_comment. _SAMPLE_SLICE. date( "Y年m月d日 H時i分s秒", time() ). "\n" ); 20 fclose( $fp ); 21 } 22 23 // 表示用データ取得 24 $data = file( _SAMPLE_FILENAME ); 25 } 26?> 27 28<!DOCTYPE html> 29<html> 30 <head> 31 <meta charset="utf-8"> 32 <title>mission_2-3</title> 33 </head> 34 <body> 35 <form action="test.php", method="get"> 36 <!-- 省略 --> 37 </form> 38 <br> 39<?php 40 // 取得したデータを表示 41 foreach( $data as $line ){ 42 $data_explode = explode( '//', $line ); 43 foreach( $data_explode as $chunk ){ 44 echo $chunk; 45 } 46 echo '<br>'; 47 } 48?> 49 </body> 50</html>

これで問題となっている部分は解決するはずですが、まだ修正が必要な部分も残っているので(「送信」のあとリロードするとデータが追記されてしまったり、ファイルの読込が1回で済むように工夫したり)
ここからも頑張ってください。

投稿2017/08/19 07:11

編集2017/08/19 07:14
OsCh

総合スコア111

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問