Php 如何使用mysqli准备的语句?

Php 如何使用mysqli准备的语句?,php,mysql,mysqli,prepared-statement,Php,Mysql,Mysqli,Prepared Statement,我正在尝试准备好的语句,但下面的代码不起作用。我得到一个错误: 致命错误:对中的非对象调用成员函数execute() /var/www/prepared.php,第12行 另外,我是否需要对准备好的语句使用mysqli?有人能给我举一个完整的例子,说明从连接到插入再到选择的语句中的错误处理吗?来自: 在执行语句或获取行之前,必须使用mysqli_stmt_bind_param()和/或mysqli_stmt_bind_result()将参数标记绑定到应用程序变量 i、 e: 我还需要为准备

我正在尝试准备好的语句,但下面的代码不起作用。我得到一个错误:

致命错误:对中的非对象调用成员函数execute() /var/www/prepared.php,第12行


另外,我是否需要对准备好的语句使用mysqli?有人能给我举一个完整的例子,说明从连接到插入再到选择的语句中的错误处理吗?

来自:

在执行语句或获取行之前,必须使用mysqli_stmt_bind_param()和/或mysqli_stmt_bind_result()将参数标记绑定到应用程序变量

i、 e:

我还需要为准备好的语句使用mysqli。有人能给我举一个完整的例子,说明从连接到插入再到选择的预处理语句的错误处理过程吗

你也可以使用我更喜欢的PDO。事实上,在代码示例中,您似乎混淆了PDO和Mysqli

$db = new PDO($dsn, $user, $pass);
$stmt = $db->prepare("INSERT INTO users (name, age) VALUES (?,?)");
$stmt->execute(array($name1, $age1));
$stmt->execute(array($name2, $age2));
与mysqli不同,您不必调用单独的绑定函数,尽管如果您喜欢/想要/需要使用它,该功能是可用的

PDO的另一个有趣之处是命名占位符,在复杂的查询中,它可以大大减少混淆:

$db = new PDO($dsn, $user, $pass);
$stmt = $db->prepare("INSERT INTO users (name, age) VALUES (:name,:age)");
$stmt->execute(array(':name' => $name1, ':age' => $age1));
$stmt->execute(array(':name' => $name2, ':age' => $age2));

试试这个,清理传入的数据。 别忘了php标签

function clean($data)
{ 
  $data = trim(strip_tags(htmlspecialchars($data)));
  return $data;
}

$field1 = isset($_POST['field1']) ? clean($_POST['field1']): NULL;
$field2 = isset($_POST['field2']) ? clean($_POST['field2']): NULL;
$field3 = isset($_POST['field3']) ? clean($_POST['field3']): NULL;
$field4 = isset($_POST['field4']) ? clean($_POST['field4']): NULL;
$field5 = isset($_POST['field5']) ? clean($_POST['field5']): NULL;
$field6 = isset($_POST['field6']) ? clean($_POST['field6']): NULL;
$field7 = isset($_POST['field7']) ? clean($_POST['field7']): NULL;
$database = new mysqli("localhost", "username", "password", "database");
if ($database->errno) die("Error opening database: " . $database->error());
$query = 'INSERT INTO `tablename` (`field1`, `field2`, `field3`, `field4`, `field5`, `field6`, `field7`) VALUES (?, ?, ?, ?, ?, ?, ?)'; 
$result = $database->prepare($query); 
$result->bind_param('sssssss', $field1, $field2, $field3, $field4, $field5, $field6, $field7); 
$result->execute(); 
$database->close();
{
    header("Location: http://www.somewebsite.com");
}
有人能给我举一个完整的例子,说明从连接到插入再到选择的语句中的错误处理过程吗

这个问题由来已久,但直到最近,我才完成了一些研究,结果发表了一系列文章,完全涵盖了该请求,因此,请看:

联系 mysqli连接的重要性经常被忽略,被减少到一行。而正确的连接代码可以解决从安全性到可用性的许多问题

鉴于您的代码是通常的程序化PHP,下面是一个简单的mysqli连接代码,将包含在您的脚本中:

$host = '127.0.0.1';
$db   = 'test';
$user = 'root';
$pass = '';
$charset = 'utf8mb4';

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
try {
    $mysqli = new mysqli($host, $user, $pass, $db);
    $mysqli->set_charset($charset);
} catch (\mysqli_sql_exception $e) {
     throw new \mysqli_sql_exception($e->getMessage(), $e->getCode());
}
unset($host, $db, $user, $pass, $charset); // we don't need them anymore
完整的解释可以在我的文章中找到(以及许多有用的提示),但只是一个小引文来强调最重要的部分:

  • 为连接设置适当的字符集将消除整个类别的错误,例如奇怪的字符/问号而不是数据、空的json_encode()输出、存储表情符号的问题等
  • 设置正确的错误报告模式将消除诸如mysqli_fetch_assoc()预期参数…/调用一个成员函数bind_param()…,而是从MySQL返回实际的错误消息
  • 安全性不是一件可笑的事情,不应该有机会向外界泄露您的数据库详细信息
插入 这个问题相对简单,在另一个答案中已经讨论过了

您只需将查询中的所有变量(以及周围的引号!)替换为问号,然后准备查询,然后将所有变量及其类型推入
bind_param()
,最后执行查询

只有一个提示:MySQL很乐意接受所有变量作为字符串,所以不要疯狂地为某个变量寻找正确的类型,只需对任何变量使用“s”

所以基本上是这样的

$sql = "INSERT INTO users (name, email, password) VALUES (?,?,?)";
$stmt= $conn->prepare($sql);
$stmt->bind_param("sss", $name, $email, $password_hash);
$stmt->execute();
对于所有其他查询类型(如更新或删除),应使用相同的原则

挑选 运行a几乎是一样的,但有一个小技巧。由于某种未知的原因,您不能在准备好的语句中立即使用熟悉的fetch函数。因此,您需要先获取mysqli_结果,然后才能使用
fetch_assoc()
fetch_obj()
等:

$sql = "SELECT * FROM users WHERE id=?"; // SQL with parameters
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $id);
$stmt->execute();
$result = $stmt->get_result(); // get the mysqli result
$user = $result->fetch_assoc(); // fetch data 
提示:完全不需要熟悉的
mysqli\u num\u rows()
函数。如果考虑到这一点,您可以始终使用数据本身来查看查询是否返回了任何行:

$user = $result->fetch_assoc();
if ($user) {
    // found!
}
多亏了

另一个技巧:有一个方便的函数
fetch_all()
,可以一次获得所有选定行的数组。例如,如果查询返回多行,可以通过将最后一行更改为

$users = $result->fetch_all(MYSQLI_ASSOC); // fetch data 
错误处理 错误处理是最重要但也有点令人惊讶的部分。尽管许多文章和示例都说,作为一项规则,您根本不应该编写任何错误处理代码。这听起来绝对疯狂,但事情必须这样做。大多数情况下,您需要做的只是报告错误。mysqli/PHP已经可以为您完成,无需任何帮助。因此,您不应该编写任何验证查询执行结果的代码-如果出现错误,mysqli将自动报告,这要归功于#连接部分中提到的
mysqli_report()
函数调用。同样,关于这一原则的完整解释可以在另一篇专门讨论一般性问题的文章中找到


在一种罕见的情况下,当您确实需要处理错误时,即在发生错误时执行一些操作,而不仅仅是报告错误,然后将查询包装在一个
try..catch

“有人能给我指出一个完整的示例,说明准备好的语句从连接到插入再到选择的错误处理”是。注意行“
mysqli\u prepare()
返回一个语句对象,如果发生错误则返回
FALSE
”。哦,@Tomalak建议首先检查
$stmt
是否为FALSE(即发生错误)。此函数不清除任何内容,与mysqli prepared语句无关。此脚本经过测试,功能正常。请解释您的语句原因。
$user = $result->fetch_assoc();
if ($user) {
    // found!
}
$users = $result->fetch_all(MYSQLI_ASSOC); // fetch data