MySqli 扩展库
创建一个商品数据表
create database shopDB charset utf8; use shopDB; CREATE TABLE `products` ( `id` mediumint unsigned NOT NULL AUTO_INCREMENT, `ishow` tinyint unsigned NOT NULL DEFAULT '0', `name` varchar(50) NOT NULL DEFAULT '0', `phone` varchar(50) NOT NULL DEFAULT '0', `intro` varchar(1500) NOT NULL DEFAULT '0', `time` varchar(50) NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; CREATE TABLE `products` ( `id` mediumint unsigned NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL DEFAULT '0', `price` varchar(50) NOT NULL DEFAULT '0', `num` varchar(50) NOT NULL DEFAULT '0', `detail` varchar(500) NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; truncate table products;
PHP5.0最主要的是将面向对象全面改写了,5.0以后增加功能,都会以对象的形式增加,
mysqli被封装在一个类中(i表示改进的意思),是一个面向对象对技,但也支持过程化的使用方式
window下安装mysqli扩展库
打开安装扩展的目录,每个扩展就是一个库 D:\xampp\php\ext\ 安装一个 php_mysqli.dll 文件
打开PHP配置文件 D:\xampp\php\php.ini ;extension=mysqli 把前面的分号去掉
重启服务器,通过 phpinfo
按照功能区分,mysqli扩展提供了三个类
1. MySQLi 和连接有关的类
主要控制PHP和mysql数据之间对链接、选择数据库、向mysql数据库服务器发生sql语句,以及设置字符集等等
2. Mysqli_result 处理结果集类
结果集就是用select语句从数据库中查询出来的,可以从结果集里面获取到记录信息、字段信息
以上两个类就可以完成前面mysql扩展的功能,而且效率更高、更稳定
第三个类就是mysqli新加的功能,我们通常叫预处理类
3. Mysqli_stmt 预处理类(后面重点介绍)
表达了一个准备好对语句
因为mysqli支持面向对象编程,也支持过程化的方式,所以手册上任何一个实例,都提供了面向对象的方法和过程化的两种方法
https://www.php.net/manual/zh/book.mysqli.php
处理数据都离不开下面几个步骤
1. 链接数据库
2. 选择数据库
3. 执行查询语句
4. 处理结果集
一、如何使用mysqli类
构造函数 mysqli() 连接数据库,链接成功返回 mysqli 对象
$mysqli = new mysqli('localhost', 'root', '', 'shopDB', '3306'); // 主机地址, 用户名, 密码, 数据库, 端口(可选) var_dump($mysqli); // object(mysqli)#1 (18) { ... }
如果链接失败也返回 mysqli 对象,对象里面的两个属性(对象里有三个属性)
connect_errno 返回错误码,链接成功返回0
connect_error 返回错误信息
header('Content-Type: text/html; charset=utf-8'); error_reporting(0); // 防止出现 Warning: mysqli::__construct(): (HY000/1045): Access denied for user 'root'@'localhost' (using password: YES) in $mysqli = new mysqli('localhost', 'root', '错误密码', 'shopDB', '3306'); var_dump($mysqli); // object(mysqli)#1 (3) { ... } if ($mysqli->connect_errno) { echo "Mysqli Link Error: $mysqli->connect_errno $mysqli->connect_error"; // Mysqli Link Error: 1045 Access denied for user 'root'@'localhost' (using password: YES) exit; } $mysqli->close(); // 脚本执行完,关闭链接
二个面向过程化的函数检查连接错误?
error_reporting(0); $mysqli = new mysqli('localhost', 'root', '错误密码', 'shopDB', '3306'); if(mysqli_connect_errno()){ // 如果连接错误返回的是1045,进入判断 echo mysqli_connect_errno(); // 返回链接错误号,链接失败返回1045,链接正确返回 0 echo mysqli_connect_error(); // 返回错误信息的 $mysqli = null; // 把 mysqli对象赋值为null,就不是对象了 exit; }
select_db('dbname') 在程序执行过程中切换数据库
$mysqli = new mysqli('localhost', 'root', '', '', '3306'); $mysqli->select_db('dbshop'); // 创建mysqli对象时不写数据库或写了默认的库,可以在程序执行过程中切换数据库 if ($mysqli->connect_errno) { echo "Mysqli Link Error: $mysqli->connect_errno $mysqli->connect_error"; exit; } $mysqli->close();
mysqli_init(void) 还有一种连接数据库的方式
$mysqli = mysqli_init(); // 返回一个mysqli对象 // 可以设置选项优化 // https://www.php.net/manual/zh/mysqli.options.php // options( in option, mixed value ) $mysqli->real_connect('127.0.0.1', 'root', '', 'shopDB'); // 连接数据库 if($mysqli->connect_errno){ echo "Mysqli Link Error: $mysqli->connect_errno $mysqli->connect_error"; exit; }else{ echo '链接成功'; } $mysqli->close();
获取服务器端、客户端信息的方法/属性
character_set_name() 获取当前字符集(mysql用的什么字符集)
get_client_info() 获取mysql客户端的信息
host_info 主机信息
protocol_version 协议的版本
server_info 服务器的信息
server_version 服务器的版本
info 获取最近执行的查询信息(还没测试这个)
$mysqli = new mysqli('localhost', 'root', '', 'shopDB', '3306'); echo $mysqli->character_set_name().'<br/>'; // utf8mb4 echo $mysqli->get_client_info().'<br/>'; // mysqlnd 7.4.20 echo $mysqli->host_info.'<br/>'; // localhost via TCP/IP echo $mysqli->protocol_version.'<br/>'; // 10 echo $mysqli->server_info.'<br/>'; // 5.5.5-10.4.19-MariaDB echo $mysqli->server_version.'<br/>'; // 100419 echo $mysqli->info.'<br/>'; // $mysqli->close();
如何执行sql语句?
执行sql语句的方式有多种
1. query() 执行sql语句(最常用的)
2. prepare() 准备执行一个sql查询语句
3. multi_query() 执行多个查询语句
sql语句又分两种,
1. 一种是select语句有结果集
2. 还有一种非select语句会影响行数
queyr()方法发送sql语句到数据库并且执行
1. 非select语句返回bool类型,成功返回真/失败返回假
2. select语句返回结果集对象
通过Mysqli对象里面的两个属性,获取错误信息?
errno 获取错误号
error 获取错误信息
提示的错误
字段写错了 1054 | Unknown column 'xxx' in 'field list' 未知的列 xxx 在字段列表里面
表名写错了 1146 | Table 'shopdb.productsxxx' doesn't exist 表名productsxxx不存在 把表名称写错
query( string query, [, int resultmode] ) 只传一个sql语句参数就行了
$mysqli = new mysqli('localhost', 'root', '', 'shopDB', '3306'); if ($mysqli->connect_errno) { echo "Mysqli Link Error: $mysqli->connect_errno $mysqli->connect_error"; exit; } $sql = "insert into products(id, name, price, num, detail)values(null, 'HUAWEI', '6000', '300', 'HarmonyOS操作系统')"; $result = $mysqli->query($sql); var_dump($result); // bool(true)(非select语句返回布尔类型) if(!$result){ echo "sql语句有误 $mysqli->errno | $mysqli->error"; exit; } $mysqli->close();
循环插入 80 条数据
$mysqli = new mysqli('localhost', 'root', '', 'shopDB', '3306'); $products = ['华为', '小米', '苹果', 'oppo', 'vivo']; $detail = ['双卡双待', '4G', '快速充电', '无线充电', '硬件配置高', '像素高']; for($i = 0; $i < 80; $i++){ $sql = "insert into products(id, name, price, num, detail)values(null, '".$products[rand(0, 4)]."', '".rand(10000, 1999)."', '".rand(200, 10)."', '".$detail[rand(0, 5)]."')"; $result = $mysqli->query($sql); echo "插入 $i 成功<br>"; } $mysqli->close();
非select语句执行成功,会有影响的行数
删除语句影响行数
1. 第一次刷新,删除多行,影响多行
2. 再刷新一次影响0条,sql 语句本身没有错,只是没有满足条件的记录而已,所以可以判断影响的行数大于0,才是真正的删除成功或修改成功了
$mysqli = new mysqli('localhost', 'root', '', 'shopDB', '3306'); if ($mysqli->connect_errno) { echo "Mysqli Link Error: $mysqli->connect_errno $mysqli->connect_error"; exit; } $sql = "delete from products where id > '60'"; $result = $mysqli->query($sql); if(!$result){ echo "sql语句有误 $mysqli->errno | $mysqli->error"; exit; } if($mysqli->affected_rows > 0){ echo "删除语句成功,影响 $mysqli->affected_rows 行"; }else{ echo '没有行数被影响'; } $mysqli->close();
insert_id 属性获取最后自动增长的id列
$mysqli = new mysqli('localhost', 'root', '', 'shopDB', '3306'); if ($mysqli->connect_errno) { echo "Mysqli Link Error: $mysqli->connect_errno $mysqli->connect_error"; exit; } $sql = "insert into products(id, name, price, num, detail)values(null, 'HUAWEI', '6000', '300', 'HarmonyOS操作系统')"; $result = $mysqli->query($sql); if(!$result){ echo "sql语句有误 $mysqli->errno | $mysqli->error"; exit; } if($mysqli->affected_rows > 0){ echo "影响 $mysqli->affected_rows 行<br/>"; } echo "最后增长的ID ", $mysqli->insert_id; // 获取最后自动增长的id列 $mysqli->close();
二、处理结果集
mysqli三个类中 mysqli_result 专门处理 select 语句后返回的结果集
结果集主要处理两方面
1. 处理记录,就是把记录一条一条的读取出来
2. 处理字段信息,如何把结果集中列(字段)信息,比如列名、列的属性获取到
执行 select 查询语句,返回的是结果集,在这里结果集就是一个对象
header('Content-Type: text/html; charset=utf-8'); $mysqli = new mysqli("localhost", "root", "", "shopdb", "3306"); if ($mysqli->connect_errno) { echo "Mysqli Link Error: $mysqli->connect_errno $mysqli->connect_error"; exit; } $sql ="select * from products"; $result = $mysqli->query($sql); // 返回的结果集是一个对象 if(!$result){ echo "Sql语句错误: $mysqli->errno $mysqli->error"; exit; } var_dump($result); // object(mysqli_result)#2 (5) { ["current_field"]=> int(0) ["field_count"]=> int(5) ["lengths"]=> NULL ["num_rows"]=> int(69) ["type"]=> int(0) } $result->close(); // 释放结果集 $mysqli->close();
按过程化来说,结果集也是一种资源,所以也需要释放,下面三个方法用那个都可以
free()
close()
free_result()
有了这个结果集对象,下面是结果集对象中的方法和属性,我们可以从结果集里面获取任意信息
方法
close()
data_seek() 指定从第几条数据开始获取数据
fetch_array() 返回记录,参数(MYSQL_ASSOCI, MYSQLI_NUM, MYSQLI_BOTH,默认是第三个)
fetch_assoc() 返回记录,关联数组的方式
fetch_field() 获取列信息
fetch_fields()
fetch_field_direct()
fetch_object()返回记录,对象的形式
fetch_row() 返回记录,索引数组的形式
field_seek() 字段(列)移动指针的
free_result()
属性
current_field 获取当前列的列号
field_count 获取结果集中的列数,有几个字段
lengths 返回当前列中字段的长度
num_rows 获取结果集中的行数,共有多少条数据
type
1、获取记录信息
获取行数和列数
num_rows属性,结果集中共有多少条数据
field_count属性,结果集中的列数,就是有几个字段(这个和下面获自段信息有点联系)
$mysqli = new mysqli("localhost", "root", "", "shopdb", "3306"); if ($mysqli->connect_errno) { echo "Mysqli Link Error: $mysqli->connect_errno $mysqli->connect_error"; exit; } $sql ="select id, name from products where id < 50"; // 查询2个字段加一个where条件限制,会影响取到的行数和列数 $result = $mysqli->query($sql); if(!$result){ echo "Sql语句错误: $mysqli->errno $mysqli->error"; exit; } $rows = $result->num_rows; // 获取结果集中的行数 $cols = $result->field_count; // 获取结果集中的列数(列的个数和下面) echo "数据表中有{$rows}行,{$cols}列"; // 数据表中有49行,2列 $result->close(); // 关闭结果集 $mysqli->close();
fetch_assoc() 返回关联数组,下标就是列名
data_seek(5) 移动指针
close() 释放结果集
获取记录信息有四个方法
fetch_row() 返回索引数组
fetch_assoc() 返回关联数组,下标就是列名
fetch_array() 两个数组都返回,参数(MYSQL_ASSOC, MYSQLI_NUM, MYSQLI_BOTH默认是第三个)
fetch_object() 返回对象
每执行一次,会从结果集中取出当前一条记录(默认当前记录就是第一行)。可以使用 data_seek(5) 方法指定,5表示默认从第五行记录开始取
$mysqli = new mysqli("localhost", "root", "", "shopdb", "3306"); if ($mysqli->connect_errno) { echo "Mysqli Link Error: $mysqli->connect_errno $mysqli->connect_error"; exit; } $sql ="select * from products"; $result = $mysqli->query($sql); if(!$result){ echo "Sql语句错误: $mysqli->errno $mysqli->error"; exit; } $assoc = $result->fetch_assoc(); // 每执行一次,从结果集中取出当前一条记录 print_r($assoc); // Array ( [id] => 1 [name] => vivo [price] => 7008 [num] => 48 [detail] => 快速充电 ) $result->close(); $mysqli->close();
每次取出一行,指针指向下一行,下次再取时就会在取出下一行,当结果集中没有记录时返回false,所以可以用循环取出数组
header('Content-Type: text/html; charset=utf-8'); $mysqli = new mysqli("localhost", "root", "", "shopdb", "3306"); if ($mysqli->connect_errno) { echo "Mysqli Link Error: $mysqli->connect_errno $mysqli->connect_error"; exit; } $sql ="select * from products"; $result = $mysqli->query($sql); if(!$result){ echo "Sql语句错误: $mysqli->errno $mysqli->error"; exit; } // 每循环一次换一行,当最后一条获取不到时,返回false退出循环,正常的情况下返回数组,数组会当成true来处理 if($result = $mysqli->query($sql)){ while($rows = $result->fetch_assoc()){ echo "<br/>"; print_r($rows); } } $result->close(); $mysqli->close();
用表格的形式打印出来
$mysqli = new mysqli("localhost", "root", "", "shopdb", "3306"); if ($mysqli->connect_errno) { echo "Mysqli Link Error: $mysqli->connect_errno $mysqli->connect_error"; exit; } $result = $mysqli->query("select * from products"); $result->data_seek(50); // 从结果集里面移动到第5行开始取数据,实际是从第6个开始显示 if(!$result){ echo "Sql语句错误: $mysqli->errno $mysqli->error"; exit; } echo '<table border="1" align="center" width="900">'; while($rows = $result->fetch_assoc()){ echo '<tr>'; // 可以用便利 // foreach($rows as $val){ // echo "<td>{$val}</td>"; // } // 也可以一行一行的写出每个单元 echo "<td>{$rows['id']}</td> <td>{$rows['name']}</td> <td>{$rows['price']}</td> <td>{$rows['detail']}</td>"; echo '</tr>'; } echo '</table>'; $result->close(); $mysqli->close();
2、获取字段(列)信息
fetch_field() 方法获取列信息
1. 获取完一列,指针往下走一次
2. 返回来的是一个对象,通过这个对象我们能获取
name 列名
orgname 列的原名(因为列可以起别名)
table 表名
orgtable 原表名
max_length 最大长度,字段值的最大列的长度
length 长度
charsetnr 字符集
type 类型
只获取列的名称(name)和列长度(max_length)
$mysqli = new mysqli("localhost", "root", "", "shopdb", "3306"); $result = $mysqli->query("select * from products where id <= 3"); echo '<table border="1" align="center" width="900">'; echo '<tr>'; // 一共有5列自动循环五列,到最后一列返回false就结束循环了 while($field = $result->fetch_field()){ echo "<th>{$field->name} - {$field->max_length}</th>"; // 返回来一个对象$field,在对象里$field里获取列名称和列长度 } echo '</tr>'; while($rows = $result->fetch_assoc()){ echo '<tr>'; echo "<td>{$rows['id']}</td> <td>{$rows['name']}</td> <td>{$rows['price']}</td> <td>{$rows['num']}</td> <td>{$rows['detail']}</td>"; echo '</tr>'; } echo '</table>'; $mysqli->close();
fetch_fields() 方法
1. 一次性把所有列全取过来了,然后形成一个数组,
2. 数组里面每一个成员,就是每一个列的对象
$mysqli = new mysqli("localhost", "root", "", "shopdb", "3306"); $result = $mysqli->query("select * from products where id < 10"); $field = $result->fetch_fields(); // 这里不用循环,把所有列都取出来 print_r($field); // 便利这个数组就可以了 $mysqli->close();
上面说过 data_seek() 方法可以移动记录的指针,这里的 field_seek() 方法可以移动字段的指针
lengths 属性是结果集对象的属性,返回当前列中单个字段的长度
$mysqli = new mysqli("localhost", "root", "", "shopdb", "3306"); $result = $mysqli->query("select * from products where id < 10"); echo '<table border="1" align="center" width="900">'; while($rows = $result->fetch_assoc()){ echo "<tr> <td>[{$result->lengths[0]}]-{$rows['id']}</td> <td>[{$result->lengths[1]}]-{$rows['name']}</td> <td>[{$result->lengths[2]}]-{$rows['price']}</td> <td>[{$result->lengths[3]}]-{$rows['num']}</td> <td>[{$result->lengths[4]}]-{$rows['detail']}</td> </tr>"; } echo '</table>'; $mysqli->close();
current_field 是结果集对象的属性,获取当前列的列号
$mysqli = new mysqli("localhost", "root", "", "shopdb", "3306"); $result = $mysqli->query("select * from products where id < 10"); echo '<table border="1" align="center" width="900">'; echo '<tr>'; while($field = $result->fetch_field()){ // current_field属性是结果集里面的属性,作用是返回当前列的列号 echo "<th>{$result->current_field}_{$field->name} - {$field->max_length}</th>"; } echo '</tr>'; while($rows = $result->fetch_assoc()){ echo '<tr>'; echo "<td>{$rows['id']}</td><td>{$rows['name']}</td><td>{$rows['price']}</td><td>{$rows['num']}</td><td>{$rows['detail']}</td>"; echo '</tr>'; } echo '</table>'; $mysqli->close();
sql语句查看表结构 desc products 可以看到那个是主键,那个是唯一索引,那个字段是否为空,下面通过该语句获取表的详细信息
$mysqli = new mysqli("localhost", "root", "", "shopdb", "3306"); $result = $mysqli->query("desc products"); // 通过该sql语句获取表信息 echo '<table border="1" align="center" width="900">'; echo '<tr>'; while($field = $result->fetch_field()){ echo "<th>{$field->name}</th>"; } echo '</tr>'; while($rows = $result->fetch_assoc()){ echo '<tr>'; foreach($rows as $val){ echo "<td>{$val}</td>"; } echo '</tr>'; } echo '</table>'; $mysqli->close();