【PHP与MySQL】快速入门详解以及自定义封装

一、Mysqli扩展

注意:使用Mysqli扩展之前,不要忘了启用。使用Wamp集成环境的可以界面操作启用,当然也可以去php.ini启用。

连接数据库

// 最后一个参数,一般不传
$link = new mysqli(主机名, 用户名, 密码, 数据库名, 端口号, socket);

// 连接错误判断
if ($link->connect_errno) { // 错误代码。连接成功返回0
    echo "连接失败" . $link->connect_error;  // 打印错误信息
    die();
} 

// 连接成功,不要忘了设置连接的字符集,否则可能会遇到乱码
$link->set_charset("utf8");

查询操作

1、逐行取出

// 从结果集中取数据
// 逐行取出,取出一行后,游标会指向下一行
// 返回一个索引数组。对应结果集的一条数据(一行)
$row = $result->fetch_row(); 
// 返回一个关联数组。数组索引与数据库表的字段名一样
$row = $result->fetch_assoc(); 

// 通过循环,取出结果集的所有数据
while (($row = $result->fetch_row()) != null) {
    // 取出字段
    $row[0]
    $row[1]
}
while (($row = $result->fetch_assoc()) != null) {
    // 取出字段
    $row['字段名1']
    $row['字段名2']
}

2、一次性取出

$rows = $result->fetch_all(返回数组的类型)
返回数组的类型:
    MYSQLI_NUM      // 以索引数组形式返回
    MYSQLI_ASSOC    // 以关联数组形式返回

foreach ($rows as $row) {
    // 取出字段
}

3、资源释放

// 释放结果集
$result->free();
// 释放数据库连接
$link->close();

4、特殊需求

// 结果集对象中的属性,而不是方法
$result->num_rows;

增、删、改操作

1、执行和操作判断

$sql = "..."; // 增、删、改的sql语句
// 增、删、改操作返回的是布尔类型
$bool = $link->query($sql);

// 除了通过这个布尔值判断是否成功外,还可以通过受影响的行数判断
if (($bool !== false) && ($link->affected_rows > 0)) {
    // 操作成功
}

2、特殊需求:如果是insert操作,需要最后插入的数据的【自增长id】(非自增长的不行)

// 在执行完insert语句之后,可通过下面代码获取自增长id
$link->insert_id; // 数据库连接对象的一个属性,而不是方法

3、关闭数据库连接,操作同上

预处理语句机制

1、假如我要插入多条数据,sql语句都差不多,就是每一条sql语句中的数据不一样(特点)。如果不使用预处理语句机制,而是逐条sql语句执行,效率比较低。针对这种情况,PHP向MySQL发送一个需要执行的sql模板,由于数据不同,sql语句中数据部分用占位符“?”表示,然后再单独发送数据。因此,可以向一个相同的准备语句发送大量的数据,大大提高了查询执行速度。

2、如果是增、删、改操作,使用预处理语句机制,可以防止sql注入。如果是查询操作,也可不必担心这种风险,因此可不必使用这种预处理机制。

1、插入多条数据 的完整使用流程

// 带有占位符的sql语句
$sql = " insert into user(id, username, password, age) 
        values(null, ?, ?, ?) ";

// 获取一个准备语句对象
$stmt = $link->prepare($sql);

// 绑定参数(将占位符跟变量绑定)
$username = null;
$password = null;
$age = null;
$stmt->bind_param("ssi", $username, $password, $age);
/*
 * 1、绑定的是变量的【引用】(引用传递)
 * 2、第一个参数表示变量类型:
 *      i:所有INTEGER类型
 *      d:DOUBLE和FLOAT类型
 *      b:BLOB类型
 *      s:所有其他类型,包括字符串
 *    字符串中的第i个字符,对应后面第i个变量的类型
 *    例如:"ssi"的第3个字符'i'表示,后面第三个变量$age是Integer类型  
 */

// 插入一条数据
// 由于$stmt绑定了变量的【引用】,所以只需为变量赋值,然后执行即可
$username = "小明";
$password = "123";
$age = 12;
$stmt->execute();

// 再插入一条
$username = "李华";
$password = "233";
$age = 13;
$stmt->execute();

// 关闭$stmt
$stmt->close();

2、查询 操作的完整流程示例

可以看出来,它是通过将结果集中的 每一行数据的各个字段绑定到各个变量上,然后通过$stmt->fetch(),移动结果集中的游标,并取出一行数据赋值到变量中。

个人觉得如果是查询操作,没必要这么干。用前面的操作更方便。

 

二、PDO扩展

PDO扩展类库为PHP访问数据库定义了一个轻量级的、一致性的接口,它提供了一个数据访问抽象层,这样,无论使用什么样的数据库,都可以通过一致的函数执行查询和获取数据。 大大简化了PHP对数据库的操作,并能够屏蔽不同数据库之间的差异。使用PDO可以很方便地进行跨数据库程序的开发,以及不同数据库间的移植。

说白了,总结几句话:

1、PDO类似Java中的JDBC,是PHP与各种数据库交互的接口层

2、Mysqli扩展只针对于PHP与MySQL数据库进行交互,而使用PDO可以跟各种数据库进行交互

