Go to comments

PHP 的 MySqli 扩展库

php 可以通过三套扩展库,实现对 mysql 数据库的管理

1. mysql 扩展

2. mysqli 扩展

3. PDO 扩展,该扩展不仅可以处理mysql,还可以处理其他各种数据库


本节课讲解 mysqli 扩展库

1. PHP5.0 最主要的是将面向对象全面改写了,和 PHP4 比 PHP5 以后新增加的功能,都会以对象的形式增加

2. mysqli 扩展库了是 PHP5 里面新增加的,所以它也是一种面向对象对的技术,但也支持过程化的使用方式

   i 表示改进的意思,1).功能增加了,2).效率大大的增加,3).更稳定

3. mysqli 扩展只能在 PHP5.0 或更高的环境使用,MySQL 4.1 或更高的版本


window 下安装 mysqli 扩展库

1. 首先打开安装扩展的目录 D:\xampp\php\ext\,目录下有很多 PHP 扩展的功能,

    每个扩展就是一套库,比如 php_gd2.dll 

    如果看到一个 php_mysqli.dll 文件就是有这个库了

2. 打开 PHP 配置文件 D:\xampp\php\php.ini 开启 myqli 这个扩展库

     ;extension=mysqli  把前面的分号去掉

3. 重启 apche 服务器,然后通过 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


而且 mysqli 过程化的方式和之前很相似只不过多了一个 i

mysql(i)_connect()

mysql(i)_select_db()

mysql(i)_query()


为了便于测试,创建一个商品数据表

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;


一、操作 MySQL 数据库

处理数据都离不开下面几个步骤

1. 链接数据库

2. 选择数据库

3. 执行查询语句

4. 处理结果集


1、连接数据库

通常使用构造方法 mysqli() 连接数据库,链接成功返回 mysqli 对象

$mysqli = new mysqli('localhost', 'root', '', 'shopDB', '3306'); // 主机地址, 用户名, 密码, 数据库, 端口(可选)

var_dump($mysqli); // object(mysqli)#1 (18) { ... }


如果链接失败返回 mysqli 对象里面有两个属性

connect_errno 属性,返回错误码,链接成功返回 0,失败返回 1045

connect_error 属性,返回错误信息

error_reporting(0); // 屏蔽系统的警告

$mysqli = new mysqli('localhost', 'root', '错误密码', 'shopDB', '3306');

// var_dump($mysqli); // object(mysqli)#1 (18) { ... }

if ($mysqli->connect_errno) {
  echo $mysqli->connect_errno; // 1045
  echo $mysqli->connect_error; // Access denied for user 'root'@'localhost' (using password: YES)
  exit;
}

echo '连接数据库成功';

$mysqli->close(); // 关闭打开的连接


老师用了2个面向过程化的函数

$mysqli = @new mysqli('localhost', 'root', '错误密码', 'shopDB', '3306');

if(mysqli_connect_errno()){
  echo '连接失败';
  echo mysqli_connect_error();
  $mysqli = null; // 把mysqli对象赋值为null或false
  exit;
}

echo '连接数据库成功';

$mysqli->close();


 select_db('dbname')  在连接成功后,选择或切换数据库

$mysqli = new mysqli('localhost', 'root', ''); // 没有写第四个参数

if ($mysqli->connect_errno) {
  echo $mysqli->connect_errno;
  echo $mysqli->connect_error;
  exit;
}

$mysqli->select_db('dbshop'); // 选择数据库

echo '连接成功';

$mysqli->close();


还有一种 mysqli_init(void) 连接数据库的方式

mysqli_init 返回一个 mysqli 对象

real_connect 连接数据库

$mysqli = mysqli_init();

$mysqli->real_connect('127.0.0.1', 'root', '', 'shopDB');

if($mysqli->connect_errno){
  echo $mysqli->connect_error;
  exit;
}

echo '链接成功';

$mysqli->close();


options( in option, mixed value ) 

可以设置选项优化 

https://www.php.net/manual/zh/mysqli.options.php


2、获取服务器端、客户端信息的方法和属性

character_set_name()  获取当前字符集(mysql 用的什么字符集)

get_client_info()  获取 mysql 客户端的信息

host_info  主机信息

protocol_version  协议的版本

server_info  服务器的信息

server_version  服务器的版本

info  获取最近执行的查询信息

$mysqli = new mysqli('localhost', 'root', '', 'shopDB', '3306');

if($mysqli->connect_errno){
  echo $mysqli->connect_error;
  exit;
}

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();


3、执行 sql 语句

执行 sql 语句的方式有多种

1. query() 执行sql语句(最常用的)

2. prepare() 准备执行一个sql查询语句

3. multi_query() 执行多个查询语句


sql 语句又分两种

1. 一种是 select 语句有结果集

2. 还有一种非 select 语句,会影响行数


query( string query, [, int resultmode] )

使用 mysqi 里面的 queyr() 方法发送 sql 语句到数据库并且执行

1. 如果是非 select 语句返回 bool 类型,成功返回真,失败返回假

2. 如果是 select 语句返回结果集对象


