风之旅人 Android Dev Engineer

11.PHP中MySQL扩展

2019-10-21
PHP

Mysql扩展(基于PHP7)

PHP 针对 MySQL 数据库操作提供的扩展:允许PHP当做MySQL的一个客户端连接服务器进行操作。

PDO或mysqli都可以连接mysql,但更推荐使用PDO连接数据库,因为PDO支持12种不同的数据库驱动程序,mysqli只支持mysql,而且PDO性能更高

;php.ini中的 MySQL 扩展
extension=mysqli

🌈PHP7对比PHP5的MySQL操作上改动很大,但是仍旧有迹可循、有规律:🌰

PHP5:
mysql_query('use examples');
PHP7:
mysqli_query($conn,'use examples');

可见,7中在 mysql命令后面多了个'i',并且传参的时候都要传入 $conn 连接对象 , 另外对于
mysqli_num_rows($res) 等增删改查以下的方法,只是把 mysql 改成 mysqli 即可

🌈MySQL8.0和PHP7.13 兼容性问题

官方人员解释👉https://mysqlserverteam.com/upgrading-to-mysql-8-0-default-authentication-plugin-considerations/
caching_sha2_password 问题 👉 https://blog.csdn.net/maoxinwen1/article/details/88629313
授权问题https://www.2ita.com/thread-27166-1-1.html

//连接阿里云CentOS中Docker内的MySQL8.0
$conn2=mysqli_connect('116.62.155.140:3306','root','ma1bao2') or die("连接失败 ".mysqli_connect_error());
🍎
Warning:  mysqli_connect(): The server requested authentication method unknown to the client [caching_sha2_password] in C:\fastwork\Apache24\htdocs\init-mysql.php on line 14

解决流程:

  1. 配置 mysql.cnf 配置默认身份验证插件
[mysqld]
default_authentication_plugin = mysql_native_password
  1. SELECT Host, User, plugin from user;
mysql> SELECT Host, User, plugin from user;
+-----------+------------------+-----------------------+
| Host      | User             | plugin                |
+-----------+------------------+-----------------------+
| %         | root             | caching_sha2_password |
| localhost | mysql.infoschema | caching_sha2_password |
| localhost | mysql.session    | caching_sha2_password |
| localhost | mysql.sys        | caching_sha2_password |
| localhost | root             | mysql_native_password |
+-----------+------------------+-----------------------+

还得改 % , % 表示外部用户连接

ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '123456';
FLUSH PRIVILEGES;

😭终于成功了…🍎

数据插入成功!阿里云数据插入成功!
61
1

🌴 连接服务器中Docker内的MySQL 连接服务器中Docker内的MySQL

连库基本操作

1.连接数据库服务器

资源 mysql_connect(服务器地址,用户名,密码)

php7改用 mysqli_connect 连接数据库;若仍旧使用 mysql_connect 则报错:

Fatal error:  Uncaught Error: Call to undefined function mysql_connect() in C:\fastwork\Apache24\htdocs\test.php:7
Stack trace:
#0 {main}
  thrown in C:\fastwork\Apache24\htdocs\test.php on line 7

PHP连接方式:

  1. 面向过程方式
header('Content-type:text/html;charset=utf-8');
echo '<pre>';

//主机地址:默认端口3306
$servername = "localhost";
$username = "root";
$password = "123456";

// 创建连接
$conn = mysqli_connect($servername, $username, $password);
//或者采用短路运算方式(https://segmentfault.com/a/1190000002949450) 👇
//$conn=mysqli_connect('127.0.0.1:3306','roo2t','123456') or die("连接失败 ".mysqli_connect_error());

// 检测连接
if (!$conn) { //👉也可以 if (mysqli_connect_error())
    die("连接失败: " ); mysqli_connect_error());
}

