0

PHP の PDO オブジェクトを使用して、条件のペアに一致するすべての行を mySQL テーブルから削除しようとしています。なぜ機能しないのかわかりません:

//This deletes all comments for a given post;
//Querying database for existent comments on that post;
$this->query = $this->db->query(
"SELECT cid 
FROM comments
WHERE id = '$html_data->id' AND pid = '$html_data->pid'"
);
//Fetching results into an array;
$this->rows = $this->query->fetchAll(PDO::FETCH_ASSOC);
//Deleting each comment on that post;
foreach ($this->rows as $this->row) {
    $this->db->exec(
    "DELETE from comments 
    WHERE cid = '$this->row['cid']'"
    );
};
//Deleting the post itself;
$this->db->exec(
"DELETE from posts 
WHERE id = '$html_data->id' AND pid = '$html_data->pid'"
);

//Deleting the post itself動作しますが、ループ内の部分がforeach何らかの理由で動作しません。デバッグのために、ループ内に次を追加しました。

echo "WHERE cid = '{$this->row['cid']}'";

そして、期待どおりに返されました:

WHERE cid = '1'
WHERE cid = '2'

したがって、フェッチされているデータは問題ではありません。私も試しました

WHERE id = '$html_data->id' AND pid = '$html_data->pid' AND cid = '$this->row['cid']'"

だけを使用する代わりにcid、それも機能しませんでした。予想どおり、それをエコーすると次のように返されます。

WHERE id = '1' AND pid = '1' AND cid = '1'
WHERE id = '1' AND pid = '1' AND cid = '2'

はい、commentsテーブルidを確認しました。削除pidcidたいのは、エコーされているものと一致します。

4

2 に答える 2

2

したがって、この問題を解決するより良い方法は、準備済みステートメントを使用して、変数をクエリから遠ざけることです。そうすれば、この問題を解決するだけでなく、現在抱えているセキュリティの問題 (SQL インジェクション) を修正することもできます...

効率的な準備済みステートメントに変換されたコードは次のとおりです。

$stmt= $this->db->prepare(
    "SELECT cid 
    FROM comments
    WHERE id = ? AND pid = ?"
);
$this->query = $stmt->execute(array($html_data->id, $html_data->pid));

$this->rows = $this->query->fetchAll(PDO::FETCH_ASSOC);

$deleteStmt = $this->db->prepare(
    "DELETE from comments 
    WHERE cid = ?"
);
foreach ($this->rows as $row) {
    $deleteStmt->execute(array($row['cid']));
};

//Deleting the post itself;
$stmt = $this->db->prepare(
    "DELETE FROM posts
    WHERE id = ? AND pid = ?"
);
$stmt->execute(array($html_data->id, $html_data->pid));

ただし、さらにクリーンアップすることはできます。これに対処する最善の方法は、外部キーを使用することです。たとえば、comments テーブルからpidpostsidフィールドへの外部キーを作成してみましょう。

CREATE TABLE posts (
    id   INT,
    name VARCHAR(35),
    PRIMARY KEY (`id`)
) ENGINE = InnoDB;

CREATE TABLE comments (
    id   INT,
    pid  INT,
    name VARCHAR(35),
    PRIMARY KEY (`id`),
    CONSTRAINT `posts_id`
    FOREIGN KEY `posts_id` (`pid`)
    REFERENCES `posts` (`id`)
    ON DELETE CASCADE
    ON UPDATE CASCADE
) ENGINE = InnoDB

ここでの美しさは、そこにあるコードの大きなブロックが次のように削減されることです。

$stmt = $this->db->prepare(
    "DELETE FROM posts
    WHERE id = ? AND pid = ?"
);
$stmt->execute(array($html_data->id, $html_data->pid));

コメントを削除すると、制約 (外部キー) が自動的にその削除をカスケードして、コメントも削除します (そうしないと、無効な制約が存在するため)...

于 2013-03-18T14:14:31.060 に答える
0

そのはず

$this->db->exec(
"DELETE from comments 
WHERE cid = '$this->row[cid]'"
);

または、使用することもできます

$this->db->exec(
"DELETE from comments 
WHERE cid = '{$this->row['cid']}'"
);
于 2013-03-18T10:32:34.070 に答える