PHP MYSQLi OOP式准备好语句

在本教程中,我们将学习如何使用 PHP 中的 MYSQLI 准备语句执行不同条件的查询,如 SELECT、UPDATE、DELETE 等。在我们开始之前,我将简要介绍您准备好的陈述。

什么是 MYSQLI 准备好的语句?

MYSQL是一种流行的关系数据库系统。MYSQLI是一个强大的 PHP 扩展,用于连接 MYSQL。准备好的语句作为先前准备并稍后使用数据执行的查询。

为什么准备好的陈述很重要?

简单地说,准备好的语句保护网站免受可用于攻击网站的SQL 注入。此外,根据某些来源,准备好的语句可能比普通查询更快(但是,根据我的经验,它们在执行简单查询时几乎相同。但是,对于重复查询,准备好的语句比普通查询快)。准备好的语句最好的地方是可读性。它们很容易被阅读、理解和管理。

先决条件

在开始之前,您将需要这些东西。

  • 安装了 PHP 和 MYSQL 的计算机。
  • 已连接到数据库的 PHP 脚本。我们将把数据库连接保存在$mysqli中。
    <?php
    $mysqli = new mysqli( 'hostname', 'username', 'password', 'database' );

  • 在本教程中,我们的数据库中将有一个这样的“user”表
    idnameemail
    1Teodorteod@gmail.com
    2Christchristoperkhawand@gmail.com
    3Austinaustin@gmail.com
    4Ayushayushagarwal@gmail.com

如何在 PHP 中使用准备好的语句

让我们看看如何使用 MYSQLI 在 PHP 中执行准备好的语句。这是基本概念。在各种查询(SELECT、UPDATE 等)中,我们将使用不同的方式(和技巧)。

  • 首先,应该准备一个查询。
    $stmt = $mysqli -> prepare('SELECT * FROM users WHERE id = ?');

    在这里,我们将语句存储在$stmt中。这是一个mysqli_stmt对象。在接下来的步骤中,我们将调用此类的方法来执行操作。

    请注意? 查询中的(问号)用作占位符。我们对 MYSQL 说这是一个空盒子,我们将在未来填充它。

  • 接下来,我们绑定数据。这就像填满盒子。
    $userId = 2;
    $stmt -> bind_param('i', $userId);

    这里我们将绑定2作为用户的 id。在bind_param()方法中,第一个参数表示每个变量的数据类型。例如,如果您要绑定三个变量(空框),它们分别是整数、整数、字符串、整数,您可以使用'iisi'。

    无缘无故,在 PHP 中,以下内容无效。bind_param函数的参数应该是除第一个之外的变量。
    $stmt -> bind_param('i', 2);
    
  • 接下来,我们执行查询
    $stmt -> execute();
    在此步骤之后,过程会根据您将执行的查询而有所不同。让我们看一些例子。

1. SELECT - 选择一行

$stmt = $mysqli -> prepare('SELECT name, email FROM users WHERE id = ?');

$userId = 1; // or $_GET['userId'];

$stmt -> bind_param('i', $userId);
$stmt -> execute();
$stmt -> store_result();
$stmt -> bind_result($name, $email);
$stmt -> fetch();

echo $name; // Teodor
echo $email; // teod@gmail.com
  • store_result()存储结果。
  • bind_result()将值绑定到变量。
  • fetch()将结果提取到变量中。

起初,如果您是初学者,这很棘手。但是,当您执行其他步骤时,您会明白。请记住,fetch()将当前行的结果保存在bind_result()的变量中。默认情况下,当前行是结果集中的第一行。当我们调用一次fetch()时,当前行是结果中的第二行。但是,我们在此查询中只有一行。

2. SELECT - 选择多行

$stmt = $mysqli -> prepare('SELECT name, email FROM users');

$stmt -> execute();
$stmt -> store_result();
$stmt -> bind_result($name, $email);

while ($stmt -> fetch()) {
	echo $name;
	echo $email;
}

