php 关于mysqli 扩展以及PDO的扩展

一、mysqli类的操作与使用

1、创建一张mysql的新表以供测试使用

CREATE TABLE IF NOT EXISTS `user`(
    id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT "用户ID",
    name VARCHAR(30) NOT NULL DEFAULT '' COMMENT "用户名",
    password CHAR(30) NOT NULL COMMENT "密码",
    email VARCHAR(100) NOT NULL UNIQUE DEFAULT '' COMMENT "邮箱",
    birthday DATE NOT NULL DEFAULT '2000-1-1' COMMENT "出生日期",
    age TINYINT UNSIGNED NOT NULL COMMENT "年龄"
)CHARSET=utf8 ENGINE=INNODB;

 2、利用mysqli建立连接

new Mysqli(主机名,用户名,密码,数据库名,端口号)

$config = [
    'host' => 'localhost',
    'user' => 'root',
    'password' => 'phpcj',
    'dbname' => 'learn',
    'port' => 3306
];
$mysqli =  new Mysqli($config['host'], $config['user'], $config['password'],$config['dbname'], $config['port']);
//如果没有错误则返回0如果有错误,那么返回对应的错误编号
if($mysqli->connect_errno) {
    die('连接错误,错误信息是'.$mysqli->connect_error);
}
//设置字符集
$mysqli->set_charset('utf8');

//执行查询操作,如果要查看执行的错误那么可以用Mysqli->error
$res = $mysqli->query('SELECT * FROM `user`');
//把mysql对象转成结果并还条打印
while($row = $res->fetch_assoc()) {
    var_dump($row);
}
//释放结果集
$res->free();
//关闭数据库
$mysqli->close();

 3、mysqli 的使用细节说明

mysqli_result::fetch_assoc => 返回的是一个关联数组(推荐使用)

mysqli_result::fetch_array => 返回的是一个关联数组以及索引数组

mysqli_result::fetch_row => 返回的是一个索引数组

mysqli_result::fetch_object => 返回的是一个对象

mysqli_result::data_seek(0) => 重置Mysql查询的指针为0;

用法如以2点的例子一样

如果想获取自增长的ID用mysqli->insert_id即可以

 4、mysql 查询的预处理

<?php
header('content-type:text/html;charset=utf8');

$config = [
    'host' => 'localhost',
    'user' => 'root',
    'password' => 'phpcj',
    'dbname' => 'learn',
    'port' => 3306
];
$mysqli =  new Mysqli($config['host'], $config['user'], $config['password'],$config['dbname'], $config['port']);
//如果没有错误则返回0如果有错误,那么返回对应的错误编号
if($mysqli->connect_errno) {
    die('连接错误,错误信息是'.$mysqli->connect_error);
}
//设置字符集
$mysqli->set_charset('utf8');

$sql = 'SELECT `id`, `name`, `age` FROM `user` WHERE `age`>?';
//进行预处理
$res = $mysqli->prepare($sql);
//假定id的值为20;
$id = 20;
//进行值的绑定
$res->bind_param('i', $id);
//进行结果绑定
$res->bind_result($myId, $myName, $myAge);
//预处理执行
if($res->execute()) {
    while($res->fetch()) {
        echo $myId,$myName,$myAge;
        //输出2bbb21
    }
}
$res->free_result();
$res->close();
$mysqli->close();
?>

 5、mysqli的批量查询操作

<?php
header('content-type:text/html;charset=utf8');
ini_set('display_errors', true);
$config = [
    'host' => 'localhost',
    'user' => 'root',
    'password' => 'phpcj',
    'dbname' => 'learn',
    'port' => 3306
];
$mysqli = new mysqli($config['host'], $config['user'], $config['password'], $config['dbname'], $config['port']);
if($mysqli->connect_errno) {
    die('连接错误'.$mysqli->connect_error);
}
$mysqli->set_charset('utf8');
$sql = sprintf('%s;%s;%s','SELECT * FROM `student`', 'SELECT * FROM `class`', 'SELECT * FROM `department`');
if($mysqli->multi_query($sql)) {
    do{
        $res = $mysqli->store_result();
        while($row = $res->fetch_assoc()) {
            var_dump($row);
        }
        $res->free();
        //判断是否还有更多的结果集,如果有返回true,如果没有则返回false;
        if(!$mysqli->more_results()) {
            break;
        }
        //把指针指向下一个结果集
    }while($mysqli->next_result());
} else {
    echo '执行失败,错误码是'.$mysqli->error;
}
?>

 注意:mysqli进行批量操作的时候,查询与增删改要分开操作,否则容易发生错误

 6、mysqli的增删改操作

<?php
header('content-type:text/html;charset=utf8');
ini_set('display_errors', true);
$config = [
    'host' => 'localhost',
    'user' => 'root',
    'password' => 'phpcj',
    'dbname' => 'learn',
    'port' => 3306
];
$mysqli =  new Mysqli($config['host'], $config['user'], $config['password'],$config['dbname'], $config['port']);
//如果没有错误则返回0如果有错误,那么返回对应的错误编号
if($mysqli->connect_errno) {
    die('连接错误,错误信息是'.$mysqli->connect_error);
}
//设置字符集
$mysqli->set_charset('utf8');

//$sql = 'INSERT INTO `student` (`name`, `age`, `classid`) VALUES ("test", 30, 1)';
$sql = 'UPDATE `student` SET `age`= 18, `name` = "ok" WHERE `studentid` = 26';
//$sql = 'DELETE FROM `student` WHERE `studentid` = 25';
$res = $mysqli->query($sql);
if(!$res) {
    printf('执行错误,错误代码是%s,SQL语句是%s',$mysqli->error, $sql);
    exit;
}
//输出影响的结果集,如果数据库中的数值没有变化,那么就会输出0
var_dump($mysqli->affected_rows);
echo '执行成功';
?>

注意:$mysqli->affected_rows的值为0并不代表着执行失败,而是对数据库没有影响,如果想获取最新添加的自增长的ID,那么用$mysqli->insert_id来获取

 7、mysqli的批量增删改操作

<?php
header('content-type:text/html;charset=utf8');
ini_set('display_errors', true);
$config = [
    'host' => 'localhost',
    'user' => 'root',
    'password' => 'phpcj',
    'dbname' => 'learn',
    'port' => 3306
];
$mysqli = new mysqli($config['host'], $config['user'], $config['password'], $config['dbname'], $config['port']);
if($mysqli->connect_errno) {
    die('连接错误'.$mysqli->connect_error);
}
$mysqli->set_charset('utf8');
$sql1 = 'UPDATE `student` SET `name` = "张飞" WHERE `studentid` = 13';
$sql2 = 'INSERT INTO `student` (`name`, `age`, `classid`) VALUES ("关羽", 19, 1)';
$sql3 = 'UPDATE `student` SET `age` = 20 WHERE `name` = "关羽"';
$sql = sprintf('%s;%s;%s',$sql1, $sql2, $sql3);
if($mysqli->multi_query($sql)) {
    echo '执行成功';
} else {
    echo '执行失败,错误码是'.$mysqli->error;
}
?>

 8、mysqli 增删改预处理

<?php
header('content-type:text/html;charset=utf8');
ini_set('display_errors', true);
$config = [
    'host' => 'localhost',
    'user' => 'root',
    'password' => 'phpcj',
    'dbname' => 'learn',
    'port' => 3306
];
$mysqli = new mysqli($config['host'], $config['user'], $config['password'], $config['dbname'], $config['port']);
if($mysqli->connect_errno) {
    die('连接错误'.$mysqli->connect_error);
}
$mysqli->set_charset('utf8');
//3. 编写添加用户的语句 ?占位符号
$sql = "INSERT INTO `student` (`name`, `age`, `classid`) VALUES(?, ?, ?)";
//$sql = "UPDATE `student` SET `name` = ? WHERE studentid = ? ";
//4.代表一个prepared语句
$pre_sql = $mysqli->prepare($sql);

//5.给$pre_sql绑定参数
$name = "test";
$age = 40;
$classid = 3;
/*
    功能: 给预处理语句的? 绑定参数
    @param isd : 表示i=>int s=>string d=>double 小数
    @param $id, $name, $money 传入值
*/
$pre_sql->bind_param('sii', $name, $age,  $classid);
if($pre_sql->execute()){
    echo '<br> 执行成功!';
}else{
    echo '<br> 执行失败' . $mysqli->error;
}
?>

 注意:如果要再次用到预处理来添加数据,那么只需要绑定值就可以了即以上第5点以下再写一次便可

 9、mysqli的事务处理

<?php
header('content-type:text/html;charset=utf-8');
// mysqli的事务控制


//连接数据库...
//演示使用mysqli完成dml
$mySQLi = new MySQLi('localhost', 'root', '123', 'itbull', 3306);

//判断是否连接成功
//Returns the error code from last connect call
//如果没有错误,返回0,如果有错误,返回对应错误号
if($mySQLi->connect_errno){
    
    //connect_error 属性表示错误信息
    die('连接错误,错误信息是' . $mySQLi->connect_error);
}else{
    echo '<br> 连接ok!';
}

