美文网首页
php 封装PDO单例 2022-11-27

php 封装PDO单例 2022-11-27

作者: 阿然学编程 | 来源:发表于2022-11-26 13:30 被阅读0次
<?php

class Db
{
    // 默认数据库配置(常量数据库配置)
    const DSN = 'mysql:host=127.0.0.1;dbname=www_test_cn;charset=utf8';
    const USER = 'www_test_cn'; //账号
    const PASS = 'test';  //密码

    // 保存DB对象的静态属性值
    private static $obj = null;
    // 保存PDO数据库操作对象
    private $link = null;
    // 保存操作的数据表
    private $table = null;
    // 保存所有表内的字段
    private $fields;
    // 保存主键名称
    private $pk;
    // 保存要查询的字段
    private $keys;
    // 保存查询条件
    private $where;
    // 保存排序条件
    private $order;
    // 保存分页条件
    private $limit;
    // 保存分组条件
    private $group;
    // 保存分组再筛选条件
    private $having;

    /**
     * 数据库 初始化操作
     */
    private function __construct($table, $config)
    {
        // 连接数据库相关设置
        $this->connect($config);
        // 设置操作的数据表
        $this->setTable($table);
        // 得到表内所有的字段
        $this->getField();
    }

    /**
     * 设置操作的表名(静态方法)
     * @param string $table 操作的表名
     * @param array $config 数据库配置选项
     * @return object 返回连接好的PDO对象
     */
    public static function table($table, $config = [])
    {
        if (self::$obj === null) {
            // 实例化PDO对象
            self::$obj = new self($table, $config);
        }
        //返回PDO对象
        return self::$obj;
    }

    /**
     * 连接数据库相关设置
     * @param array $config 数据库配置选项
     */
    protected function connect($config = [])
    {
        // 如果配置项为空,则使用默认的常量配置
        if (empty($config)) {
            $config = [
                'dsn' => self::DSN,
                'user' => self::USER,
                'pass' => self::PASS
            ];
        }
        // 实例化PDO的对象
        try {
            $options = [
                \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
                \PDO::ATTR_EMULATE_PREPARES => false,
                \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC
            ];

            $this->link = new \PDO($config['dsn'], $config['user'], $config['pass'], $options);
        } catch (\PDOException $e) {
            throw new \Exception("数据库连接失败: " . $e->getMessage());
        }
    }

    /**
     * 设置操作的数据表
     * @param string $table 要操作的数据表
     */
    protected function setTable($table)
    {
        $this->table = $table;
    }


    /**
     * 查询多条数据
     * @return 二维数组/空数组
     */
    public function select()
    {
        $keys = '*'; // 默认查全部
        // 判断有无字段条件
        if (!empty($this->keys)) {
            $keys = $this->keys;
            $this->keys = null; // 每次清除查询条件
        }

        $where = ''; // 默认无where条件
        // 判断有无 where条件
        if (!empty($this->where)) {
            // 注意WHERE后面有空格,再拼接where条件
            $where = 'WHERE ' . $this->where;
            $this->where = null;// 每次用完清除条件
        }

        $order = '';
        // 判断有无order条件
        if (!empty($this->order)) {
            $order = 'ORDER BY ' . $this->order;
            $this->order = null;// 每次用完清除条件
        }

        $limit = '';
        // 判断有无limit条件
        if (!empty($this->limit)) {
            $limit = 'LIMIT ' . $this->limit;
            $this->limit = null;// 每次用完清除条件
        }

        $group = '';
        // 判断有无group条件
        if (!empty($this->group)) {
            $group = 'GROUP BY ' . $this->group;
            $this->group = null;// 每次用完清除条件
        }

        $having = '';
        // 判断有无having条件
        if (!empty($this->having)) {
            $having = 'HAVING ' . $this->having;
            $this->having = null;// 每次用完清除条件
        }

        // 查询的sql语句
        $sql = "SELECT {$keys} FROM {$this->table} {$where} {$group} {$having} {$order} {$limit}";

        try {
            // 执行查询
            $stmt = $this->link->query($sql);
            // 处理结果集
            $result = $stmt->fetchAll();
        } catch (\PDOException $e) {
            throw new \Exception("Query failed: " . $e->getMessage());
        }

        // 返回结果
        return $result;
    }