这里是非 select 语句,

1. 非 select 语句返回 bool 类型,所以可以用返回 !$result 的判断 sql 语句是否成功,如果成功就不进入判断

2. 如果有 sql 语句有错误,如何获取错误信息呢?

    通过 Mysqli 对象里面的两个属性,errno 获取错误号,error 获取错误信息

$mysqli = @new mysqli('localhost', 'root', '', 'shopDB', '3306');

if($mysqli->connect_errno) {
  echo "数据连接错误" . $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)

if(!$result){
  echo "sql语句有误<br/>";
  echo $mysqli->errno;
  echo $mysqli->error;
  exit;
}

$mysqli->close();


记录 2 个提示的错误

字段写错了,提示 Unknown column 'xxx' in 'field list',未知的列 xxx 在字段列表里面

表名写错了,提示 Table 'shopdb.productsxxx' doesn't exist,表名 productsxxx 不存在


非 select 语句执行成功,

会影响的行数,通过 affected_rows 属性获取到影响的行数


什么语句会影响行数

插入语句 insert

删除语句 detele

更新语句 updata


插入一次影响 1 个行数

$mysqli = new mysqli('localhost', 'root', '', 'shopDB', '3306');

$products = ['华为', '小米', '苹果', 'oppo', 'vivo'];
$detail = ['双卡双待', '4G', '快速充电', '无线充电', '硬件配置高', '像素高'];

$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 $mysqli->affected_rows; // 1

$mysqli->close();


删除语句影响行数

1. 第一次刷新,删除多行,影响多行

2. 再刷新一次影响 0 条,

    sql 语句本身没有错,只是没有满足条件的记录而已

3. 所以判断影响的行数大于 0 的时候,是真正的删除成功,或真正修改成功了

$mysqli = new mysqli('localhost', 'root', '', 'shopDB', '3306');

$sql = "delete from products where id > '6'";
$result = $mysqli->query($sql);

if($mysqli->affected_rows > 0){
  echo "删除语句成功,影响 $mysqli->affected_rows 行";
}else{
  echo '没有行数被影响';
}

$mysqli->close();


!$result 是判断 sql 语句是否有误

affected_rows 属性是判断有没有行数被影响,要经常用到这个属性


insert_id

只有插入语句,而且表中有一列是自动增长的 ,才能获取到自动增长的 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. 处理字段信息,结果集中列(字段)信息,比如获取列名、列的属性


mysqli_result 结果集类里面的属性和方法

方法

名称作用参数
data_seek()移动记录的指针,指定从第几条数据开始获取数据data_seek(5)
fetch_array() 获取记录信息,关联索引两种数组

MYSQL_ASSOCI,MYSQLI_NUM,MYSQLI_BOTH 默认是第三个

fetch_assoc()获取信息,关联数组的方式
fetch_object()获取记录信息,对象的形式
fetch_row()获取记录信息,索引数组的形式
free_result()释放结果集
close()释放结果集
field_seek()移动字段(列)指针
fetch_field()获取列的信息,也是每次获一列,然后往下走一次
fetch_fields()

fetch_field_direct()

 

属性

名称作用
current_field获取当前列的列号
field_count获取结果集中的列数,有几个字段
lengths返回当前列中字段的长度
num_rows获取结果集中的行数,共有多少条数据
type


执行 select 查询语句,返回的是结果集,这里的结果集就是一个对象( object(mysqli_result)

header('Content-Type: text/html; charset=utf-8');

$mysqli = new mysqli("localhost", "root", "", "shopdb", "3306");

if ($mysqli->connect_errno) {
  echo "数据库连接错误".$mysqli->connect_error;
  exit;
}

$sql ="select * from products";

$result = $mysqli->query($sql); // 执行select语句返回的结果集是一个对象

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()


1、处理记录信息

获取记录信息的四个方法

fetch_row()     返回索引数组

fetch_assoc()  返回关联数组,下标就是列名

fetch_array()   两个数组都返回,尽量不使用,因为取两个数组效率不是那么高

fetch_object() 返回对象


每执行一次 fetch_assoc(),

就会从结果集中取出当前一条记录(默认当前记录就是第一行,可以使用 data_seek(5) 方法指定,5 表示默认从第五行记录开始取)

$mysqli = new mysqli("localhost", "root", "", "shopdb", "3306");

if ($mysqli->connect_errno) {
  echo "Mysqli Link Error: $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 的时候退出循环,正常的情况下返回数组,数组会当成 true 来处理

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_error";
  exit;
}

$sql ="select * from products";
$result = $mysqli->query($sql);

if(!$result){
  echo "Sql语句错误: $mysqli->errno $mysqli->error";
  exit;
}

// 每循环一次换一行,当最后一条获取不到时返回false退出循环,正常的情况下返回数组,数组会当成true来处理
while($rows = $result->fetch_assoc()){
  print_r($rows);
  echo "<br/>";
}

$result->close();
$mysqli->close();


用 table 表格的形式打印出来

$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); // 指定从结果集里面移动指针到第50行开始取数据