//2.设置字符集
$mySQLi->set_charset('utf8'); 

//3. 编写sql
$sql1 = "UPDATE `account` SET money = money - 1 WHERE id = 100";
$sql2 = "UPDAT `account` SET money = money + 1 WHERE id = 200";

//4. 开始事务
$mySQLi->begin_transaction();

$res1 = $mySQLi->query($sql1);
$res2 = $mySQLi->query($sql2);

if($res1 && $res2){
    
    echo '<br> sql语句执行成功, 正式提交';
    $mySQLi->commit();

}else{
    echo '<br> sql语句有执行失败的, 回滚';
    $mySQLi->rollback();
}

 二、PDO类的操作与使用

1、pdo扩展提供了三个类,分别是:PDO、PDOStatement、PDOException

PDO类连接数据库,并对数据库进行增删改查操作

封装个单例模式

<?php
ini_set('display_errors', true);
ERROR_REPORTING(E_ALL);
final class DB {
    private static $db;
    private function __clone() {}
    private function __construct() {
        $config = parse_ini_file('./db.ini');
        $dsn = sprintf('mysql:host=%s;dbname=%s;port=%d;charset=%s', $config['host'], $config['dbname'], $config['port'], $config['charset']);
        try{
            self::$db = new PDO($dsn, $config['user'], $config['password']);
        }catch(PDOException $e) {
            exit($e->getMessage());
        }
    }
    public static function getInstance(): PDO {
        if(!self::$db instanceof PDO) {
            new self();
        }
        return self::$db;
    }
}
?>

2、PDO返回的结果集分为两种情况:第一种是增删改,是通过PDO对象exec来实现的,返回的是受影响的记录数, 第二种是查询,通过PDO对象的query来实现的,返回的是查询的结果集

3、PDO连接后针对以上的$pdo对象的属性解析

errorcode() : 表示错误的code

errorinfo(): 表示错误的信息,返回的是一个数组,第一项是errorcode(), 第三项的错误具体信息

quote(): 对引号进行转义以防止SQL注入

query(): 表示执行查询语句, 当执行成功返回的是PDOStatement对象,如果执行失败,那么返回的是布尔值false

query 成功后返回PDOStatement对象里面关乎查询的方法有:

PDOStatement::fetch() 查询一条记录        

PDOStatement::fetchAll() 查询所有的记录

注:以上两个方法接收一个参数,通常使用PDO::FETCH_ASSOC返回关联数组,PDO::FETCH_BOTH 返回关联和索引数组 ,PDO::FETCH_NUM返回索引数组

<?php
//在单例模式的基础上
$db = DB::getInstance();
//查询数据用query
$querySql = sprintf('SELECT * FROM `user` WHERE `id` > %d', 0);
$res = $db->query($querySql);
var_dump($res->fetch(PDO::FETCH_ASSOC));
//输出一个结果集
echo '<hr/>';
var_dump($res->fetchAll(PDO::FETCH_ASSOC));
//输出全部的结果集
?>

PDOStatement::fetchColumn() 接收一个数字型的参数,当有多条记录时可不断输出指定列的数据,当没有数据时返回bool(false);

<?php
//在单例模式的基础上
$db = DB::getInstance();
//查询数据用query
$querySql = sprintf('SELECT * FROM `user` WHERE `id` > %d', 0);
$res = $db->query($querySql);
//输出结果集的所有查询结果
var_dump($res->fetchColumn(1)); //输出 “admin”
var_dump($res->fetchColumn(1)); //输出 “aaa”
var_dump($res->fetchColumn(1)); //输出 “bbb”
var_dump($res->fetchColumn(1)); //输出 “ccc”
var_dump($res->fetchColumn(1)); //输出 bool(false)
?>

exec(): 表示执行增删改语句,返回的是受影响的记录数

<?php
//前提在上面单例模式的前提下进行调用
$db = DB::getInstance();
//插入数据用exec;
//利用quote对引号进行转义有利于防止sql注入
$insertSql = sprintf('INSERT INTO `user` (`user`, `pwd`) VALUE (%s, %1$.s), (%2$.s,%2$.s)', $db->quote('aaa'), $db->quote('bbb'));
$res = $db->exec($insertSql);
var_dump($res);
//输出 int(2); 如果执行错误,那么返回bool(false)

$updateSql = sprintf('UPDATE `user` SET `user` = %1$.s, `pwd` = %1$.s WHERE `user` = %2$.s', $db->quote('ccc'), $db->quote('aaa'));
$res = $db->exec($updateSql);
//输出 int(1); 如果执行错误,那么返回bool(false);
?>

