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

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

ただいまの
回答率

90.49%

  • PHP

    20787questions

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

PHP・簡易掲示板の削除機能について

解決済

回答 3

投稿

  • 評価
  • クリップ 1
  • VIEW 7,781

saki_program

score 13

PHPを使って簡易掲示板を作成しております。    
下記コードにて1行投稿は行えるのですが、
削除番号を指定して、投稿を削除できる機能がうまく書けません。
どのように書き直したらよいか、ご回答をお願いします。

コード
<?php

$dataFile = 'bbs.dat';

function h ($s) {
    return htmlspecialchars($s, ENT_QUOTES, 'UTF-8');
}


if(isset($_POST['toukou'])){

    $lines = file('bbs.dat');
    $cnt = count($lines);
    $cnt += 1;

    $message = $_POST['message'];
    $user = $_POST['user'];
    $time = date("Y/m/d H:i:s");

    
    $newData = "{番号}"."<".$cnt.">"."\t"."{名前}"."<".$user.">"."\t"."{コメント}"."\n";
    
    $fp = fopen($dataFile, 'a');
    fwrite($fp, $newData);
    fclose($fp);

    }

$posts = file($dataFile, FILE_IGNORE_NEW_LINES);
$posts = array_reverse($posts);

if (isset($_POST['delete'])) {
  for ($i = 0; $i < count($lines); $i++) {
    $items = explode("\t", $lines[$i]);
    if ($items[0] == $_POST['delno']) {
      array_splice($lines, $i, 1);
    }
  }
}


?>

<!DOCTYPE html>
    <html lang="ja">
    <head>
        <meta charset="UTF-8">
        <title>簡易掲示板</title>
    </head>
    <body>
        <h1>簡易掲示板</h1>
        <form action="" method="post">
            名前:<input type="text" name="user">
            コメント:<input type="text" name="message">
            <input type="submit" name="toukou" value="投稿">
        </form>
        <form method="post" action="">
            削除指定番号:<input type="text" name="delno"> <input type="submit" name="delete" value="削除">
        </form>
        <h2>投稿一覧 (<?php echo count($posts); ?>件)</h2>
        <ul>
            <?php if (count($posts)): ?>
                <?php foreach ($posts as $post): ?>
                <?php list($cnt, $user, $message, $time) = explode("\t", $post); ?>
                    <li><?php echo h($cnt); ?> <?php echo h($user); ?></li>
                <?php endforeach ?>
            <?php else: ?>
                <li>まだ投稿はありません。</li>
            <?php endif; ?>
        </ul>
    </body>
    </html>    
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

checkベストアンサー

0

あなたのコードをできるだけ尊重して実装してみました。
全投稿件数の取得と、投稿番号の連番を両立するため、
削除があったレコードは空行にしてあります。

<?php
$dataFile = 'bbs.dat';

function h($s)
{
    return htmlspecialchars($s, ENT_QUOTES, 'UTF-8');
}

if (isset($_POST['toukou'])){

    $lines = file('bbs.dat');
    $cnt = count($lines);
    $cnt += 1;

    $message = $_POST['message'];
    $user = $_POST['user'];
    $time = date("Y/m/d H:i:s");


    $newData = "{番号}" . "<" . $cnt . ">" . "\t" . "{名前}" . "<" . $user . ">" . "\t" . "{コメント}" . "<" . $message . ">" . "\t" . $time . "\n";

     write($dataFile, $newData, "a");
}

$posts = file($dataFile, FILE_IGNORE_NEW_LINES);
$posts = array_reverse($posts);

if (isset($_POST['delete']))
{
    for ($i = 0; $i < count($posts); $i++)
    {
        $items = explode("\t", $posts[$i]);
        if($items[0] == "{番号}<{$_POST['delno']}>")
        {
            $posts[$i] = "";
        }
    }
    
    $newData = array_reverse($posts);
    $newData = implode("\n", $newData) . "\n";

    write($dataFile, $newData, "w");
}

$all_posts = count($posts);
foreach($posts as $post)
{
    if(empty($post)){ $all_posts--; }
}

function write($dataFile, $newData, $mode)
{
    $fp = fopen($dataFile, $mode);
    fwrite($fp, $newData);
    fclose($fp);
}