if(!$result){
  echo "Sql语句错误: $mysqli->errno $mysqli->error";
  exit;
}

echo '<table border="1" align="center" width="900">';
while($rows = $result->fetch_assoc()){
  echo '<tr>';
  // $rows是数组包含每一列的信息,可以用foreach便利数组
  // 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();


结果集中的行数和列数

num_rows 属性,获取结果集中共有多少条数据(多少行)

field_count 属性,获取结果集中的列数,就是有几个字段(这个和下面获自段信息有点联系)

$mysqli = new mysqli("localhost", "root", "", "shopdb", "3306");
if ($mysqli->connect_errno) {
  echo "Mysqli Link Error: $mysqli->connect_error";
  exit;
}

$sql ="select id, name from products where id < 50"; // 查询2个字段设置一个where条件限制,会影响取到的行数和列数
$result = $mysqli->query($sql);

$rows = $result->num_rows; // 获取结果集中的行数
$cols = $result->field_count; // 获取结果集中的列数(列的个数和下面)

echo "数据表中有{$rows}行,{$cols}列";

$result->close(); // 关闭结果集
$mysqli->close();


2、处理字段信息

fetch_field() 获取当前列信息

1. 每次获取完一列,然后指针往下走一次

2. 返回来的是一个对象,通过这个对象我们能获取

属性名
name列名
orgname列的原名,因为表和列都可以起别名
table表名
orgtable原表名,因为表和列都可以起别名
max_length最大长度,字段值的最大列的长度 
length长度
charsetnr字符集
flags
type类型
decimals


name 属性获取列的名称,

max_length 属性列最大长度 

$mysqli = new mysqli("localhost", "root", "", "shopdb", "3306");

$result = $mysqli->query("select id cid, name shopname, price, num, detail from products"); // 给列起别名

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对象,在对象里name和max_length获取列的名称和列长度
}
echo '</tr>';

while($rows = $result->fetch_assoc()){
  echo '<tr>';
  foreach($rows as $col){
    echo "<td>{$col}</td>";
  }
  echo '</tr>';
}
echo '</table>';

$mysqli->close();


上面的 data_seek() 方法可以移动记录的指针,

field_seek() 方法可以移动字段的指针,field_seek(2) 从第二个字段开始取


fetch_fields() 方法

1. 一次性把所有列全取过来了,然后形成一个数组

2. 数组里面每一个成员,就是每一个列的对象

$mysqli = new mysqli("localhost", "root", "", "shopdb", "3306");

$sql = "select id cid, name shopname, price, num, detail from products"; // 给列起别名

$result = $mysqli->query($sql);

echo '<table border="1" align="center" width="900">';

echo '<tr>';
$fields = $result->fetch_fields(); // 一次性把列全取出来
foreach($fields as $col){
  echo "<th>{$col->name}[{$col->max_length}]</th>";
}
echo '</tr>';

while($rows = $result->fetch_assoc()){
  echo '<tr>';
  foreach($rows as $col){
    echo "<td>{$col}</td>";
  }
  echo '</tr>';
}

echo '</table>';

$mysqli->close();


lengths  结果集对象属性,跟之前 max_length 属性获取列的最大长度一样,只过不返回的是单个的每一个列长度

$mysqli = new mysqli("localhost", "root", "", "shopdb", "3306");

$sql = "select * from products";

$result = $mysqli->query($sql);

echo '<table border="1" align="center" width="900">';
while($rows = $result->fetch_assoc()){
  echo "<tr>
    <td>{$rows['id']}    [{$result->lengths[0]}]</td>
    <td>{$rows['name']}  [{$result->lengths[1]}]</td>
    <td>{$rows['price']} [{$result->lengths[2]}]</td>
    <td>{$rows['num']}   [{$result->lengths[3]}]</td>
    <td>{$rows['detail']}[{$result->lengths[4]}]</td>
  </tr>";
}
echo '</table>';

$mysqli->close();


current_field 是结果集 $result 对象里面属性(不是 $fieild 里面的属性),获取当前列的列号

$mysqli = new mysqli("localhost", "root", "", "shopdb", "3306");

$sql = "select * from products";

$result = $mysqli->query($sql);

echo '<table border="1" align="center" width="900">';
echo '<tr>';

while($field = $result->fetch_field()){
  // current_field属性是结果集$result里面的属性,作用是返回当前列的列号
  echo "<th>{$result->current_field}_{$field->name} [{$field->max_length}]</th>"; 
}
echo '</tr>';

while($rows = $result->fetch_assoc()){
  echo '<tr>';
  foreach($rows as $col){
    echo "<td>{$col}</td>";
  }
  echo '</tr>';
}

echo '</table>';

$mysqli->close();


怎么获取 主键 和 唯一索引?

 desc products  查看表结构的 sql 语句

可以看到那个是主键,

那个是唯一索引,

那个字段是否为空,


所以获取表的详细信息,借助于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();


总结,

获取结果集中列和行的信息

field_count

current_field

lengths

field_seek()

fetch_field()

fetch_fields()




Leave a comment 0 Comments.

Leave a Reply

换一张