var_dump($conn);
//关闭连接
mysqli_close($conn);
🍎
object(mysqli)#1 (19) {
  ["affected_rows"]=>
  int(0)
  ["client_info"]=>
  string(79) "mysqlnd 5.0.12-dev - 20150407 - $Id: 7cc7cc96e675f6d72e5cf0f267f48e167c2abb23 $"
  ["client_version"]=>
  int(50012)
  ["connect_errno"]=>
  int(0)
  ["connect_error"]=>
  NULL
  ["errno"]=>
  int(0)
  ["error"]=>
  string(0) ""
  ["error_list"]=>
  array(0) {
  }
  ["field_count"]=>
  int(0)
  ["host_info"]=>
  string(20) "localhost via TCP/IP"
  ["info"]=>
  NULL
  ["insert_id"]=>
  int(0)
  ["server_info"]=>
  string(6) "8.0.17"
  ["server_version"]=>
  int(80017)
  ["stat"]=>
  string(135) "Uptime: 3074  Threads: 2  Questions: 120  Slow queries: 0  Opens: 306  Flush tables: 3  Open tables: 226  Queries per second avg: 0.039"
  ["sqlstate"]=>
  string(5) "00000"
  ["protocol_version"]=>
  int(10)
  ["thread_id"]=>
  int(48)
  ["warning_count"]=>
  int(0)
}

连接资源默认也是超全局的,任何地方都可以使用该资源进行数据库的其他操作

  1. 使用 PDO 连接 MySQL
try {
    $conn = new PDO("mysql:host=$servername;", $username, $password);
    echo "连接成功";
}
catch(PDOException $e)
{
    echo "连接失败 ".$e->getMessage();
}
//关闭连接
$conn = null;
🍎失败情况
连接失败 SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client
  1. 实际开发中 :
    • 推荐使用 PDO连接方式 , 因为可以连接更多的数据库
    • 使用函数 parse_ini_file() 解析配置文件 config.ini 来获得数据库连接参数 , 如下所示:
//解析config.ini文件
$config = parse_ini_file(realpath(dirname(__FILE__) . '/config/config.ini'));
//对mysqli类进行实例化
$conn = new mysqli($config['host'], $config['username'], $config['password'], $config['dbname']);

补充: mysql_connect 默认是对一个服务器只连接一次(如果再次运行,返回的是同一个资源),但是如果有需要连接同一个资源两次,那么可以使用第四个参数:TRUE

2.设置连接编码

保持客户端与服务器之间的沟通顺畅:同一“语言”(字符集)

//php7
mysqli_query($conn, "set character set 'utf8'");//读库
mysqli_query($conn,"set names 'utf8'");//写库
//php5
mysql_query("set character set 'utf8'");//读库
mysql_query("set names 'utf8'");//写库
🌰
//设定字符集
$res = mysqli_query($conn,"set names 'utf8'");//写库
//或者 $res = mysqli_set_charset($conn,'utf8');
var_dump($res);
🍎
bool(true)

怎么确定要使用何种编码 客户端当前执行脚本的界面是什么字符集,就设定成什么字符集

3.选定要使用的数据库
$res = mysqli_query($conn,'use examples');
//或者 $res = mysqli_select_db($conn,'examples');
var_dump($res);
🍎
bool(true)//表示连接数据库成功
4.关闭连接
$res = mysqli_close($conn);
var_dump($res);

执行增删改操作

  1. 环境准备:
create database News charset utf8;

create table n_news(
id int primary key auto_increment,
title varchar(50) not null comment '新闻标题',
isTop tinyint not null comment '是否置顶',
content text comment '内容',
publiser varchar(20) not null comment '发布人',
pub_time int not null comment '发布时间'
)charset utf8;
  1. 做个专门负责数据库初始化的脚本:之后要操作数据库包含该脚本即可
header('Content-type:text/html;charset=utf-8');
echo '<pre>';

//连接认证
$conn=mysqli_connect('127.0.0.1:3306','root','123456') or die("连接失败 ".mysqli_connect_error());
//设定字符集
mysqli_query($conn,'set names utf8');
//选择数据库
mysqli_query($conn,'use News');
insert 插入
//引入初始文件
include_once 'init-mysql.php';

