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

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

ただいまの
回答率

88.93%

PHP 編集後のファイル書き込みについて

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 2,073

terutin

score 11

前提・実現したいこと

PHPで簡易掲示板を作成しているのですが、編集機能において編集し差し替えた後のテキストファイルの中身とブラウザの表示が、差し替えた文が2文表示されてしまいうまくいかない状態です。
例

上記の画像の状態で「a」を「b」と「comment」を「編集したよ」と変更し送信ボタンを押すと

1 a これはテストです
2 b 編集したよ
3 a test
4 b 編集したよ

と表示されてしまいます。
実現したい状態としてはこの4行目を表示させたくないです。
よろしければコードミスなどを教えていただきたいです。

該当のソースコード

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>mission_3-4</title>
    <style>
      form {
        margin-bottom: 20px;
      }
    </style>
  </head>
  <body>

    <?php
      $filename = "mission_3-4.txt";

      //投稿機能

      //フォーム内が空でない場合に以下を実行する
      if (!empty($_POST['name']) && !empty($_POST['comment'])) {

          //入力データの受け取りを変数に代入
          $name = $_POST['name'];
          $comment = $_POST['comment'];

          //日付データを取得して変数に代入
          $postedAt = date("Y年m月d日 H:i:s");

          //ファイルの存在がある場合は投稿番号+1、なかったら1を指定する
          if (file_exists($filename)) {
              $num = count(file($filename))+1;
          } else {
              $num = 1;
          }

          //書き込む文字列を組み合わせた変数
          $newdata = $num . "<>" . $name . "<>" . $comment . "<>" . $postedAt;

          //ファイルを追記保存モードでオープンする
          $fp = fopen($filename,"a");

          //入力データのファイル書き込み
          fwrite($fp,$newdata . "\n");
          fclose($fp);
      }

      //削除機能

      //削除フォームの送信の有無で処理を分岐
      if (!empty($_POST['dnum'])) {

          //入力データの受け取りを変数に代入
          $delete = $_POST['dnum'];

          //読み込んだファイルの中身を配列に格納する
          $delCon = file($filename);

          //ファイルを書き込みモードでオープン+中身を空に
          $fp = fopen($filename,"w");

          //配列の数だけループさせる
          foreach ($delCon as $line) {

                //explode関数でそれぞれの値を取得
                $deldata = explode("<>",$line);

                //削除番号と行番号が一致しなければ書き込み
                if ($delete !== $deldata[0]) {

                    //入力データのファイル書き込み
                    fwrite($fp,$line);
                }
          }
          fclose($fp);
      }

      //編集選択機能

      //編集フォームの送信の有無で処理を分岐
      if (!empty($_POST['edit'])) {

          //入力データの受け取りを変数に代入
          $edit = $_POST['edit'];

          //読み込んだファイルの中身を配列に格納する
          $editCon = file($filename);

          //配列の数だけループさせる
          foreach ($editCon as $line) {

              //explode関数でそれぞれの値を取得
              $editdata = explode("<>",$line);

              //投稿番号と編集対象番号が一致したらその投稿の「名前」と「コメント」を取得
              if ($edit == $editdata[0]) {

                  //投稿のそれぞれの値を取得し変数に代入
                  $editnumber = $editdata[0];
                  $editname = $editdata[1];
                  $editcomment = $editdata[2];

                  //既存の投稿フォームに、上記で取得した「名前」と「コメント」の内容が既に入っている状態で表示させる
                  //formのvalue属性で対応
              }
            }
      }

      //編集実行機能

      //編集か新規投稿か判断
      if ((!empty($_POST['name'])) && (!empty($_POST['comment'])) && (!empty($_POST['editNO']))) {

          //入力データの受け取りを変数に代入
          $editNO = $_POST['editNO'];

          //読み込んだファイルの中身を配列に格納する
          $ret_array = file($filename);

          //ファイルを書き込みモードでオープン+中身を空に
          $fp = fopen($filename,"w");

          //配列の数だけループさせる
          foreach ($ret_array as $line) {

              //explode関数でそれぞれの値を取得
              $data = explode("<>",$line);

              //投稿番号と編集番号が一致したら
              if ($data[0] == $editNO) {

                  //編集のフォームから送信された値と差し替えて上書き
                  fwrite($fp,$editNO . "<>" . $name . "<>" . $comment . "<>" . $postedAt . "\n");
              } else {

                  //一致しなかったところはそのまま書き込む
                  fwrite($fp,$line);
              }
          }
          fclose($fp);
      }
    ?>

    <form action="mission_3-4.php" method="post">
      <input type="text" name="name" placeholder="名前" value="<?php if(isset($editname)) {echo $editname;} ?>"><br>
      <input type="text" name="comment" placeholder="コメント" value="<?php if(isset($editcomment)) {echo $editcomment;} ?>"><br>
      <input type="text" name="editNO" value="<?php if(isset($editnumber)) {echo $editnumber;} ?>">
      <input type="submit" name="submit" value="送信">
    </form>

    <form action="mission_3-4.php" method="post">
      <input type="text" name="dnum" placeholder="削除対象番号">
      <input type="submit" name="delete" value="削除">
    </form>

    <form action="mission_3-4.php" method="post">
      <input type="text" name="edit" placeholder="編集対象番号">
      <input type="submit" value="編集">
    </form>

    <?php
      $filemei = "mission_3-4.txt";
      //表示機能

      //ファイルの存在がある場合だけ行う
      if (file_exists($filemei)) {

          //読み込んだファイルの中身を配列に格納する
          $array = file($filemei);

          //取得したファイルデータを全て表示する(ループ処理)
          foreach ($array as $word) {

                //explode関数でそれぞれの値を取得
                $getdata = explode("<>",$word);

                //取得した値を表示する
                echo $getdata[0] . " " . $getdata[1] . " " . $getdata[2] . " " . $getdata[3] . "<br>";
          }
      }
    ?>
  </body>
