yudai39
@yudai39 (Yudai Otahara)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

削除機能と編集機能がうまく作動しません

解決したいこと

phpとSQLを使って、新規投稿、編集機能、削除機能、パスワードの簡単な掲示板を作成しています。
するとエラーは起きていないのですが以下の動作が作動しません。
・ 例えば、投稿番号「1」で投稿をした後、それを削除します。その後また投稿したら、また投稿番号「1」で投稿したいのですが、投稿番号「2」を表示してしまいます。
・ 編集ボタンを押すと、投稿フォーム欄に投稿番号と同じフォームが表示されて、編集に移れるようにしたいのですが、編集ボタンを押しても何も表示されません。

自分で考えたこととしては。。
・ 削除機能を出力するたびに、DROP文を使って一度ファイルを消すようにする?
・ 編集番号と一致する行を、投稿フォームにecho?

です。
アドバイス、どのような処理をしたらいいか教えていただけたら嬉しいです

発生している問題・エラー

スクリーンショット 2023-06-05 18.58.03.png
↓編集ボタンを押しても
スクリーンショット 2023-06-05 18.58.13.png

該当するソースコード

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>掲示板</title>
</head>
<body>
    
<?php

//フィールド変数
$time = date("Y-m-d H:i:s");
$reName="";
$reTxt="";
$selectEdit="";
?>


<?php
//データベースに接続
$dsn='';
$user = '';
$password = '';
$pdo = new PDO($dsn, $user, $password, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING));

//テーブル作成
    $sql = "CREATE TABLE IF NOT EXISTS tb"
    ." ("
    . "id INT AUTO_INCREMENT PRIMARY KEY,"
    . "name char(32),"
    . "comment TEXT,"
    . "time DATETIME,"
    . "pass TEXT"
    .");";
    $stmt = $pdo->query($sql);
?>

<?php
//新規or編集
if (!empty($_POST["name"]) &&!empty($_POST["txt"]) && !empty($_POST["pass"]) && !empty($_POST["submit"])){

    $name=$_POST["name"];
    $comment=$_POST["txt"];
    $pass=$_POST["pass"];

   //編集投稿
   $updateNum=$_POST["updateNum"];
    if($updateNum>0){
        $sql= "UPDATE tb SET name=:name, comment=:comment, time=:time, pass=:pass WHERE id=:id";
        $update= $pdo->prepare($sql);
        $update->bindParam(":name", $name, PDO::PARAM_STR);
        $update->bindParam(":comment", $comment, PDO::PARAM_STR);
        $update->bindParam(":time", $time, PDO::PARAM_STR);
        $update->bindParam(":pass", $pass, PDO::PARAM_STR);
        $update->bindParam(":id", $updateNum, PDO::PARAM_INT);
        $update->execute();
    }else{ //新規投稿
    
        $post=$pdo->prepare("INSERT INTO tb(name, comment, time, pass) VALUES(:name, :comment, :time, :pass)");
        $post->bindParam(":name", $name, PDO::PARAM_STR);
        $post->bindParam(":comment", $comment, PDO::PARAM_STR);
        $post->bindParam(":time", $time, PDO::PARAM_STR);
        $post->bindParam(":pass", $pass, PDO::PARAM_STR);
        $post->execute();
    }


}


// 削除処理
if (!empty($_POST["delnum"]) && !empty($_POST["delpass"]) && !empty($_POST["delete"])) {

    $delpass=$_POST["delpass"];
    $delnum = $_POST["delnum"];
    $sql="SELECT * FROM tb WHERE id=:id";
    $delete=$pdo->prepare($sql);         //削除するとこゲットしてSQL実行の準備
    $delete->bindParam(":id", $delnum, PDO::PARAM_INT);
    $delete->execute();
    //結果セットの全てをゲットして
    $lines=$delete->fetchALL();
    foreach($lines as $line){
        if($delpass==$line["pass"]){ //パスワード同じか
                $sql = 'delete from tb where id=:id';
                $stmt = $pdo->prepare($sql);
                $stmt->bindParam(':id', $delnum, PDO::PARAM_INT); //削除番号削除
                $stmt->execute();
      }
    }}


//編集投稿
if (!empty($_POST["editnum"]) && !empty($_POST["editpass"]) && !empty($_POST["edit"])) {
    $editpass=$_POST["editpass"];
    $editnum=$_POST["editnum"];
    
    $sql="SELECT * FROM tb WHERE id=:id";
    $edit=$pdo->prepare($sql);
    $edit->bindParam(":id", $editnum, PDO::PARAM_INT);
    $edit->execute();
    
    $lines=$edit->fetchAll();
    foreach($lines as $line){
        if($line["pass"]==$_POST["editpass"]){//パスワード一致なら表示
            $newname=$line["name"];
            $newcomment=$line["comment"];
            $newnum=$line["id"];
        }
    }

}

?>



<form action="" method="post">
    <!-- 投稿用 -->
    <h3>【投稿フォーム】</h3>
    <br>
    <label>名前:</label>
    <input type="text" name="name" value="<?php echo $reName; ?>" placeholder="名前">
    <br>
    <label>コメント:</label>
    <input type="text" name="txt" value="<?php echo $reTxt ; ?>" placeholder="コメント">
    <input type="hidden" name="updateNum" value="<?php echo $selectEdit; ?>">
    <br>
    <label>パスワード:</label>
    <input type="password" name="pass" placeholder="パスワードを入力してください">
    <br>
    <input type="submit" name="submit" value="送信">
    <br>

    <!-- 削除用 -->
    <h3>【削除フォーム】</h3>
    <br>
    <label>投稿番号:</label>
    <input type="number" name="delnum" value="">
    <br>
    <label>パスワード:</label>
    <input type="password" name="delpass" placeholder="パスワードを入力してください">
    <br>
    <input type="submit" name="delete" value="削除">
    
    <!-- 編集用 -->
    <h3>【編集フォーム】</h3>
    <br>
    <label>投稿番号:</label>
    <input type="number" name="editnum" value="" placeholder="編集したい投稿番号">
    <br>
    <label>パスワード:</label>
    <input type="password" name="editpass" placeholder="パスワードを入力してください">
    <br>
    <input type="submit" name="edit" value="編集">
    <br>
    <input type="hidden" name="hiddenNum" value="<?php echo $selectEdit; ?>" >
</form>
<?php
//ブラウザに表示
$sql="SELECT * FROM tb";
$statement=$pdo->query($sql);
$lines=$statement->fetchAll();
foreach($lines as $line){
        echo $line["id"]. "<br>";
        echo "名前: " . $line["name"] . "<br>";
        echo "コメント: " . $line["comment"] . "<br>";
        echo $line["time"] . "<br><br>";
    }

?>


0

2Answer

ちょっと気になった点を伝えます。
編集機能におけるパスワードの検証部分に問題がありそう。コード内で$newname$newcomment$newnum変数を設定していますが、それらの変数はその後のコードで使用されていません。おそらくこれらは編集する投稿のデータをフォームにプリセットするためのものだと思いますが。

この編集部分を修正するには、以下のように編集用フォームのvalue属性を設定することで、選択された投稿のデータをプリセットできます。

<!-- 投稿用 -->
<label>名前:</label>
<input type="text" name="name" value="<?php echo isset($newname) ? $newname : ''; ?>" placeholder="名前">
<br>
<label>コメント:</label>
<input type="text" name="txt" value="<?php echo isset($newcomment) ? $newcomment : ''; ?>" placeholder="コメント">
<input type="hidden" name="updateNum" value="<?php echo isset($newnum) ? $newnum : ''; ?>">

この修正で、パスワードが一致する場合には編集したい投稿の名前とコメントがフォームに自動的に入力され、投稿を編集する際にはその投稿のidupdateNumにセットされるようになります。

また、上記の修正ではisset()関数を使用して変数が設定されているかどうかを確認しています。これは$newname$newcomment$newnumが常に設定されているわけではないため、エラーを避けるためのものです。

また、セキュリティ面を考慮すると、パスワードが平文でデータベースに保存されている点や、SQLインジェクション攻撃に対する防御など、改善の余地があります。

3Like

Comments

  1. @yudai39

    Questioner

    とってもわかりやすい解説ありがとうございます!! アドバイス通りコードを直したら、編集機能が動きました!パワスワードのセキュリティ面も考えたことなかったので色々調べてやってみたいと思います。
    ちなみになんですけど、isset()と!emptyの違いってありますか?

  2. isset()!empty()はPHPで使われる2つの異なる関数で、それぞれ異なる目的と機能があります。

    isset(): この関数は、変数がセットされている(つまり、値が割り当てられている)かどうかを確認します。変数がnullである場合、isset()falseを返します。つまり、変数が存在し、その値がnullでない場合にのみtrueを返します。

    !empty(): この関数は、変数が"空"(0、0.0、"0"、null、false、空の配列、空の文字列など)でないかどうかを確認します。つまり、empty()は変数が"空"の場合にtrueを返し、それ以外の場合にfalseを返します。そのため、!empty()は変数が"空"でない場合にtrueを返します。

    これらの違いを理解するための一例を示します。以下のコードを考えてみてください:

    $var = 0;
    
    if (isset($var)) {
        echo "var is set";
    }
    
    if (!empty($var)) {
        echo "var is not empty";
    }
    

    この場合、isset($var)trueを返し、"var is set"を出力します。一方で、!empty($var)falseを返し、"var is not empty"は出力されません。なぜなら、変数$varはセットされていますが(そのためisset()true)、その値は0であり、これは"空"とみなされるためです(そのため!empty()false)。

    このように、isset()!empty()は微妙に異なる動作をしますので、使用する際にはその違いを理解しておくことが重要です!

isset()と!emptyの違い

この記事が参考になると思います。
!emptyはtrue/falseが逆転するので適宜読み替えてください)

issetはnullや未定義をチェックするのに対し、emptyはfalseに等しいものを判定します。
例えばゼロ(数値/文字列)、ブランク文字列、空の配列の判定に違いがあります。

$nZero = 0;
var_dump(isset($nZero)); // true
var_dump(!empty($nZero)); // false

$sZero = '0';
var_dump(isset($sZero)); // true
var_dump(!empty($sZero)); // false

$blank = '';
var_dump(isset($blank)); // true
var_dump(!empty($blank)); // false

$emptyArr = [];
var_dump(isset($emptyArr)); // true
var_dump(!empty($emptyArr)); // false

0Like

Your answer might help someone💌