//组织SQL指令
$pub_time = time();
$sql = "insert into n_news values(null,'11.PHP的MySQL扩展',1,'MySQL扩展......','Javakam',{$pub_time})";

//执行SQL指令
if(mysqli_query($conn,$sql)){
  //操作成功:通常是返回自增长ID给用户
  echo '数据插入成功!';
}else{
  //操作失败
  echo '数据插入失败!'.mysqli_error($conn);;
}
delete 删除
//组织SQL指令:实际删除时通常也是根据ID进行删除,但是ID都是传递过来
$sql = "delete from n_news where id = 5";
update 修改
//组织SQL指令:实际更新时通常也是根据ID进行更新,但是ID都是传递过来
$sql = "update n_news set content = '好嗨友' where id = 20";
判断执行结果
  1. 执行成功,结果为true,只代表SQL指令执行成功
  2. 执行失败,结果为false,代表SQL指令错误或者操作对象不存在
select 查询
  1. mysql_query("select ...")
  2. 其他类似查询语句,比如:show语句,desc语句

以上两种情况的总结:凡是执行操作希望拿到数据库返回的数据进行展示的(结果返回:数据结果)

  1. 执行结果的处理:成功为结果集,失败为false

成功返回结果:SQL指令没有错误,但是如果查询结果本身为空返回也是true(结果集是一种资源:转换成bool永远为TRUE)

include_once 'init-mysql.php';

//组织SQL指令
$sql = "select * from n_news";

$res=mysqli_query($conn,$sql);
var_dump($res);
🍎
object(mysqli_result)#2 (5) {
  ["current_field"]=>
  int(0)
  ["field_count"]=>
  int(6)
  ["lengths"]=>
  NULL
  ["num_rows"]=>
  int(18)
  ["type"]=>
  int(0)
}
获取结果集行数

mysqli_num_rows('查询结果集合'):获取结果集中到底有多少行记录

include_once 'init-mysql.php';
//组织SQL指令
$sql = "select * from n_news";
$res=mysqli_query($conn,$sql);
//获取结果集数据条数:多少行记录
$rows = mysqli_num_rows($res);
echo $rows;
🍎
18
解析结果集

将一种结果集资源(PHP不能直接使用),转换成一种PHP能够解析的数据格式:通过从结果集中(结果集指针:类似数组指针),按照结果集指针所在位置取出对应的一条记录(一行),返回一个数组,同时指针下移…直到指针移出结果集。

  1. mysqli_fetch_assoc(): 获取关联数组,表的表单名字作为数组下标,元素值作为数组元素值
//解析结果集
$row = mysqli_fetch_assoc($res);
echo '<pre>';
print_r($row);
🍎
Array
(
    [id] => 4
    [title] => 11.PHP的MySQL扩展
    [isTop] => 1
    [content] => MySQL扩展......
    [publiser] => Javakam
    [pub_time] => 1571639075
)
  1. mysql_fetch_row(): 获取索引数组,只获取数据的值,然后数组的下标从0开始自动索
$row = mysqli_fetch_row($res);
🍎
Array
(
    [0] => 4
    [1] => 学校学习L扩展111
    [2] => 1
    [3] => MySQL扩展......
    [4] => Javakam
    [5] => 1571639075
)
  1. mysql_fetch_array():获取关联或者索引数组,但是默认是同时存在:一个记录取两次,形成一组是关联数组,一组是索引数组;
    但是可以通过第二个参数来决定获取的方式:MYSQL_ASSOC只获取关联数组;MYSQL_NUM只获取索引数组;MYSQL_BOTH获取全部两种。
//MYSQL_FETCH_ARRAY
$row = mysqli_fetch_array($res);
print_r($row);

//获取两种
$row = mysqli_fetch_array($res,MYSQLI_BOTH);
print_r($row);

//获取关联
$row = mysqli_fetch_array($res,MYSQLI_ASSOC);
print_r($row);