    /**
     * 查单条数据
     * @param str $findValue 指定查询的字段值
     * @param str $findKey 指定查询的字段条件
     * @return bool/array 返回一维数组或false
     */
    public function find($findKey = null, $findValue)
    {
        $keys = '*'; //默认查全部
        //判断有无字段条件
        if (!empty($this->keys)) {
            $keys = $this->keys;
            $this->keys = null; // 每次用完清除查询条件
        }

        // 无参2,则指定为主键
        if ($findKey === null) {
            $findKey = $this->pk; // 若无参数 `$findKey`,则默认使用主键作为查找条件
        }

        // SQL语句
        $sql = "SELECT {$keys} FROM {$this->table} WHERE {$findKey} = :findValue LIMIT 1";

        try {
            $stmt = $this->link->prepare($sql);
            $stmt->bindValue(':findValue', $findValue);
            $stmt->execute();

            $data = $stmt->fetch();
        } catch (PDOException $e) {
            throw new \Exception("Query failed: " . $e->getMessage());
        }

        return !empty($data) ? $data : false;
    }


    /**
     * 获取要查询的字段,对象链操作
     * @param arr $arr 以数组形式,指定要查询的字段
     * @param arr $func 以数组形式,指定SQL中统计函数
     * @return $this
     */
    public function field($arr, $func = [])
    {
        // 判断参数 是否是数组.如不是,直接返回自己
        if (!is_array($arr)) return $this;

        // 遍历$arr 删除非法字段(数据表里没有的字段)
        foreach ($arr as $key => $val) {
            if (!in_array($val, $this->fields)) {
                unset($arr[$key]);
            }
        }

        // 如果处理好的参数为空,则直接返回自己
        if (empty($arr)) return $this;

        // 生成字段条件,存为属性,方便其它方法使用
        $this->keys = implode(',', $arr);

        // 判断有无传递参2
        if (!empty($func) && is_array($func)) {
            $this->keys = $this->keys . ',' . implode(',', $func);
        }

        // 返回自己,用于对象链操作
        return $this;
    }


    /**
     * 获取要查询的条件,对象链操作
     * @param str $where 指定要查询的条件
     * @return $this
     */
    public function where($where)
    {
        // 设置要查询的条件
        $this->where = $where;
        // 返回自己,用于对象链操作
        return $this;
    }


    /**
     * 获取排序的条件,对象链操作
     * @param str $order 指定排序条件
     * @return $this
     */
    public function order($order)
    {
        // 设置排序条件
        $this->order = $order;
        // 返回自己,用于对象链操作
        return $this;
    }

    /**
     * 获取分页条件,对象链操作
     * @param str $order 指定分页条件
     * @return $this
     */
    public function limit($limit)
    {
        // 设置分页条件
        $this->limit = $limit;
        // 返回自己,用于对象链操作
        return $this;
    }

    /**
     * 获取分组条件,对象链操作
     * @param str $group 指定分组条件
     * @return $this
     */
    public function group($group)
    {
        // 设置分组条件
        $this->group = $group;
        // 返回自己,用于对象链操作
        return $this;
    }


    /**
     * 获取分组再筛选条件,对象链操作
     * @param str $having 指定分组筛选条件
     * @return $this
     */
    public function having($having)
    {
        // 判断有无分组条件,无则直接返回$this,不进行操作
        if (!isset($this->group)) return $this;
        // 设置分组条件
        $this->having = $having;
        // 返回自己,用于对象链操作
        return $this;
    }


    /**
     * 新增数据
     * @param array $data 要添加的数据
     * @return 新增成功返回ID/失败返回false
     */
    public function insert($data = [])
    {
        if (empty($data)) {
            $data = $_POST; // 默认使用 $_POST 数据
        }

        $list = [];
        foreach ($data as $k => $v) {
            if (in_array($k, $this->fields)) {
                $list[$k] = $v;
            }
        }

        $keys = implode(',', array_keys($list));
        $values = implode("','", array_values($list));

        $sql = "INSERT INTO {$this->table} ({$keys}) VALUES ('{$values}')";

        return $this->execute($sql);
    }