此处,仍以PDO操作MySQL数据为例,介绍PDO。

注意,使用扩展前,记得启用!!!

插入多条数据完整实例

从下面代码,可以看出,插入一条数据也可以用下面代码实现

// 创建pdo对象
$dsn = "mysql:dbname=test;host=localhost";
$username = 'root';
$password = '123';
try {
    $pdo = new PDO($dsn, $username, $password);
} catch (PDOException $e) {
    echo '数据连接失败:' . $e->getMessage();
    exit();
}

// 获取准备语句对象
$sql = " insert into user(id, username, password, age)
 values(null, ?, ?, ?) ";
$stmt = $pdo->prepare($sql);

// 直接在execute中以数组形式传入参数值,代替占位符
// 注意,数组的值要与占位符一一对应
$stmt->execute(array('小明', '123', 12));
$stmt->execute(array('李华', '233', 13));

// 当然也可以像前面Mysqli里面的预处理机制一样
// 先绑定变量,再给变量赋值,再执行

查询操作示例

$sql = " select * from user where age=? ";
$stmt = $pdo->prepare($sql);

$bool = $stmt->execute(array(12)); // 为占位符赋值,然后执行
if ($bool === true) {
    // 12岁的user可能不只一个,故返回的数组是二维数组(可想象为一张表)
    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); // 以关联数组形式返回
}

PDO扩展的封装

可以看出来,PDO扩展的代码简单明了。参考教材,实现PDO的基本封装,简化以后我们数据库操作的代码量

<?php
/**
 * @author passerbyYSQ
 * @create 2020年4月17日 下午3:41:53
 */
require_once 'config/config.php';

class DbDao {
    // 注意这里有static。在构造函数里,确保$db单例
    protected static $db = null;
    
    public function __construct() {
        // 确保$db单例
        isset(self::$db) || self::connect();
    }
    
    private static function connect() {
        // 获取配置
        $config = require_once SA_PATH . '/config/db_config.php';
        $dsn = "{$config['type']}:host={$config['host']};port={$config['port']};
            dbname={$config['dbname']};charset={$config['charset']}";
        try {
            self::$db = new PDO($dsn, $config['user'], $config['pwd']);
        } catch (PDOException $e) {
            echo '连接错误!<br/>';
            echo '错误文件:'.$e->getFile().'<br/>';
            echo '错误行号:'.$e->getLine().'<br/>';
            echo '错误描述:'.$e->getMessage().'<br/>';
            die();
        }
    }
       
    public function query($sql, $parms, $batch = false, &$ids = null) {
        $data = $batch ? $parms : array($parms); 
        $stmt = self::$db->prepare($sql);
        foreach ($data as $v) {
            if ($stmt->execute($v) === false) {
                var_dump($stmt->errorInfo()); // 用于调试
                if ($ids !== null) {
                    $ids = null;
                }
                return null;
            } else {
                if ($ids !== null) {
                    $ids[] = self::$db->lastInsertId();
                }
            }
        }
        return $stmt;
    }
    
    /**
     * 插入多条数据
     * @param unknown $sql      带有占位符的sql语句
     * @param unknown $parms    参数值。由于是多条数据,故应传入一个二维数组(索引数组)
     * @param unknown $auto     是否是自增长Id。默认Id是自增长的。
     * @return array            如果全部插入成功,返回一个索引数组,每个元素对应插入的每条记录的自增长id
     *                          注意主键需要是自增长的id。若Id非自增长,返回受影响的行数
     */
    public function insertMul($sql, $parms, $auto = true) {
        if ($auto === true) {
            // id自增长的情况
            $lastIds = array();
            $this->query($sql, $parms, true, $lastIds);
            return $lastIds;
        } else {
            // id非自增长的情况
            $stmt = $this->query($sql, $parms, true);
            return $stmt->rowCount();
        }
    }
    
    /**
     * 插入一条数据
     * @param unknown $sql      带有占位符的sql语句
     * @param unknown $parms    参数值。应为一维数组(索引数组)
     * @return                  自增长id
     */
    public function insertOne($sql, $parms, $auto = true) {
        if ($auto === true) {
            // id自增长的情况
            $this->query($sql, $parms);
            return self::$db->lastInsertId();
        } else {
            // id非自增长的情况
            $this->query($sql, $parms);
        }        
    }
    
    // 查询全部数据
    public function selectAll($sql, $parms) {
        return $this->query($sql, $parms)->fetchAll(PDO::FETCH_ASSOC);
    }
    
    // 查询一条数据
    public function selectOne($sql, $parms) {
        return $this->query($sql, $parms)->fetch(PDO::FETCH_ASSOC);
    }
    
    // 修改或删除。返回受影响行数
    public function updateOrDelete($sql, $parms) {
        return $this->query($sql, $parms)->rowCount(); 
    }
    
    // 获取行数
    public function getCount($table, $where = '') {
        $sql = ' select count(*) from ' . $table . $where;
        $result = self::$db->query($sql);
        return $result->fetch()[0];
    }
    
}

?>

这是pdo基础操作的封装。使用时,将它作为基类来继承,扩展更复杂的业务操作

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值