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

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

ただいまの
回答率

90.51%

  • PHP

    24054questions

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

  • MySQL

    7002questions

    MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

  • データベース

    837questions

    データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

データベースの値が削除できません

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 244

newyee

score 143

PHPの学習としまして簡易な掲示板を作成したのですが、うまくいかない部分がありご助言頂きたいです。
以下は、ユーザのコメント入力画面である、「bbs.php」です。

<?php 
include 'includes/login.php';
  error_reporting(E_ALL);
  ini_set("display_errors",1);
  //1ページに表示されるコメントの数
  $num = 10;
  $user = 'root';
  $password = '';
  $dsn = 'mysql:host=localhost;dbname=online_bbs;charset=utf8';
  //ページ数が指定されている時
  $page = 0;
  if(isset($_GET['page']) && $_GET['page'] > 0){
    $page = intval($_GET['page']) -1;

  }

  try{
    $dbh = new PDO($dsn,$user,$password);
    $dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
    $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);

    $stmt = $dbh->prepare("SELECT * FROM post ORDER BY created_at DESC LIMIT
    :page,:num");
    //パラメーターを割り当て
    $page = $page * $num;

    $stmt->bindValue(':page',$page,PDO::PARAM_INT);
    $stmt->bindValue(':num',$num,PDO::PARAM_INT);
    $stmt->execute();

  }catch(PDOException $e){
    echo "エラー: " . $e->getMessage();
  }



?>

  <html>
    <head>
      <title>交流サイト:掲示板</title>
      <meta charset="utf-8">
    </head>
    <body>
      <h1>掲示板</h1>
      <form action="write.php" method="post">
        <p>名前:<input type="text" name="name" value="<?php echo isset($_COOKIE['name']) ? $_COOKIE['name'] : '' ?>"></p>
        <p>タイトル:<input type="text" name="title" size="60"></p>
        <textarea name="comment"></textarea>
        <p>削除パスワード(数字4桁):<input type="text" name="pass">
        <input type="submit" name="submit" value="書き込む">
        <input type="hidden" name="token" value="<?php echo password_hash(session_id(),PASSWORD_DEFAULT); ?>">
      </form> 
      <hr>
    <?php 
      while($row = $stmt->fetch()):
        $title = $row['title'] ? $row['title'] : '(無題)';
      ?>
      <p>名前:<?php echo $row['name'] ?></p>
      <p>タイトル:<?php echo $title ?></p>
      <p><?php echo nl2br(htmlspecialchars($row['comment'],ENT_QUOTES,'UTF-8'),false) ?></p>
      <p><?php echo $row['created_at'] ?></p>
      <form action="delete.php" method="post">
        <input type="hidden" name="id" value="<?php echo $row['id']; ?>">
        削除パスワード:<input type="password" name="pass">
        <input type="submit" value="削除">
        <input type="hidden" name="token" value="<?php echo password_hash(session_id(),PASSWORD_DEFAULT); ?>">
      </form>
    <?php 
      endwhile;
      //ページ数の表示
      try{
        $stmt = $dbh->prepare("SELECT COUNT(*) FROM post");
        $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);
        $dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);

        //クエリの実行
        $stmt->execute();

      }catch(PDOException $e){
        echo "エラー:" . $e->getMessage();
      }
      /**
       * コメントの件数を取得
       *fetchColumn関数で 最初のレコードを取り出し、最初の列「id」のデータを取り出す
       * idは降順に設定されているため、コメントの件数が分かる
       * */
      $comments = $stmt->fetchColumn();
      $max_page = ceil($comments / $num);
      echo '<p>';
      for($i = 1; $i <= $max_page; $i++){
        echo '<a href="bbs.php?page=' . $i .'">' . $i .
        '</a>&nbsp;'; 
      }
      echo '</p>';
      ?>

    </body>
  </html>


上記を実行した際の画像が以下になります。
イメージ説明
以下の画像は、削除パスワードを入力し、削除ボタンを押したら、データベースよりコメント情報(名前、タイトル、日付)を削除する処理となる、「delete.php」です