prepare($sql): 表示pdo的预处理机制

A、利用预处理执行增删改语句,下面以更新为例

PDOStatement::bindValue 表示为预处理语句绑定一个值

PDOStatement::execute() 表示执行预处理语句

PDOStatement::rowCount() 表示返回受影响的记录数

<?php
//在单例模式的基础上
$db = DB::getInstance();
$sql = 'UPDATE `user` SET `user` = :user WHERE `id` = :id';
$res  = $db->prepare($sql);
$res->bindValue(':user', 'abc1', PDO::PARAM_STR);
$res->bindValue(':id', 6, PDO::PARAM_INT);
$res->execute();  //如果执行成功,那么返回true,否则返回false;
var_dump($res->rowCount()); //返回受影响的记录数
?>

B、预处理查询语句

<?php
//在单例模式的基础上
$db = DB::getInstance();
$state = $db->prepare('SELECT * FROM `user` WHERE id > :id');
$state->bindValue(':id', 2, PDO::PARAM_INT);
$state->execute();
$res = $state->fetchAll(PDO::FETCH_ASSOC);
var_dump($res);
//输出结果集
?>

PDOStatement::bindValue(':name', value, type)  type有分成PDO::PARAM_STR, PDO::PARAM_INT, PDO::PARAM_BOOL几种(常用)

PDOStatement::bindParam(':name', value, type)  type有分成PDO::PARAM_STR, PDO::PARAM_INT, PDO::PARAM_BOOL几种(常用)

bindValue 与 bindParam的区别:

1、bindParam是绑定一个参数到指定的变量名   bindValue则是把一个值绑定到一个参数

2、bindParam第二个参数有且只能是一个变量名, 不能是一个具体的值  bindValue既可以绑定一个变量名,又可以绑定一个值

3、不同于 PDOStatement::bindValue(),PDOStatement::bindParam()中的变量作为引用被绑定,并只在 PDOStatement::execute() 被调用的时候才取其值

<?php
//在单例模式的基础上
$db = DB::getInstance();
$user = 'first';
$pwd = 'second';
$state = $db->prepare('INSERT INTO `user` (`user`, `pwd`) VALUES (:name, :pwd)');
//如果执行下面两条语句,那么存入数据库的是 first 与 second
$state->bindValue(':name', $user, PDO::PARAM_STR);
$state->bindValue(':pwd', $pwd, PDO::PARAM_STR);
//如果执行的是下面两条语句,那么存入数据库的是 haha, check
$state->bindParam(':name', $user, PDO::PARAM_STR);
$state->bindParam(':pwd', $pwd, PDO::PARAM_STR);
$user  = 'haha';
$pwd = 'check';
$state->execute();  //返回的是bool(true)
$res = $state->rowCount();
var_dump($res);
//输出结果集 int(1)
?>

PDOStatement::closeCursor():用于在查询数据后关闭游标和指针的(即初始化,便于下次查询)

PDOStatement::errorCode(), PDOStatement::errorInfo(): 区别于pdo对象里的方法,在statement里面主要获取预编译时的错误信息和错误码(执行之后才能获得错误信息)

lastInsertId(): 返回最新插入的记录自增长ID

<?php
//在单例模式的基础上
$db = DB::getInstance();
$statement = $db->prepare('INSERT INTO `user` (`user`, `pwd`) VALUES (:name, :pwd)');
$statement->bindValue(':name', 'ricky');
$statement->bindValue(':pwd', '123456');
$statement->execute();
var_dump($statement->rowCount());
//输出 int(1) 
var_dump($db->lastInsertId());
//输出 string(1) "5"
?>

beginTransaction(): 开启事务

commit(): 提交事务

rollBack(): 事务的回滚

<?php
//在单例模式的基础上
$db = DB::getInstance();
try {
    $sql = "UPDATE `user` SET `user`= :user WHERE `id`=:id";
    $db->beginTransaction();
    $exe1 = $db->prepare($sql);
    $exe2 = $db->prepare($sql);
    $exe1->bindValue(':user', 'this is first');
    $exe1->bindValue(':id', 4, PDO::PARAM_INT);
    $exe2->bindValue(':user', 'this is second');
    $exe2->bindValue(':id', 5, PDO::PARAM_INT);
    if($exe1->execute() && $exe2->execute()) {
        $db->commit();
    } else {
        $db->rollBack();
    }
}catch(PDOException $e) {
    $db->rollBack();
    exit($e->getMessage());
}
?>
原文地址:https://www.cnblogs.com/rickyctbu/p/10802563.html