当您没有任何要传递的变量时,不需要bind_param()函数。这将选择所有用户并回显所有用户的姓名和电子邮件。

特别说明:

  • fetch()成功时返回 true,失败时返回 false。如果没有找到行,它将返回 false。所以,我们可以直接用它作为while循环的条件。
  • 在每次调用fetch()时,当前行的结果都保存在$name和$email变量中。并且,光标移动到下一行。(所以,当我们下次调用 fetch 时,它会获取下一行)

3. SELECT - 获取所选行数

$stmt = $mysqli -> prepare('SELECT name, email FROM users');

$stmt -> execute();
$stmt -> store_result();
// 4
echo $stmt -> num_rows;

需要记住的一件事是,应该在使用num_rows属性之前调用store_result() 。

4. 选择 - 获取结果

$stmt = $mysqli -> prepare('SELECT name, email FROM users WHERE id > ?');

$greaterThan = 1;
$stmt -> bind_param('i', $greaterThan);
$stmt -> execute();
$result = $stmt -> get_result();

现在$result与$mysqli -> query(...)相同。您可以使用以下内容来使用结果。

while ($row = $result -> fetch_assoc()) {
	echo $row['name']; 
	echo $row['email'];
}

5. SELECT - 带通配符

通配符用于匹配 MYSQL 中的模式。

<?php
$stmt = $mysqli -> prepare('SELECT name, email FROM users WHERE name LIKE ?');

$like = 'a%';
$stmt -> bind_param('s', $like);
$stmt -> execute();
$stmt -> store_result();
$stmt -> bind_result($name, $email);

while ($stmt -> fetch()) {
	echo $name;
	echo $email;
}

在此示例中,我们将选择名称以字母a开头的所有用户。(奥斯汀和阿尤什)

6. SELECT - 带有 ID 数组

在使用准备好的语句时,这是一件非常困难的事情。我们需要动态地将问号添加到查询中。

// array of user IDs
$userIdArray = [1,2,3,4];
// number of question marks
$questionMarksCount = count($userIdArray);
// create a array with question marks
$questionMarks = array_fill(0, $questionMarksCount, '?');
// join them with ,
$questionMarks = implode(',', $questionMarks);
// data types for bind param
$dataTypes = str_repeat('i', $questionMarksCount);

$stmt = $mysqli -> prepare("SELECT name, email FROM users WHERE id IN ($questionMarks)");

$stmt -> bind_param($dataTypes, ...$userIdArray);
$stmt -> execute();
$stmt -> store_result();
$stmt -> bind_result($name, $email);

while ($stmt -> fetch()) {
	echo $name;
	echo $email;
}

7. 选择 - 限制和偏移

$stmt = $mysqli -> prepare("SELECT name, email FROM users LIMIT ? OFFSET ?");

// limit of rows
$limit = 2;
// skip n rows
$offset = 1;

$stmt -> bind_param('ii', $limit, $offset);
$stmt -> execute();
$stmt -> store_result();
$stmt -> bind_result($name, $email);

while ($stmt -> fetch()) {
	echo $name;
	echo $email;
}

8. 选择 - 之间

$stmt = $mysqli -> prepare("SELECT name, email FROM users WHERE id BETWEEN ? AND ?");

$betweenStart = 2;
$betweenEnd = 4;

$stmt -> bind_param('ii', $betweenStart, $betweenEnd);
$stmt -> execute();
$stmt -> store_result();
$stmt -> bind_result($name, $email);

while ($stmt -> fetch()) {
	echo $name;
	echo $email;
}

9. 插入 - 一行

$stmt = $mysqli -> prepare('INSERT INTO users (name, email) VALUES (?,?)');

$name = 'Akhil';
$email = 'akhilkumar@gmail.com';

$stmt -> bind_param('ss', $name, $email);
$stmt -> execute();

10. INSERT - 获取插入 ID