//获取索引
$row = mysqli_fetch_array($res,MYSQLI_NUM);
print_r($row);
echo '<pre>';
print_r($row);
🍎
Array
(
    [0] => 4
    [id] => 4
    [1] => 学校学习L扩展111
    [title] => 学校学习L扩展111
    [2] => 1
    [isTop] => 1
    [3] => MySQL扩展......
    [content] => MySQL扩展......
    [4] => Javakam
    [publiser] => Javakam
    [5] => 1571639075
    [pub_time] => 1571639075
)
Array
(
    [0] => 6
    [id] => 6
    [1] => 2312321的MySQL扩展
    [title] => 2312321的MySQL扩展
    [2] => 1
    [isTop] => 1
    [3] => MySQL扩展......
    [content] => MySQL扩展......
    [4] => Javakam
    [publiser] => Javakam
    [5] => 1571639079
    [pub_time] => 1571639079
)
Array
(
    [id] => 7
    [title] => 11.PHP的MySQL扩展
    [isTop] => 1
    [content] => MySQL扩展......
    [publiser] => Javakam
    [pub_time] => 1571639496
)
Array
(
    [0] => 8
    [1] => 打撒撒多`的MySQL扩展
    [2] => 1
    [3] => MySQL扩展......
    [4] => Javakam
    [5] => 1571639497
)
Array
(
    [0] => 8
    [1] => 打撒撒多`的MySQL扩展
    [2] => 1
    [3] => MySQL扩展......
    [4] => Javakam
    [5] => 1571639497
)

1.2.3 三种方式,都会使指针下移,mysqli_fetch_array 的结果所示。

通常结果集的操作:一般是获取里面的所有(全部记录)

其他相关函数

有字段信息
  1. mysqli_num_fields():获取一个指定结果集中所有的字段数
//查询当前结果集中所有的字段数量 👉 table有几个字段
echo mysqli_num_fields($res);
🍎
6
  1. mysqli_fetch_field_direct():获取一个指定结果集中指定位置字段的名字 php7中已废弃 mysqli_field_name() 👉 https://dev.mysql.com/doc/apis-php/en/apis-php-function.mysql-field-name.html
//查询当前结果集中所有的字段数量 , 默认从索引0开始
print_r(mysqli_fetch_field_direct($res,1));
🍎
stdClass Object
(
    [name] => title
    [orgname] => title
    [table] => n_news
    [orgtable] => n_news
    [def] =>
    [db] => news
    [catalog] => def
    [max_length] => 27
    [length] => 150
    [charsetnr] => 33
    [flags] => 4097
    [type] => 253
    [decimals] => 0
)
有关出错信息
  1. mysqli_error(‘数据库连接对象 $conn’):获取出错对应的提示信息
  2. mysqli_errno(‘数据库连接对象 $conn’):获取出错对应的错误提示代号
//错误判定
if(!$res){
  //代表结果为false
  echo 'SQL指令执行出错,错误编号为:' . mysqli_errno($conn) . '<br/>';
  echo 'SQL指令执行出错,错误信息是:' . mysqli_error($conn) . '<br/>';
  //终止代码执行
  exit();
}

🍎

SQL指令执行出错,错误编号为:1064
SQL指令执行出错,错误信息是:You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'from2 n_news' at line 1
其他函数

mysql_insert_id($conn) : 获取上次插入操作所产生的自增长ID,如果没有自增长ID返回0

//引入初始文件
include_once 'init-mysql.php';

//组织SQL指令
$pub_time = time();
$sql = "insert into n_news values(null,'11.PHP的MySQL扩展',1,'MySQL扩展......','Javakam',{$pub_time})";

//执行SQL指令
$res=mysqli_query($conn,$sql);
if($res){
  //操作成功:通常是返回自增长ID给用户
  echo '数据插入成功!';
}else{

  //代表结果为false
  echo 'SQL指令执行出错,错误编号为:' . mysqli_errno($conn) . '<br/>';
  echo 'SQL指令执行出错,错误信息是:' . mysqli_error($conn) . '<br/>';
  //终止代码执行
  exit();
}

//获取自增长ID
echo mysqli_insert_id($conn);
🍎 每刷新一次浏览器,自增1
数据插入成功!31


相关文章

评论