    /**
     * 删除数据
     * @param str $delValue 指定删除的字段值
     * @param str $delKey 指定删除的字段条件
     * @return bool 成功返回true/失败返回false
     */
    public function delete($delKey = null, $delValue)
    {
        if ($delKey === null) {
            $delKey = $this->pk; // 若无参数 `$delKey`,则默认使用主键进行删除操作
        }

        $sql = "DELETE FROM {$this->table} WHERE {$delKey} = :delValue";
        $stmt = $this->link->prepare($sql);
        $stmt->bindValue(':delValue', $delValue);

        return $stmt->execute();
    }

    /**
     * 更新数据
     * @param array $data 要更新的数据
     * @return bool 成功返回true/失败返回false
     */

    public function update($conditions = [], $data = [])
    {
        // 如果数据为空,则将POST数据赋值给$data变量
        if (empty($data)) {
            $data = $_POST;
        }

        // 筛选出有效字段的数据
        $list = [];
        foreach ($data as $k => $v) {
            if (in_array($k, $this->fields) && $k != $this->pk) {
                $list[] = "`{$k}`='{$v}'";
            }
        }

        // 生成SET条件
        $set = implode(',', $list);

        // 根据给定的条件生成WHERE条件
        $where = '';
        foreach ($conditions as $key => $value) {
            $where .= "`{$key}` = '{$value}' AND ";
        }
        $where = rtrim($where, ' AND ');

        // SQL查询语句
        $sql = "UPDATE {$this->table} SET {$set} WHERE {$where}";

        // 执行查询并返回true或false
        return $this->execute($sql);
    }


    /**
     * 执行 查询的 SQL语句的操作
     * @param string $sql 指定执行的SQL语句
     * @return array  返回数组(二维数组/空数组)
     */
    public function query($sql)
    {
        $stmt = $this->link->query($sql);
        return $stmt->fetchAll();
    }


    /**
     * 执行 增删改 SQL语句的操作
     * @param string $sql 指定执行的SQL语句
     * @return bool/int  操作失败返回false/删改成功返回true/新增成功返回ID
     */
    public function execute($sql)
    {
        $result = $this->link->exec($sql);
        if ($result === 0) {
            // 增删改失败
            return false;
        } else {
            if ($this->link->lastInsertId() > 0) {
                //新增成功 返回自增ID
                return $this->link->lastInsertId();
            } else {
                // 删改成功返回true
                return true;
            }
        }
    }


    /**
     * 获取数据表内所有的字段
     * @return null 无返回值,执行结果会存储到fields属性值中
     */
    private function getField()
    {
        //查询表结构
        $sql = "DESC {$this->table}";
        $list = $this->query($sql);
        // 遍历得到全部字段名字
        $fields = [];
        foreach ($list as $val) {
            $fields[] = $val['Field'];
            // 获取主键
            if ($val['Key'] == 'PRI') {
                $this->pk = $val['Field'];
            }
        }
        //给属性赋值
        $this->fields = $fields;
    }


    /**
     * 私有化克隆方法
     * @return 无
     */
    private function __clone()
    {
        // 该对象无法被克隆
    }

}
  • 使用示例
<?php


error_reporting(E_ALL);
ini_set('display_errors', 1);

require dirname(__FILE__) . '/Db.class.php';


function test()
{
    //数据库配置
    $db_config = [
        'dsn' => 'mysql:host=127.0.0.1;dbname=tp51;charset=utf8',
        'user' => 'root',
        'pass' => 'rootv8',
    ];

    $data = [
        'code' => 112001,
        'name' => 222222
    ];

    //设置数据表和相关配置(配置不写则使用默认配置)
    $db = Db::table('region_1_provinces', $db_config);

    // select查询
    $res = $db->where('id>12')->select();

    // find单条查询
    $res = $db->find('id', 1);

    //update更新
    $res = $db->update(array('id' => 40), $data);

    //insert插入
    $res = $db->insert($data);

    //delete删除
    $res = $db->delete('code', 111);

    dump($res);
}

//调用
test();
?>

相关文章

网友评论

      本文标题:php 封装PDO单例 2022-11-27

      本文链接:https://www.haomeiwen.com/subject/vflcfdtx.html