如果您有一个用于保存 ID 的自动增量列,在许多情况下,我们需要知道我们刚刚插入数据库的用户的 ID 是什么。在这种情况下使用$stmt -> insert_id属性。

$stmt = $mysqli -> prepare('INSERT INTO users (name, email) VALUES (?,?)');

$name = 'Akhil';
$email = 'akhilkumar@gmail.com';

$stmt -> bind_param('ss', $name, $email);
$stmt -> execute();

echo 'Your account id is ' . $stmt -> insert_id;

11. INSERT - 多行(递归)

使用准备好的语句完成递归插入非常强大。我们准备一个语句并使用它来插入多行。

$newUsers = [
	[ 'sulliops', 'sulliops@gmail.com' ],
	[ 'infinity', 'infinity@gmail.com' ],
	[ 'aivarasco', 'aivarasco@gmail.com' ]
];

$stmt = $mysqli -> prepare('INSERT INTO users (name, email) VALUES (?,?)');

foreach ($newUsers as $user) {
		
	$name = $user[0];
	$email = $user[1];

	$stmt -> bind_param('ss', $name, $email);
	$stmt -> execute();

	echo "{$name}'s account id is {$stmt -> insert_id}";

}

每次插入新行时,您都会看到$stmt -> insert_id更新。

12. 更新

$stmt = $mysqli -> prepare('UPDATE users SET email = ? WHERE id = ? LIMIT 1');
	
$email = 'newemail@hyvor.com';
$id = 2;

$stmt -> bind_param('si', $email, $id);
$stmt -> execute();

13. 更新 - 获取受影响的行

有时您需要知道我们的 UPDATE 查询影响了多少行。

$stmt = $mysqli -> prepare('UPDATE users SET email = ? WHERE name = ? LIMIT 1');
	
$email = 'newemail@hyvor.com';
$name = 'teodor';

$stmt -> bind_param('ss', $email, $name);
$stmt -> execute();

// 1
echo $stmt -> affected_rows;

14. 删除

$stmt = $mysqli -> prepare('DELETE FROM users WHERE id = ?');
	
$userId = 4;

$stmt -> bind_param('i', $userId);
$stmt -> execute();

// number of deleted rows
echo $stmt -> affected_rows;

处理错误

知道如何调试 MYSQLI 准备好的语句总是很好的。这里有一些提示。

1. 准备失败时

有时$mysqli -> prepare()函数会因为查询错误而失败。

如何检测?

$stmt = $mysqli -> prepare('SELECT * FROM no_table WHERE id = ?');
	
$id = 1;
$stmt -> bind_param('i', $id);

如果您在调用$stmt的方法时 看到 PHP 中的错误,例如“在布尔值上调用成员函数 bind_param()”,则说明准备工作失败。当$mysql -> prepare()失败时,它返回false。因此$stmt是一个布尔值,而不是一个对象。现在我们可以使用$mysqli -> error来查找查询中的错误。

$stmt = $mysqli -> prepare('SELECT * FROM no_table WHERE id = ?');
echo $mysqli -> error;

2. 执行失败时

执行失败通常不会引发错误。因此,您应该添加一个条件来检查执行是否成功。如果不是,$stmt -> error会告诉你什么是错误。

$stmt = $mysqli -> prepare('INSERT INTO stmt_users (name) VALUES (?)');
	
$name = 'User';
$stmt -> bind_param('i', $name);

if (! $stmt -> execute()) {
	echo $stmt -> error;
}

对于我们的示例表,错误是"Field 'email' doesn't have a default value"

结论

我的目标是涵盖在本教程中执行准备好的语句的所有方法。我们讨论了如何为 SELECT、INSERT、UPDATE 和 DELETE 使用准备好的语句。所以,我希望我涵盖了所有内容。如果您愿意学习执行 MYSQLI 准备好的语句的最佳方法,那么本文适合您。我正在等待在评论部分看到您的反馈。感谢您的阅读!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值