PHPで作るチャット(5) フォームから送信されたデータをファイルに書き込む

2017年7月19日(更新: 2017年12月9日)

前回は、HTMLのフォームから送信されたデータをページに表示する方法を紹介しました。

今回は、フォームから送信されたデータをそのまま表示するのではなく、ファイルに一旦書き込み、そのファイルからデータを読み取る方法を紹介します。

編集するソースコード

前回作成したソースコードは以下の通りです。

<!-- chat.php -->
  
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>1行メッセージ</title>
</head>
  
<body>
  
  <h1>1行メッセージ</h1>
  
  <form method="post" action="chat.php">
    <div>
      <b>おなまえ</b>
      <input name="name" type="text" size="20" maxlength="10">
    </div>
    <div>
      <b>コメント</b>
      <input name="message" type="text" size="100" maxlength="50" required>
    </div>
    <button name="submit" type="submit">送信</button>
  </form>
  
  <section>
    <?php
        // 送信された名前とメッセージの表示
        if (isset($_POST['name'])) {
          echo '名前: ' . $_POST['name'] . '<br>';
        }
        if (isset($_POST['message'])) {
          echo 'メッセージ: ' . $_POST['message'];
        }
    ?>
  </section>
  
</body>
</html>

このソースコードを編集して、送信されたデータをテキストファイルに書き込むように変更します。

送信されたデータを変数に格納する

まず、データを扱いやすくするために、送信されたデータを変数に格納するようにします。PHPの部分を以下のように書き換えます。

...
    <?php

        // 名前を格納する変数
        $name = "";
        // メッセージを格納する変数
        $message = ""

        // 送信された名前とメッセージを変数に代入
        if (isset($_POST['name'])) {
          $name = $_POST['name'];

          if ($name == "") {
            $name = "noname";
          }
        }

        if (isset($_POST['message'])) {
          $message = $_POST['message'];
        }
    ?>
...

名前の変数 $name には、空のデータが送信された時に使用するデフォルト値(noname)を設定します。

変数のデータをテキストファイルに書き込む

変数に格納されたデータをファイルに書き込むには、以前紹介した fopen 及び fwrite を使ったプログラムを利用します。

プログラムを追加すると、全体のPHPスクリプト部分は以下のようになります。

    <?php

        // データを書き込むファイルの名前
        $LOG_FILE_NAME = "log.txt";

        // 名前を格納する変数
        $name = "";
        // メッセージを格納する変数
        $message = ""

        if (isset($_POST['name'])) {
          $name = $_POST['name'];

          if ($name == "") {
            $name = "noname";
          }
        }

        if (isset($_POST['message'])) {
          $message = $_POST['message'];
          
          // メッセージがある場合のみファイルに書き込む
          $fp = fopen($LOG_FILE_NAME, "a") or exit($LOG_FILE_NAME . "が開けません");

          fwrite($fp, "ここに書き込むデータを入れる");
        }
    ?>

書き込むべきデータは「名前」と「メッセージ」の2つがあります。これらを1行ずつに分けて書き込むこともできますが、データの扱いの都合上、関連するデータを1行にまとめると後ほど楽に扱うことができます。

したがって、以下のように、2つのデータとそれを区切ための文字を決めて、これらを繋げた一行のテキストとして書き込みます。また、一行書き込んだら改行するように、最後に改行コード「\n」を追加します。

以下のように fwrite の引数を変更してください。

        ...

        // | を区切り文字として2つのデータを繋げて書き込む
        fwrite($fp, $name . "|" . $message . "\n");
    ?>

また、これらのPHPの中では、HTMLを出力する処理がないため、記述する位置をファイルの先頭に移動させておきます。すると、全体のコードは以下のようになります。

<!-- chat.php -->

<?php
    // データを書き込むファイルの名前
    $LOG_FILE_NAME = "log.txt";

    // 名前を格納する変数
    $name = "";
    // メッセージを格納する変数
    $message = "";

    // 送信された名前とメッセージを変数に代入
    if (isset($_POST['name'])) {
      $name = $_POST['name'];

      if ($name == "") {
        $name = "noname";
      }
    }

    if (isset($_POST['message'])) {
      $message = $_POST['message'];

      // メッセージがある場合のみファイルに書き込む
      $fp = fopen($LOG_FILE_NAME, "a") or exit($LOG_FILE_NAME . "が開けません");

      // | を区切り文字として2つのデータを繋げて書き込む
      fwrite($fp, $name . "|" . $message . "\n");
    }
?>
  
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>1行メッセージ</title>
</head>
  
<body>
  
  <h1>1行メッセージ</h1>
  
  <form method="post" action="chat.php">
    <div>
      <b>おなまえ</b>
      <input name="name" type="text" size="20" maxlength="10">
    </div>
    <div>
      <b>コメント</b>
      <input name="message" type="text" size="100" maxlength="50" required>
    </div>
    <button name="submit" type="submit">送信</button>
  </form>
  
</body>
</html>

ここで、実際にデータが書き込まれるかどうかテストしてみます。以下のようにテキストを入力し、データを送信します。

HTMLフォームから送信するテキストデータ

プログラムにミスがなければ「log.txt」というファイルが作成され、以下のように送信されたデータが書き込まれます。

フォームから送信されたデータがログファイルに書き込まれる

続けてデータを送信すると、二行目に書き込まれます。

二行目の書き込み

書き込まれた内容を読み込んでページに表示

次に、上記の処理によって「log.txt」に書き込まれたテキストをページに読み込む方法についてです。

テキストファイルの全行を読み込む

PHPの関数 file を利用すると、テキストファイル内の複数行のテキストを一行ずつに分けて配列に格納できます。PHPスクリプトを記載している最後の部分に次の処理を書き加えてください。

<?php
  ...

  // ファイルの全行を読み取る
  $lines = file($LOG_FILE_NAME);
?>

これで、変数 $lines にログファイルのテキストが一行ずつ配列の要素として格納されます。

読み込んだテキストを出力

HTMLでフォームを作成している部分の下に、読み込んだテキストを表示する処理を追加します。

  ...
  <section>
    <?php

      // 読み込んだ行数
      $linesNum = count($lines);

      // 一行ずつ表示する処理
      for ($i = 0; $i < $linesNum; $i++) {

         // 区切り文字でテキストを分けて配列に格納
         $array = explode("|", $lines[$i]);

         // 区切り文字の前の部分は名前
         $name = $array[0];

         // 区切り文字の後の部分はメッセージ
         $message = $array[1];

         // 名前とメッセージを表示
         echo '<p>' . $name . "「" . $message . '」</p>';
      }
    ?>
  </section>
  ...

PHPの関数 count は、配列の要素数を出力します。先ほどファイルを一行ずつ配列に格納したので、変数 $linesNum には、読み込んだテキストの行数が格納されます。

$linesNum に格納された行数の数だけループ処理を行い、読み込んだデータを一行ずつページに表示する処理を実行します。

関数 explode は区切り文字を指定してテキストを分割します。これによって書き込み時に指定した区切り文字でデータ(今回は名前とメッセージ)を別々の配列に読み込むことが可能となります。

読み込んだデータを整形して echo で出力しています。実際の実行結果は以下のようになります。

ログファイルに書き込んだデータを読み込んでページに表示した例

フォームでデータを送信するごとに表示される行が増えます。

この時点での全体のコードは以下のようになっているはずです。

<!-- chat.php -->

<?php
    // データを書き込むファイルの名前
    $LOG_FILE_NAME = "log.txt";

    // 名前を格納する変数
    $name = "";
    // メッセージを格納する変数
    $message = "";

    // 送信された名前とメッセージを変数に代入
    if (isset($_POST['name'])) {
      $name = $_POST['name'];

      if ($name == "") {
        $name = "noname";
      }
    }

    if (isset($_POST['message'])) {
      $message = $_POST['message'];
      //書き込みモードでファイルを開く
      $fp = fopen($LOG_FILE_NAME, "a") or exit($LOG_FILE_NAME . "が開けません");

      // | を区切り文字として2つのデータを繋げて書き込む
      fwrite($fp, $name . "|" . $message . "\n");
    }

    // ファイルの全行を読み取る
    $lines = file($LOG_FILE_NAME);
?>

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>1行メッセージ</title>
</head>

<body>

  <h1>1行メッセージ</h1>

  <form method="post" action="chat.php">
    <div>
      <b>おなまえ</b>
      <input name="name" type="text" size="20" maxlength="10">
    </div>
    <div>
      <b>コメント</b>
      <input name="message" type="text" size="100" maxlength="50" required>
    </div>
    <button name="submit" type="submit">送信</button>
  </form>

  <section>
    <?php

      // 読み込んだ行数
      $linesNum = count($lines);

      // 一行ずつ表示する処理
      for ($i = 0; $i < $linesNum; $i++) {

         // 区切り文字でデータを区切って配列に格納
         $array = explode("|", $lines[$i]);

         // 区切り文字の前の部分は名前
         $name = $array[0];

         // 区切り文字の後の部分はメッセージ
         $message = $array[1];

         // 名前とメッセージを表示
         echo '<p>' . $name . "「" . $message . '」</p>';
      }
    ?>
  </section>

</body>
</html>

以上、フォームで送信したデータをPHPでファイルに書き込み、そのデータをページに表示する方法でした。

一見問題なく動作していますが、このスクリプトには様々な問題があります。次回以降はその問題についてとそれを修正する方法について紹介していきます。

PHPで作るチャット(5) フォームから送信されたデータをファイルに書き込む」への2件のフィードバック

  1. ピンバック: PHPで作るチャット(4) HTMLのフォームから送信されたデータを受け取る | JoyPlotドキュメント

  2. ピンバック: PHPで作るチャット(6) データ送信に関する問題の修正 | JoyPlotドキュメント

コメントを残す

メールアドレスが公開されることはありません。