?>

<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
        <title>簡易掲示板</title>
    </head>
    <body>
        <h1>簡易掲示板</h1>
        <form action="" method="post">
            名前:<input type="text" name="user">
            コメント:<input type="text" name="message">
            <input type="submit" name="toukou" value="投稿">
        </form>
        <form method="post" action="">
            削除指定番号:<input type="text" name="delno"> <input type="submit" name="delete" value="削除">
        </form>
        <h2>投稿一覧 (<?php echo $all_posts; ?>件)</h2>
        <ul>
<?php if (count($posts)): ?>
    <?php foreach ($posts as $post): ?>
        <?php if (empty($post)) continue; ?>
        <?php list($cnt, $user, $message, $time) = explode("\t", $post); ?>
                    <li><?php echo h($cnt); ?> <?php echo h($user); ?> <?php echo h($message); ?></li>
                <?php endforeach ?>
            <?php else: ?>
                <li>まだ投稿はありません。</li>
            <?php endif; ?>
        </ul>
    </body>
</html>    

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2015/03/04 19:09

    luckerさん 
    コード有難うございます。すごく助かりました。
    写経だけでは自分の力にならないのですが、それぞれのコードの意味をしっかりと理解するようにします。
    また質問スレ上げると思うので、ぜひ今後とも宜しくお願いします。

    キャンセル

  • 2015/03/04 19:43

    このコードでは削除レコードを空にしていますが、
    せっかくですからit_solution_labさんの言っているフラグを持たせて
    削除レコードを残すように改変してみてはどうでしょう?
    その辺の改変も簡単にできるようなコードにしたつもりです。

    最初はみんなちょっとしたことで迷宮に入ってしまうので、
    めげない、あきらめない、あせらない、で続けていっていただけたら嬉しいですね。

    キャンセル

  • 2015/03/04 20:05

    luckerさん
    課題まで頂けて嬉しいです。また自分で調べながら挑戦してみますね^^

    キャンセル

0

削除番号を指定して、投稿を削除できる機能がうまく書けません。 
ご質問される際には、何がどううまくいかないのかを記述されると良いかと思います。
回答者側が勝手に想像したことが、質問者さんの望む答えとは限りませんので、
本来期待する結果を書いていただけるとスムーズに質疑が行えると思います。

if (isset($_POST['delete'])) {
  for ($i = 0; $i < count($lines); $i++) {
    $items = explode("\t", $lines[$i]);
    if ($items[0] == $_POST['delno']) {
      array_splice($lines, $i, 1);
    }
  }
}
詳しく見ていませんが、まずは上記の箇所にファイルに書き込む処理を追加してみてください。


またここで記事番号を作成しているようですが、削除処理で物理的にデータを削除してしまうと、番号がずれませんか?
    $lines = file('bbs.dat');
    $cnt = count($lines);
    $cnt += 1;
以下のいずれかの方法をとってみてください
・カウンター用のデータファイルを別に用意する、
・ファイル中から記事番号の最大値を取得する、
・物理的に削除するのではなく、論理削除する
  ※データの最後に1, 0をつけて、0なら表示する、1なら表示しない
   削除は0を1にして記録


あと、これから書かれるのだと思いますが、投稿された内容から「改行」「タブ」を削除しておく必要があります。ついでにHTMLのタグを許可されないのであれば、<, >、”あたりを置換などされると良いでしょう。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2015/03/03 20:09

    ご回答ありがとうございます。
    質問があいまいで申し訳ございませんでした。

    >>削除番号を指定して、投稿を削除できる機能がうまく書けません。



    とは、
    削除指定番号:<input type="text" name="delno"> <input type="submit" name="delete" value="削除">

    テキストボックスに投稿番号を入力して(1番なら1と入力)
    削除ボタンを押すと該当番号の投稿が削除される機能がほしいということです。

    >>まずは上記の箇所にファイルに書き込む処理を追加してみてください。

    if (isset($_POST['delete'])) {
    for ($i = 0; $i < count($lines); $i++) {
    $items = explode("\t", $lines[$i]);
    if ($items[0] == $_POST['delno']) {
    array_splice($lines, $i, 1);
    }
    }
    $fp = fopen($dataFile, 'w');
    fwrite($fp, $newData);
    fclose($fp);
    }

    と、書き込んでみましたが、該当番号は削除されず、何も入力せずにもう1回削除ボタンを押したら、全部の投稿が削除されてしまいました。

    おそらく解決方法は
    ・カウンター用のデータファイルを別に用意する、
    ・ファイル中から記事番号の最大値を取得する、
    ・物理的に削除するのではなく、論理削除する

    とmunyaXさんのおっしゃっている方法で解決できるのだろうと思いますが、私の勉強不足および理解不足のため、どのようなコードを書けばよいのやらと、迷走しております。

    折角のご親戚な回答ですのに、本当に申し訳ないです。

    キャンセル

  • 2015/03/04 00:41

    まずは落ち着いて、変数の中に何が入っているかを考えて欲しいのですが、
    > if (isset($_POST['delete'])) {
    > for ($i = 0; $i < count($lines); $i++) {
    この$linesには何が入っているでしょうか?
    forの直前あたりに、var_dump($lines); などとして中身を確認してみてください。
    (ご自身の期待されたものであればそれでOKですし、違っていれば原因を考えてみてください)


    また削除を行う際に、
    > if ($items[0] == $_POST['delno']) {
    > array_splice($lines, $i, 1);
    > }

    削除したデータは $lines に入ってるっぽいじゃないですか。
    ところが今回追加された記録処理では、
    > $fp = fopen($dataFile, 'w');
    > fwrite($fp, $newData);
    > fclose($fp);
    となっています。このとき$newDataの中には何が入っているか考えてみてください。


    また実際に投稿内容を表示する際には、$postsを見ていますよね?
    > <?php foreach ($posts as $post): ?>
    $postsには削除されたデータが入っているでしょうか?


    一箇所ずつ、変数が意図したものかをゆっくりと整理してみてください。
    その後で
    > ・カウンター用のデータファイルを別に用意する、
    > ・ファイル中から記事番号の最大値を取得する、
    > ・物理的に削除するのではなく、論理削除する
    あたりの対策に乗り出されると良いかと思います。

    キャンセル

0

fopen の 'a' は追記ですから、
後ろに追加することはできても、途中は削除できないのでは?

削除時は、別途添付ファイルに元の "bbs.dat" を複写しながら、削除対象の行だけ
複写しないで、書き込んで、終わったら bbs.dat に上書きする。

というのではどうでしょうか?

ちなみに、これらBBSデータをテキストファイルで管理した場合、
ファイルが壊れたりもしますけど・・・

削除処理をやってる間に追加されたり、とかそういったことについての
考慮は、別途工夫されたりしている、ということですよね?

複数が同時に削除にいったり、複数の人が書き込んだり、


投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2015/03/03 19:57

    ご回答ありがとうございます。
    環境はローカルのテスト環境のみで行います。

    fopen の 'a' は,'a' のままにしないと連番で新しく投稿できないので変えることができないと思ってます。

    >>削除時は、別途添付ファイルに元の "bbs.dat" を複写しながら、削除対象の行だけ
    >>複写しないで、書き込んで、終わったら bbs.dat に上書きする。

    if (isset($_POST['delete'])) {
    for ($i = 0; $i < count($lines); $i++) {
    $items = explode("\t", $lines[$i]);
    if ($items[0] == $_POST['delno']) {
    array_splice($lines, $i, 1);
    }
    }
    }

    ここにfopenを追記していくということだと思いますが、おっしゃられている処理はどのようなコードを書けばよいか、まだまだ勉強不足で分かりません。すいません。

    キャンセル

  • 2015/03/04 09:58

    "a"は、追記する、というオプションですから、何もしなくても、fopen したあと
    write すれば、無条件で、後ろに追加されます。
    特定の場所を削除する、ということは、"a"では実現できないので、
    もう一つ、別の作業ファイルに、複写しながら該当行をコピーしない、か
    または、表示するかしないかのフラグ項目'del_flag'のようなものをもう一つ作って、
    簡易掲示板で del_flag が1のときは表示しない、ようにして、
    他の方のおっしゃっているように、行数を変えないなら、削除対象のところだけ、
    del_flag=1 になるようにして書き出せばよいと思います。

    "a"でfopen している時点で、そもそも、所定の位置を消す(編集する)ということが出来ないのではないでしょうか?

    キャンセル

  • 2015/03/04 10:16

    目に入ったもので横からすみません、

    以下の箇所の話しでしたら、
    > $fp = fopen($dataFile, 'a');
    > fwrite($fp, $newData);
    > fclose($fp);
    これは新規投稿を記録する部分だと思うので、ここについては問題無いと思いますよ。

    その後、私が回答したコメント部分で、削除後の記録処理も入れていただいたのですが、そこでは
    > $fp = fopen($dataFile, 'w');
    という記述をされていたので、ファイルオープン時のモードについては理解されているようです。

    プログラム初めたばかりだと、フラグの考え方はコロンブスの卵ですよねw
    自分は10数年前の出来事なのであまり覚えてないですがw

    キャンセル

  • 2015/03/04 10:38

    fopen のモードについてご理解してらっしゃるとのことなので、それでしたら
    フラグ処理が一番 かんたんでは?
    レコードを消してしまうのではなくて、削除というフラグを用意し、
    通常の新規投稿時は、0にしておいて、
    削除したら、1にする

    表示する側で、削除フラグが1なら表示しないようにすれば、表向きは
    削除したようになります。

    どんな投稿が削除されたか?を残しておくってのも一つの考え方です。
    もし、誤って削除してしまった、というとき復活できる、というのも
    データベースの考え方からすると、私は、そういう考えで作ってます。

    本当にデータを削除したいときは、メンテナンスで行います・・・

    キャンセル

  • 2015/03/04 10:56

    > fopen のモードについてご理解してらっしゃるとのことなので、それでしたら
    > フラグ処理が一番 かんたんでは?
    まぁ何が簡単かはご本人に判断していただきましょうw
    練習用とか個人用途であればカウンター用のファイル用意するのも、既存コードのロジックから変更が少ないので楽かもしれません。

    > 本当にデータを削除したいときは、メンテナンスで行います・・・
    ここらへんは組織によって運用変わりますよね。
    自分もメンテナンス時にやることが多いですが、ボリュームが相当数になってからは一定のタイミングで削除処理を平行して走らせたりする案件も過去にありました。まぁケースバイケースですかね。

    キャンセル

  • 2015/03/04 11:39

    一定日付以前の古いものの 削除フラグが立っているものを自動的にクリア、なんてこともしたりしますが、
    本件では、日付も記録していないようなので、練習用なのでしょう
    テキストであれこれやるより、むしろDB使ってしまったほうが、このあたり
    すごく楽なのですがね

    キャンセル

  • 2015/03/04 12:14

    > テキストであれこれやるより、むしろDB使ってしまったほうが、このあたり
    > すごく楽なのですがね
    慣れるとそうですねー。
    この手の議論のポイントは、自転車に乗れるようになると、自転車に乗れない人の気持ちがわからなくなるのと同じで、質問者さんの技術レベルに合わせて、どう説明したら一番わかってもらえるかを考えるのが良いのですよね。そう考えるとはDBの提案はもう少し先でしょうか。

    口出しはここらへんにしておきます。
    お邪魔しました。

    キャンセル

  • 2015/03/04 19:15

    munyaX さん
    DBはまだ手を出していないんです。
    テキストファイルに保存するというやり方で行ってます。

    キャンセル

  • 2015/03/04 19:18

    it_solution_lab さん

    >特定の場所を削除する、ということは、"a"では実現できないので、
    >もう一つ、別の作業ファイルに、複写しながら該当行をコピーしない、か
    >または、表示するかしないかのフラグ項目'del_flag'のようなものをもう一つ作って、
    >簡易掲示板で del_flag が1のときは表示しない、ようにして、
    >他の方のおっしゃっているように、行数を変えないなら、削除対象のところだけ、
    >del_flag=1 になるようにして書き出せばよい

    折角のご提案ですが、どうやってコード書くのと、頭がこんがらがってます。
    まだまだ勉強不足ですね。
    自分が情けないです・・・、

    キャンセル

関連した質問

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

  • PHP

    20787questions

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