如何使用 PHP & PDO 正确删除一行
How to properly delete a row using PHP & PDO
我查找了多种删除PDO中指定行的方法,我是初学者PHP/PDO。本来我用的是Mysql_query之类的,现在被告知使用是不好的做法。我有一个脚本,可以在按下删除按钮时按 id 删除新闻 post。我将它从原始的 MySQL 代码转换为 PDO,但这样做我担心我误读了一些东西并搞砸了。我只是想知道这是否是一种 "secure" 方法,或者我是否应该使用 MySQLI 等。
下面是我的脚本,如果你能帮助我让它工作那就太好了,但我更感兴趣的是在 PHP/PDO 中删除一行的正确方法。
<?php
$dbh = connectDb();
if( isset($_POST['delete']) )
{
if( isset( $_POST['id'] ) && is_numeric( $_POST['id'] ) && $_POST['id'] > 0 )
{
$id = $_POST['id'];
$stmt = $dbh->prepare( "DELETE FROM stats WHERE id =:id" );
$stmt->bindParam(':id', $id);
$stmt->execute();
}
else
{
echo "Invalid ID";
}
}
$stmt = $dbh->query('SELECT * FROM news ORDER BY id ASC');
while($stmt = $rows->fetch(PDO::FETCH_ASSOC)) {
echo <<<_END
<pre>
Id: {$rows['id']}
Title: {$rows['title']}
Body: {$rows['body']}
Date: {$rows['date']}
</pre>
<form action="rmposts.php" method="post">
<input type="hidden" name="delete" value="yes" />
<input type="hidden" name="id" value="{$rows['id']}" />
<input type="submit" name="delete" value="DELETE NEWS" /></form>
_END;
}
?>
看来您没有正确设置 $id
变量。您必须了解 php 脚本在 $_POST
变量中接收所有表单值(包括要删除的 ID):重新加载脚本时不会保留之前加载的任何其他值。
因此,您必须检查 $_POST['id']
并将其值分配给 $id
变量:
$dbh = connectDb();
if( isset($_POST['delete']) )
{
if( isset( $_POST['id'] ) && is_numeric( $_POST['id'] ) && $_POST['id'] > 0 )
{
$id = $_POST['id'];
$stmt = $dbh->prepare( "DELETE FROM news WHERE id =:id" );
$stmt->bindParam(':id', $id);
$stmt->execute();
if( ! $stmt->rowCount() ) echo "Deletion failed";
}
else
{
echo "ID must be a positive integer";
}
}
首先,我们将 if( isset($_POST['delete']) )
提升为完整删除代码的包装器:如果不执行,则没有理由准备查询。另外,如果没有设置$_POST['delete']
,并不是说删除失败,只是没有要求删除,所以去掉错误提示。
然后,我们检查 $_POST['id']
有效性(存在,是数字,是正数),我们将它分配给 $id
变量,现在我们执行查询:通过 ->rowCount()
我们检查受查询影响的行,如果结果为 0,我们将显示一条错误消息。
编辑:其他错误:
你的查询例程有误:
$rows = dbh->query('SELECT * FROM news ORDER BY id ASC');
# └─┬─┘
# └─────────┐
# ┌─┴─┐
while($rows = $stmt->fetch(PDO::FETCH_ASSOC)) {
在第一行上方更改:
$stmt = dbh->query('SELECT * FROM news ORDER BY id ASC');
您的 Heredoc 语法也是错误的:在 <<<_END ... END
中您必须用方括号括起数组名称:{$rows['id']}
、{$rows['title']}
等...
仔细注意:
调试代码时,您必须检查错误:
而且,以后,不要忘记在我们的 php 代码中激活错误检查:
error_reporting( E_ALL );
ini_set( 'display_errors', 1 );
通过错误检查,我们的原始代码产生了这个错误:
激活错误报告(error_reporting( E_ALL ); ini_set( 'display_errors', 1 );
在你的脚本顶部)并且——如果你有一个 500 服务器错误——查看你的服务器错误日志:在这里你会看到详细的错误、文件和行发生错误。
我查找了多种删除PDO中指定行的方法,我是初学者PHP/PDO。本来我用的是Mysql_query之类的,现在被告知使用是不好的做法。我有一个脚本,可以在按下删除按钮时按 id 删除新闻 post。我将它从原始的 MySQL 代码转换为 PDO,但这样做我担心我误读了一些东西并搞砸了。我只是想知道这是否是一种 "secure" 方法,或者我是否应该使用 MySQLI 等。
下面是我的脚本,如果你能帮助我让它工作那就太好了,但我更感兴趣的是在 PHP/PDO 中删除一行的正确方法。
<?php
$dbh = connectDb();
if( isset($_POST['delete']) )
{
if( isset( $_POST['id'] ) && is_numeric( $_POST['id'] ) && $_POST['id'] > 0 )
{
$id = $_POST['id'];
$stmt = $dbh->prepare( "DELETE FROM stats WHERE id =:id" );
$stmt->bindParam(':id', $id);
$stmt->execute();
}
else
{
echo "Invalid ID";
}
}
$stmt = $dbh->query('SELECT * FROM news ORDER BY id ASC');
while($stmt = $rows->fetch(PDO::FETCH_ASSOC)) {
echo <<<_END
<pre>
Id: {$rows['id']}
Title: {$rows['title']}
Body: {$rows['body']}
Date: {$rows['date']}
</pre>
<form action="rmposts.php" method="post">
<input type="hidden" name="delete" value="yes" />
<input type="hidden" name="id" value="{$rows['id']}" />
<input type="submit" name="delete" value="DELETE NEWS" /></form>
_END;
}
?>
看来您没有正确设置 $id
变量。您必须了解 php 脚本在 $_POST
变量中接收所有表单值(包括要删除的 ID):重新加载脚本时不会保留之前加载的任何其他值。
因此,您必须检查 $_POST['id']
并将其值分配给 $id
变量:
$dbh = connectDb();
if( isset($_POST['delete']) )
{
if( isset( $_POST['id'] ) && is_numeric( $_POST['id'] ) && $_POST['id'] > 0 )
{
$id = $_POST['id'];
$stmt = $dbh->prepare( "DELETE FROM news WHERE id =:id" );
$stmt->bindParam(':id', $id);
$stmt->execute();
if( ! $stmt->rowCount() ) echo "Deletion failed";
}
else
{
echo "ID must be a positive integer";
}
}
首先,我们将 if( isset($_POST['delete']) )
提升为完整删除代码的包装器:如果不执行,则没有理由准备查询。另外,如果没有设置$_POST['delete']
,并不是说删除失败,只是没有要求删除,所以去掉错误提示。
然后,我们检查 $_POST['id']
有效性(存在,是数字,是正数),我们将它分配给 $id
变量,现在我们执行查询:通过 ->rowCount()
我们检查受查询影响的行,如果结果为 0,我们将显示一条错误消息。
编辑:其他错误:
你的查询例程有误:
$rows = dbh->query('SELECT * FROM news ORDER BY id ASC');
# └─┬─┘
# └─────────┐
# ┌─┴─┐
while($rows = $stmt->fetch(PDO::FETCH_ASSOC)) {
在第一行上方更改:
$stmt = dbh->query('SELECT * FROM news ORDER BY id ASC');
您的 Heredoc 语法也是错误的:在 <<<_END ... END
中您必须用方括号括起数组名称:{$rows['id']}
、{$rows['title']}
等...
仔细注意:
调试代码时,您必须检查错误:
而且,以后,不要忘记在我们的 php 代码中激活错误检查:
error_reporting( E_ALL );
ini_set( 'display_errors', 1 );
通过错误检查,我们的原始代码产生了这个错误:
激活错误报告(error_reporting( E_ALL ); ini_set( 'display_errors', 1 );
在你的脚本顶部)并且——如果你有一个 500 服务器错误——查看你的服务器错误日志:在这里你会看到详细的错误、文件和行发生错误。