<?php 
include 'includes/login.php';
  error_reporting(E_ALL);
  ini_set("display_errors",1);
  $id = intval($_POST['id']);
  $pass = $_POST['pass'];
  $token = $_POST['token'];
  //var_dump($id);
  $err_msg = [];

  if($pass == ''){

    $err_msg[] = 'パスワードが入力されていません'; 

  }

  //CRLF対策
  if(!password_verify(session_id(),$token)){
    header('Location:bbs.php');
    exit();
  };

  if(count($err_msg) === 0){


    $dsn = 'mysql:host=localhost;dbname=online_bbs;charset=utf8';
    $user = 'root';
    $password = '';

      try{
        $dbh = new PDO($dsn,$user,$password);
        $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);
        $dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
        $stmt = $dbh->prepare("
          SELECT password FROM post where id = :id 
        ");
        $stmt->bindValue(':id',$id,PDO::PARAM_INT);

        $stmt->execute();

        $db_pass = $stmt->fetch();

        if(!password_verify($pass,$db_pass['password'])){

          die('パスワードが違います');

        }

      }catch(PDOException $e){

        die('エラー:'. $e->getMessage());
      }

      try{
        $dbh = new PDO($dsn,$user,$password);
        $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);
        $dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
        $stmt = $dbh->prepare(
          "DELETE FROM post WHERE id = :id AND password = :pass"
        );

        $stmt->bindValue(':id',$id,PDO::PARAM_INT);
        $stmt->bindvalue(':pass',$pass,PDO::PARAM_STR);
        $stmt->execute();

      }catch(PDOExeption $e){

        die( "エラー:" . $e->getMessage());
      }

    header('Location: bbs.php');
    exit();

    } 

?>


以下は、コメント情報を格納しているテーブルである、「post」テーブルになります。
イメージ説明

お聞きしたい部分なのですが、削除パスワードを正しく入力しているにも関わらず、「delete.php」にて削除処理がなされず、「bbs.php」に投稿されたコメントが残り続けています。
原因が分からない為、ご助言頂けましたら幸いです。よろしくお願いします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • newyee

    2019/03/04 17:02

    実は、あれから、削除パスワードをデータベースに入力する際、password_hashで暗号化し、delete.phpにて、データベースに入っているパスワードとの照合を行う処理を追記してみたのですが、そしたら、何故か削除できなくなってしまったんですよね...

    キャンセル

  • mts10806

    2019/03/04 17:09

    整合性がきちんと取れているかどうか確認する必要がありますよ。
    暗号化するということは入力文字数よりも増えることになるので。

    キャンセル

  • newyee

    2019/03/04 17:10

    すみません。ご回答頂いた点も踏まえてもう一度確認してみます。

    キャンセル

回答 4

checkベストアンサー

+2