</html>
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

まず、端的になぜこのような現象が起こっているかについてですが
17行目からの投稿機能が送信が押された場合に必ず実行されてしまうため、新規投稿が実行された後に108行目の編集機能も実行されてそのような現象が起こっています。

次にこれを直す方法についてですが、色々と書き方はあると思うので今のソースからあまり変えないで
わかりやすく直すとすると、108行目以降の編集実行機能は削除して「//編集か新規投稿か判断」を投稿機能の部分に持ってきます。
フォーム内が空じゃない場合でeditNOが空の場合は新規、editNOが空じゃない場合には編集と判断するようにしてみます。
(ネストを深くしたくないなどもあると思うので書き方等は良い感じで)

  //投稿機能

  //フォーム内が空でない場合に以下を実行する
  if (!empty($_POST['name']) && !empty($_POST['comment'])) {

    //入力データの受け取りを変数に代入
    $name = $_POST['name'];
    $comment = $_POST['comment'];

    //日付データを取得して変数に代入
    $postedAt = date("Y年m月d日 H:i:s");

    // editNoがないときは新規投稿、ある場合は編集 ***ここで判断
    if (empty($_POST['editNO'])) {
      // 以下、新規投稿機能
      //ファイルの存在がある場合は投稿番号+1、なかったら1を指定する
      if (file_exists($filename)) {
        $num = count(file($filename)) + 1;
      } else {
        $num = 1;
      }

      //書き込む文字列を組み合わせた変数
      $newdata = $num . "<>" . $name . "<>" . $comment . "<>" . $postedAt;

      //ファイルを追記保存モードでオープンする
      $fp = fopen($filename, "a");

      //入力データのファイル書き込み
      fwrite($fp, $newdata . "\n");
      fclose($fp);
    } else {
      // 以下編集機能
      //入力データの受け取りを変数に代入
      $editNO = $_POST['editNO'];

      //読み込んだファイルの中身を配列に格納する
      $ret_array = file($filename);

      //ファイルを書き込みモードでオープン+中身を空に
      $fp = fopen($filename, "w");

      //配列の数だけループさせる
      foreach ($ret_array as $line) {

        //explode関数でそれぞれの値を取得
        $data = explode("<>", $line);

        //投稿番号と編集番号が一致したら
        if ($data[0] == $editNO) {

          //編集のフォームから送信された値と差し替えて上書き
          fwrite($fp, $editNO . "<>" . $name . "<>" . $comment . "<>" . $postedAt . "\n");
        } else {
          //一致しなかったところはそのまま書き込む
          fwrite($fp, $line);
        }
      }
      fclose($fp);
    }
  }

以上です。何かわからない部分があればコメントください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/07/03 00:19

    なるほど!見落としていました...。
    rezumaさんの回答を参考にし、投稿機能の途中に新規投稿か編集かを分岐するif文を追加したことで実現したい状態にすることができました。
    夜分遅くに丁寧に回答していただいてありがとうございます!

    キャンセル

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

  • ただいまの回答率 88.93%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る