通过 PHP Mysqli 扩展与 MySQL 数据库交互

由 学院君 创建于8个月前, 最后更新于 6个月前

版本号 #1

1269 views

0 likes

0 collects

引言

前面学院君给大家简单介绍了如何在本地安装 MySQL 以及通过命令行和 GUI 客户端软件与 MySQL 服务器进行交互。

在命令行可以通过命令与 MySQL 交互,在客户端软件可以通过图形化界面与 MySQL 交互,那么在 PHP 程序中如何建立与 MySQL 的连接和交互呢?实际上,我们完全可以把 PHP 应用看作是 MySQL 服务器的客户端,然后通过封装好的 PHP 扩展包提供的 API 与 MySQL 服务器进行交互,就好像我们在命令行和客户端软件中所做的一样,只不过现在这种交互由手动操作转变成了通过编写对应的 PHP 代码来完成。

PHP MySQLi 扩展

PHP 官方提供了很多用于与 MySQL 服务器进行交互的扩展,从最早的 mysql 到后来增强版的 mysqli(更加安全),它们都是 PHP 函数式编程时代的扩展包,一般来说,本地 PHP 集成开发环境都会自带 mysqli 扩展:

下面我们通过一个简单的示例来演示如何通过 mysqli 扩展与 MySQL 服务器交互。

数据库连接与查询

示例代码

在 php_learning 目录下新增一个 mysql 子目录,然后在该子目录下新建一个 mysqli.php 文件,编写一段通过 mysqli 扩展 API 建立数据库连接和查询的代码:

$host = '127.0.0.1'; // MySQL 服务器主机地址

$port = 3306; // MySQL 服务器进程端口号

$user = 'root'; // 用户名

$password = 'root'; // 密码

$dbname = 'test'; // 使用的数据库名称

// 通过 mysqli 扩展建立与 mysql 服务器的连接

$conn = mysqli_connect($host, $user, $password, $dbname, $port);

// 在连接实例上进行查询

$sql = 'SELECT * FROM `post`';

$res = mysqli_query($conn, $sql);

// 获取所有结果

$rows = mysqli_fetch_all($res);

var_dump($rows);

// 释放资源

mysqli_free_result($res);

// 关闭连接

mysqli_close($conn);

可以看到,通过 mysqli_connect 函数即可建立与 MySQL 数据库的连接,我们传入了5个参数,依次是数据库主机、用户名、密码、数据库名称和端口号,建立连接成功后,就可以持有这个连接实例通过 mysqli_query 函数执行数据库查询了,我们将 SQL 语句作为第二个参数传入,该函数的返回结果是一个查询结果集实例,拿到这个实例之后,就可以通过 mysqli_fetch_* 系列函数获取结果数据了。

这里我们通过 mysqli_fetch_all 函数获取所有查询结果,通过 php -S localhost:9000 启动 PHP 内置 HTTP 服务器:

就可以在浏览器中通过 http://localhost:9000/mysql/mysqli.php 打印的查询结果了:

优化渲染效果

这个时候页面样式可读性很差,可以在源码中打印输出结果之前,插入一段 echo '

' 代码优化渲染效果:

// 获取所有结果

$rows = mysqli_fetch_all($res);

echo '

';

var_dump($rows);

刷新浏览器页面,就可以看到如下打印效果:

设置字符编码

这里有个小问题,那就是 Emoji 表情符号没有正常显示出来,乱码了,我们可以像在命令行中设置默认字符编码一样,通过 mysqli_set_charset 函数设置字符编码为 utf8mb4:

// 通过 mysqli 扩展建立与 mysql 服务器的连接

$conn = mysqli_connect($host, $user, $password, $dbname, $port);

// 设置字符编码为 utf8mb4

mysqli_set_charset($conn, 'utf8mb4');

...

// 获取所有结果

$rows = mysqli_fetch_all($res);

echo '

';

var_dump($rows[2]);

刷新页面就可以看到 Emoji 表情了:

返回关联数组

目前返回的结果是索引数组,无法得知数值对应的字段名,要获取完整的字段名与字段值映射,可以将传入 mysqli_fetch_all 函数的第二个参数值设置为 MYSQLI_ASSOC 来实现(默认是 MYSQLI_NUM):

// 获取所有结果(关联数组)

$rows = mysqli_fetch_all($res, MYSQLI_ASSOC);

echo '

';

var_dump($rows[2]);

返回单条结果

上面返回的都是多条结果(即使只返回一条记录,返回的也是多维数组),有时候,我们只想返回结果集中的第一条结果,这时候可以通过 mysqli_fetch_row 函数来实现:

// 在连接实例上进行查询

$sql = 'SELECT * FROM `post` WHERE id = 1';

$res = mysqli_query($conn, $sql);

// 获取所有结果

/*

$rows = mysqli_fetch_all($res, MYSQLI_ASSOC);

echo '

';

var_dump($rows);*/

// 获取单条结果

$row = mysqli_fetch_row($res);

echo '

';

var_dump($row);

刷新浏览器测试页面,打印结果如下:

可以看到返回结果已经是一个一维数组了,只包含一条记录。如果想要返回关联数组结果,需要通过一个新的函数 mysqli_fetch_assoc 函数来实现:

// 获取单条结果

// $row = mysqli_fetch_row($res);

$row = mysqli_fetch_assoc($res);

echo '

';

var_dump($row);

对应的打印结果如下:

将返回结果映射到指定对象

除了返回数组格式结果外,还可以借助 mysqli_fetch_object 函数将数据库查询结果映射到指定对象实例并返回:

class Post

{

public $id;

public $title;

public $content;

public $created_at;

public function __toString()

{

return '[#' . $this->id . ']' . $this->title;

}

}

// 将数据库返回结果映射到指定个对象

$post = mysqli_fetch_object($res, Post::class);

echo $post;

对应的打印结果如下,说明对象映射成功(调用了对象的魔术方法 __toString 打印输出该对象):

避免 SQL 注入攻击

在上述数据库查询操作中,我们直接将原生 SQL 语句传递给 MySQL 数据库执行,如果 SQL 语句中包含了用户传递的参数,则存在 SQL 注入风险,要避免 SQL 注入攻击,在 mysqli 扩展中,可以通过构建预处理语句的方式实现:

首先通过 mysqli_prepare 函数构建包含占位符(替代具体参数值)的预处理 SQL 语句;

最后通过 mysqli_stmt_execute 函数执行填充参数值之后的完整 SQL 语句,由于底层做了转化处理,所以这时候执行的 SQL 语句不存在 SQL 注入风险。

下面,我们以插入记录到数据库为例,演示如何通过预处理语句的方式与数据库交互,提高代码安全性。

插入记录到数据库

我们首先基于预处理语句编写插入记录到数据库的代码如下(基于上面的 $conn 连接实例):

// 插入记录到数据库

$sql = 'INSERT INTO `post` (title, content, created_at) VALUES (?, ?, ?)';

// 构建预处理 SQL 语句

$stmt = mysqli_prepare($conn, $sql);

// 绑定参数值

$title = '这是一篇测试文章';

$content = '测试文章啊啊啊?';

$created_at = '2020-05-27';

mysqli_stmt_bind_param($stmt, 'sss', $title, $content, $created_at);

// 执行 SQL 语句

mysqli_stmt_execute($stmt);

// 打印影响行数

printf("%d Row inserted.\n", mysqli_stmt_affected_rows($stmt));

// 获取插入记录对应的主键ID

$lastInsertId = mysqli_stmt_insert_id($stmt);

// 释放资源

mysqli_stmt_close($stmt);

基本流程后上面介绍的预处理语句执行流程一致,需要注意的是在 mysqli_stmt_bind_param 的第二个参数中,需要指定参数类型,s 表示字符串,i 表示整型,d 表示浮点型,并且需要和后面跟着的具体参数值一一对应,即一个参数类型对应一个参数值,整个预处理语句执行过程中,需要持有初始化后的 $stmt 实例,最后执行完毕后,可以通过 mysqli_stmt_affected_rows 函数获取受影响的行数,对于插入语句,还可以通过 mysqli_stmt_insert_id 函数获取对应新增的主键 ID。

预处理语句执行之后,记得通过 mysqli_stmt_close 函数释放资源。

接下来,我们基于上面返回的 $lastInsertId 查询新增的记录:

// 查询新插入的记录

$sql = 'SELECT * FROM `post` WHERE id = ' . $lastInsertId;

$res = mysqli_query($conn, mysqli_escape_string($conn, $sql));

$post = mysqli_fetch_object($res, Post::class);

echo $post;

这里,我们用到了 mysqli_escape_string 函数,它可以在当前连接中对传入的 SQL 语句包含的特殊字符进行转义,从而得到一个编码合法的 SQL 语句,所以也可以通过它规避一些简单的 SQL 注入(数字型注入不生效),为了打印完整的 Post 对象内容,我们修改 Post 类的 __toString 方法实现如下:

class Post

{

...

public function __toString()

{

return '[#' . $this->id . ']' . $this->title . ':' . $this->content;

}

}

在浏览器中访问 http://localhost:9000/mysql/mysqli.php,打印结果如下,表明数据插入成功:

关于更新语句和删除语句参照插入语句实现即可,对于 mysqli 扩展来说,并没有针对 SELECT、INSERT、UDPATE、DELETE 语句提供不同的 API 方法,所有这些 DML 语句都可以通过 mysqli_query 或者 mysqli_stmt_execute 方法传入对应的 SQL 语句在 MySQL 服务器执行。更多细节,我这里就不一一介绍了,感兴趣的同学可以自行去 PHP 官方文档 查看 mysqli 扩展介绍。另外,mysqli 扩展也支持面向对象风格,你可以参照官方文档的示例,通过面向对象的风格实现本篇教程的示例代码。

下篇教程,我们来演示如何通过生而面向对象的、扩展性更强的、支持更多数据库的 PDO 扩展建立与 MySQL 数据库服务器的连接和交互。

mysql数据库与mysqli_通过 PHP Mysqli 扩展与 MySQL 数据库交互相关推荐

  1. mysqli扩展是mysql扩展的增强版_PHP学习笔记【22】--PHP数据库编程 mysql扩展库 和mysqli扩展库...

    <?php         // php数据库编程     //php链接有 mysql 和mysqli    //    $conn  = mysql_connect("localh ...

  2. php使用mysqli连接mysql数据库_PHP使用mysqli扩展连接MySQL数据库

    1.面向对象的使用方式 $db = new mysqli('localhost', 'root', '123456', 'dbname'); 如果建立连接时未指定数据库则选择使用的数据库,切换使用的数 ...

  3. PHP mysqli 扩展库(面向对象/数据库操作封装/事务控制/预编译)

    1.和mysql扩展库的区别: (1   安全性.稳定性更高 (2  提供了面向对象和面向过程两种风格 2.php.ini  中的  extension=php_mysqli.dll 解除封印 3.面 ...

  4. php面向对象封装mysql_PHP mysqli 扩展库(面向对象/数据库操作封装/事务控制/预编译)...

    1.和mysql扩展库的区别: (1   安全性.稳定性更高 (2  提供了面向对象和面向过程两种风格 2.php.ini  中的  extension=php_mysqli.dll 解除封印 3.面 ...

  5. php操作mysql数据库的扩展有哪些_8.PHP操作MySQL数据库(Mysqli扩展)

    思考:如果数据库的操作都是需要我们手动去调用客户端发送指令,那么这样的操作有什么意义呢? 引入:手动通过客户端操作MySQL数据库,只是我们学习SQL的一种手段.要实现数据库的自动调用,就需要客户端能 ...

  6. mysql报11004_使用mysqli扩展技术查看服务器连接错误报告的方法

    使用mysqli扩展技术查看服务器连接错误报告的方法 作为PHP的黄金搭档MySQL数据库,在PHP项目开发过程中有着举足轻重的作用,这不仅因为MySQL是完全免费的,而且和PHP一样都是完全跨平台的 ...

  7. 陈力:传智播客古代 珍宝币 泡泡龙游戏开发第39讲:PHP数据库编程MySQLi扩展库

    陈力:传智播客古代 珍宝币 泡泡龙游戏开发第39讲:PHP数据库编程MySQLi扩展库 mysqli扩展允许我们访问MySQL 数据库,并对MySql数据库进行curd操作.mysqli扩展可以进行数 ...

  8. php5.5 mysqli扩展,PHP 5的mysqli扩展

    在通常情况下,使用 PHP构建的应用系统都是搭配着 MySQL 数据库,很长时间以来,mysql扩展一直伴随着PHP与MySQL,并为二者之间的交互提供了通道.mysql扩展库提供的相关函数使PHP程 ...

  9. php mysql 持久化_PHP: mysqli 扩展和持久化连接 - Manual

    mysqli 扩展和持久化连接 从 PHP 5.3 mysqli 扩展开始支持持久化连接. 持久化连接已经在 PDO MYSQL 和 ext/mysql 中提供支持. 持久化连接的目的在于重用客户端到 ...

最新文章

  1. mysql用外键链接两个表_可能做一个MySQL外键的两个可能的表之一?
  2. 是否会回到起点.回忆只能是回忆
  3. Java抓取网页数据(原网页+Javascript返回数据)
  4. 1.1 Java包装类、装箱和拆箱
  5. 新建springBoot项目提示:The type org.springframework.context.ConfigurableApplicationContext cannot be resol
  6. 如果编程替换成中文就会怎样? 程序员看了表示头疼
  7. c++歌手大赛系统_计人即讯|第十届程序设计大赛
  8. android抽屉屏幕右滑,android - Android - 使滑动抽屉从左向右滑动 - 堆栈内存溢出...
  9. python的安装包下载_科学网—[转载]python常用的安装包下载 - 林清莹的博文
  10. Nginx根据User-Agent适配PC和手机
  11. oracle dba 连不上,Oracle10g的DBA无法登录解决方案
  12. python机器学习库keras——CNN卷积神经网络识别手写体
  13. 几个免费IP地址查询API接口
  14. 电力行业适合学习的开源软件
  15. MP4之sample信息
  16. mac蓝牙鼠标总是自己断开_解决Mac蓝牙鼠标和键盘经常断开的问题
  17. 数据库-音乐网站-sql
  18. linux如何扫描网络漏洞,在Linux系统上用nmap扫描SSL漏洞的方法
  19. SpringBoot+Mybatis+Thymeleaf-Build Blog site_2
  20. 微信支付V3版开发中遇到的一个问题及原因:缺少prepay_id

热门文章

  1. 山西计算机专业二本大学排名,2021年山西二本大学排名及录取分数线
  2. Kinect SDK(1):读取彩色、深度、骨骼信息并用OpenCV显示
  3. GIEC2022第九届全球互联网经济大会
  4. 超简单爬虫使用requests模块+有道云翻译,python实现翻译小功能
  5. BraTS 2021脑肿瘤分割数据集介绍
  6. iOS Pages插入方程功能分析
  7. 7种Normalization总结(batch normalization,layer normalization,Weight Normalization,Cosine Normalization)
  8. android四种点击事件,android点击事件的四种方式
  9. Unity 动态加载Prefab
  10. Visio中将多个自绘图形组合后填充颜色