if(!password_verify($pass,$db_pass['password'])){


としてある以上カラムpasswordにはハッシュ値が入っている
$stmt->bindvalue(':pass',$pass,PDO::PARAM_STR);
この時passwordカラムと比較するデータは生のパスワード
例えば$2y$10$b0050/lEAPEv5fzI68bare2unjkoGKFzgQq3.FXZHYyYXZepAEMk
などのデータが入っています。
DELETE FROM post WHERE id= 1 AND password = "password"
となり実際に入っているだろうと思われるハッシュ値とは一致しません。
またこのハッシュ値と完全に一致させることはほぼ無理です。
同じpasswordというハッシュ値を作成しても作成するたびに違う文字列になります。

なのでこの削除処理だとpassword_verifyでpasswordが一致したら次のDELETEでIDだけ指定して削除するのがいいと思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/03/04 17:24

    ご回答ありがとうございます。
    今色々見直していたのですが、何故、削除できないかの理由がご回答いただきましたおかげで分かりました...
    コードの方、修正して削除されるか検証してみたいと思います...

    キャンセル

+1

PDOExeption ではなくPDOException
一箇所スペルミスがあります。
手打ちではなくマニュアルからコピペが原則です。
というか手打ちであってもIDEを利用すれば自動でチェックしてくれますし
イメージ説明

予測で候補も出してくれます
イメージ説明

※いずれもEclipseの例

このあたりでのケアレスミスがなくなればコーディングに集中できるので、
導入しない理由はないです。


おかしいですね。
前の質問に登録処理のコードも貼ってもらいましたが
password_verify()はあくまでトークンのチェックに行われているだけでパスワードに対しては行ってませんよね?
登録処理は修正して、修正後にデータを新しく登録しなおして、
その新しいデータに対して対応を行いましたか?
もし登録処理を修正していないのでしたら修正する必要がありますし、
修正前に登録したデータを削除しようとしているのであれば、
暗号化行われていないpasswordなので合致しないのは当たり前です。

あと、暗号化すると入力した文字数より長くなります。

echo password_hash("test", PASSWORD_DEFAULT);
//$2y$10$/IFPho40PbQ5H84qsSQVzO0fXJL5cNdUf9WvQPiB0r825aBcIMoLe


暗号化方式もあわせて文字数が入るじゅうぶんな桁数がパスワードカラムに設定されている必要があります。
元々暗号化されてなかったのでしたら、それなりの文字数しか設定してなかったのでは?

そのあたり全て整合性を確認してください。


蛇足:
同じコードの中で何度も接続処理を書くのは無駄ですし、
Exceptionを拾ったら処理終了なのであれば全部囲うべきですね。

try{
    $dbh = new PDO($dsn,$user,$password);
    $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);
    $dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
    $stmt = $dbh->prepare("
          SELECT password FROM post where id = :id
        ");
    $stmt->bindValue(':id',$id,PDO::PARAM_INT);

    $stmt->execute();

    $db_pass = $stmt->fetch();

    if(!password_verify($pass,$db_pass['password'])){

        die('パスワードが違います');

    }

    $stmt = $dbh->prepare(
        "DELETE FROM post WHERE id = :id AND password = :pass"
        );

    $stmt->bindValue(':id',$id,PDO::PARAM_INT);
    $stmt->bindvalue(':pass',$pass,PDO::PARAM_STR);
    $stmt->execute();

}catch(PDOException $e){

    die( "エラー:" . $e->getMessage());
}

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/03/04 17:38

    ご丁寧にありがとうございます。
    >Exceptionを拾ったら処理終了なのであれば全部囲うべきですね
    dateさんのご回答を元に、mtsさんにご提示頂きましたようにtry,catch文を一つにまとめましたら、かなりコードもスッキリとなりエラーも解決しました。
    僕のコードはいかに、無駄が多かったのかを実感致しました...

    キャンセル

  • 2019/03/04 17:40

    ご回答に記載いただきましたIDEなのですが、良いですね...今使っています、エディッタが結構気に入っているので、拡張機能でどうにかならないか、一度調べてみてから、検討してみたいと思います。

    キャンセル

  • 2019/03/04 18:06

    Atomでしたっけ?
    使ったことないですが構文チェックくらいならプラグインでなんとかなりそうに思います。

    キャンセル

  • 2019/03/05 05:39

    いえ、vscodeですね。プラグイン調べてみたいと思います。

    キャンセル

  • 2019/03/05 11:13

    ああ、失礼。
    拡張機能ありますね
    https://www.elp.co.jp/staffblog/?p=5620

    キャンセル

  • 2019/03/05 11:53

    ご親切にありがとうございます。
    拡張機能導入できました。

    キャンセル

0

commit していますか?

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/03/04 16:49

    MySQLはオートコミットで、そもそもトランザクション張ってdeleteしてるわけではないのであまり関係なさそうです。

    キャンセル

  • 2019/03/04 16:50

    前の質問とあまり変わらない状態で、一度は削除できたようですし。
    https://teratail.com/questions/177507

    キャンセル

  • 2019/03/04 16:59

    オートコミットでしたか。

    キャンセル

0

パスワードカラムの文字列の長さは十分とっていますか?
自動で切り詰められた場合イコールではヒットしません

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/03/04 17:08

    ご回答ありがとうございます。
    passwordには、当初は4文字のみしか格納できないよう、「char(4)」としていたのですが、それではpassword_verifyで照合できないと知り、「varchar(255)」に変更したんですよね...
    入力された削除パスワードをpassword_hashで暗号化する前は、削除できていたのですが、暗号化し、delete.phpにて、入力されたパスワードと照合を行う処理を追記したら、何故か削除できなくなってしまいました...

    キャンセル

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

  • PHP

    24054questions

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

  • MySQL

    7002questions

    MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

  • データベース

    837questions

    データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます