【PHP】一个不错的DB类

<?php

/**

 * 数据库类

 *

 */

defined('FW') || header('HTTP/1.0 400 Bad Request');

/**

 * DB 抽象类

 * 其中主要是创建了一个静态变量$db,所有集成类的对象实例化到$db中方便调用

 * 该抽象类初始化时候根据配置文件存入$db变量,并调用子类进行DB实例化,使用DB::init()进行调用

 * 本类只实现了一个静态方法,并规定了其子类必须实现的一些方法。

 *

 */

abstract class DB {

    const DB_FETCH_ASSOC    = 1;

    const DB_FETCH_ARRAY    = 3;

    const DB_FETCH_ROW      = 2;

    const DB_FETCH_DEFAULT  = self::DB_FETCH_ASSOC;

    public static $db;

    protected static $db_type = array('mysqli' => 'MySQLi', 'oracle' => 'Oracle');

    protected $u_conn;

    protected $q_conn;

    protected $dsn;

    protected $db_key;

    protected $fecth_mode;

    protected $sql;

    protected $sqls;

    protected $qrs;

    protected $urs;

    protected $u_sqls;

    protected $q_sqls;

    protected $query_num;

    protected $update_num;

    protected function __construct() {

    }

    /**

     * DB初始化

     *

     * @param array $dsn 配置文件中的DB信息

     * @param string $db_key 配置中的数据库KEY名

     * @param const $fetch_mode 返回数据的KEY类型

     * @return array|DB DB对象

     */

    public static function &init(& $dsn, $db_key, $fetch_mode = self::DB_FETCH_ASSOC) {

        $key = explode('.', $db_key);

        $key = "['" . implode("']['" , $key) . "']";

        eval('$flag = isset(self::$db' . $key . ');');

        eval("/$db_info = /$dsn" . $key . ";");

        if (!$flag) {

            $class_name = 'DB_' . self::$db_type[strtolower($db_info['db_type'])];

            $obj = new $class_name($db_info, $db_key, $fetch_mode);

            eval('self::$db' . $key . ' =& $obj;');

            unset($obj);

        }

        return self::$db;

    }

    public abstract function connect($type = "slave");

    public abstract function close();

    public abstract function query($sql, $limit = null, $quick = false);

    public abstract function update($sql);

    public abstract function getOne($sql);

    public abstract function getCol($sql, $limit = null);

    public abstract function getRow($sql, $fetch_mode = self::DB_FETCH_DEFAULT);

    public abstract function getAll($sql, $limit = null, $fetch_mode = self::DB_FETCH_DEFAULT);

}

class DB_MySQLi extends DB {

    /**

     * MySQLi构造函数

     *

     * @param array $db_info 数据库配置信息

     * @param string $db_key db的key

     * @param 返回的数据格式 $fetch_mode

     */

    public function __construct(& $db_info, $db_key, $fetch_mode) {

        $this->db_key = $db_key;

        $this->dsn =& $db_info;

        $this->fecth_mode = $fetch_mode;

    }

    /**

     * 连接数据库

     *

     * 连接数据库之前可能需要改变DSN,一般不建议使用此方法

     *

     * @param string $type 选择连接主服务器或者从服务器

     * @return boolean

     */

    public function connect($type = "slave") {

        if ($type == "master" || !isset($this->dsn["slave"])) {

            $db_host = isset($this->dsn["master"]) ? $this->dsn["master"]["db_host"] : $this->dsn["db_host"];

            $db_name = isset($this->dsn["master"]) ? $this->dsn["master"]["db_name"] : $this->dsn["db_name"];

            $db_user = isset($this->dsn["master"]) ? $this->dsn["master"]["db_user"] : $this->dsn["db_user"];

            $db_pass = isset($this->dsn["master"]) ? $this->dsn["master"]["db_pass"] : $this->dsn["db_pass"];

            $this->u_conn = mysqli_connect($db_host, $db_user, $db_pass);

            if (!$this->u_conn) {

                throw new DB_Exception('更新数据库连接失败');

            }

            if (!mysqli_select_db($this->u_conn, $db_name)) {

                throw new DB_Exception('更新数据库选择失败');

            }

            if (!isset($this->dsn["slave"])) {

                $this->q_conn =& $this->u_conn;

            }

        } else {

            if (empty($this->dsn["slave"])) {

                $this->connect('master');

                return $this->q_conn =& $this->u_conn;

            }

            if (empty($_COOKIE[COOKIE_PREFIX . $this->db_key . '_db_no'])) {

                $db_no = array_rand($this->dsn["slave"]);

                setcookie(COOKIE_PREFIX . $this->db_key . '_db_no', $db_no, null, COOKIE_PATH, COOKIE_DOMAIN);

            } else {

                $db_no = $_COOKIE[COOKIE_PREFIX . $this->db_key . '_db_no'];

            }

            $db_info = $this->dsn["slave"][$db_no];

            $db_host = $db_info["db_host"];

            $db_name = $db_info["db_name"];

            $db_user = $db_info["db_user"];

            $db_pass = $db_info["db_pass"];

            $this->q_conn = mysqli_connect($db_host, $db_user, $db_pass);

            if (!$this->q_conn) {

                if (!$this->u_conn) {

                    $this->connect('slave');

                }

                $this->q_conn =& $this->u_conn;

                if (!$this->q_conn) {

                    throw new DB_Exception('查询数据库连接失败');

                }

            } else {

                if (!mysqli_select_db($this->q_conn, $db_name)) {

                    throw new DB_Exception('查询数据库选择失败');

                }

            }

        }

        return true;

    }

    /**

     * 关闭数据库连接

     *

     * 一般不需要调用此方法

     */

    public function close() {

        if ($this->u_conn === $this->q_conn) {

            if (is_object($this->u_conn)) {

                mysqli_close($this->u_conn);

            }

        } else {

            if (is_object($this->u_conn)) {

                mysqli_close($this->u_conn);

            }

            if (is_object($this->q_conn)) {

                mysqli_close($this->q_conn);

            }

        }

    }

    /**

     * 执行一个SQL查询

     *

     * 本函数仅限于执行SELECT类型的SQL语句

     *

     * @param string $sql SQL查询语句

     * @param mixed $limit 整型或者字符串类型,如10|10,10

     * @param boolean $quick 是否快速查询

     * @return resource 返回查询结果资源句柄

     */

    public function query($sql, $limit = null, $quick = false) {

        if ($limit != null) {

            $sql = $sql . " LIMIT " . $limit;

        }

        $this->sqls[] = $sql;

        $this->q_sqls[] = $sql;

        $this->sql = $sql;

        if (!$this->q_conn) {

            $this->connect("slave");

        }

        $this->qrs = mysqli_query($this->q_conn, $sql, $quick ? MYSQLI_USE_RESULT : MYSQLI_STORE_RESULT);

        if (!$this->qrs) {

            throw new DB_Exception('查询失败:' . mysqli_error($this->q_conn));

        } else {

            $this->query_num++;

            return $this->qrs;

        }

    }

    /**

     * 获取结果集

     *

     * @param resource $rs 查询结果资源句柄

     * @param const $fetch_mode 返回的数据格式

     * @return array 返回数据集每一行,并将$rs指针下移

     */

    public function fetch($rs, $fetch_mode = self::DB_FETCH_DEFAULT) {

        switch ($fetch_mode) {

            case 1:

                $fetch_mode = self::DB_FETCH_ASSOC;

                break;

            case 2:

                $fetch_mode = self::DB_FETCH_ROW;

                break;

            case 3:

                $fetch_mode = self::DB_FETCH_ARRAY;

                break;

            default:

                $fetch_mode = self::DB_FETCH_DEFAULT;

                break;

        }

        return mysqli_fetch_array($rs, $fetch_mode);

    }

    /**

     * 执行一个SQL更新

     *

     * 本方法仅限数据库UPDATE操作

     *

     * @param string $sql 数据库更新SQL语句

     * @return boolean

     */

    public function update($sql) {

        $this->sql = $sql;

        $this->sqls[] = $this->sql;

        $this->u_sqls[] = $this->sql;

        if (!$this->u_conn) {

            $this->connect("master");

        }

        $this->urs = mysqli_query($this->u_conn, $sql);

        if (!$this->urs) {

            throw new DB_Exception('更新失败:' . mysqli_error($this->u_conn));

        } else {

            $this->update_num++;

            return $this->urs;

        }

    }

    /**

     * 返回SQL语句执行结果集中的第一行第一列数据

     *

     * @param string $sql 需要执行的SQL语句

     * @return mixed 查询结果

     */

    public function getOne($sql) {

        if (!$rs = $this->query($sql, 1, true)) {

            return false;

        }

        $row = $this->fetch($rs, self::DB_FETCH_ROW);

        $this->free($rs);

        return $row[0];

    }

    /**

     * 返回SQL语句执行结果集中的第一列数据

     *

     * @param string $sql 需要执行的SQL语句

     * @param mixed $limit 整型或者字符串类型,如10|10,10

     * @return array 结果集数组

     */

    public function getCol($sql, $limit = null) {

        if (!$rs = $this->query($sql, $limit, true)) {

            return false;

        }

        $result = array();

        while ($rows = $this->fetch($rs, self::DB_FETCH_ROW)) {

            $result[] = $rows[0];

        }

        $this->free($rs);

        return $result;

    }

    /**

     * 返回SQL语句执行结果中的第一行数据

     *

     * @param string $sql 需要执行的SQL语句

     * @param const $fetch_mode 返回的数据格式

     * @return array 结果集数组

     */

    public function getRow($sql, $fetch_mode = self::DB_FETCH_DEFAULT) {

        if (!$rs = $this->query($sql, 1, true)) {

            return false;

        }

        $row = $this->fetch($rs, $fetch_mode);

        $this->free($rs);

        return $row;

    }

    /**

     * 返回SQL语句执行结果中的所有行数据

     *

     * @param string $sql 需要执行的SQL语句

     * @param mixed $limit 整型或者字符串类型,如10|10,10

     * @param const $fetch_mode 返回的数据格式

     * @return array 结果集二维数组

     */

    public function getAll($sql, $limit = null, $fetch_mode = self::DB_FETCH_DEFAULT) {

        if (!$rs = $this->query($sql, $limit, true)) {

            return false;

        }

        $all_rows = array();

        while($rows = $this->fetch($rs, $fetch_mode)) {

            $all_rows[] = $rows;

        }

        $this->free($rs);

        return $all_rows;

    }

    /**

     * 返回最近一次查询返回的结果集条数

     *

     * @return int

     */

    public function rows() {

        return mysqli_num_rows($this->qrs);

    }

    /**

     * 返回最近一次插入语句的自增长字段的值

     *

     * @return int

     */

    public function lastID() {

        return mysqli_insert_id($this->u_conn);

    }

    /**

     * 释放当前查询结果资源句柄

     *

     */

    public function free($rs) {

        if ($rs) {

            return mysqli_free_result($rs);

        }

    }

    /**

     * 转义需要插入或者更新的字段值

     *

     * 在所有查询和更新的字段变量都需要调用此方法处理数据

     *

     * @param mixed $str 需要处理的变量

     * @return mixed 返回转义后的结果

     */

    public function escape($str) {

        return addslashes($str);

    }

    /**

     * 析构函数,暂时不需要做什么处理

     *

     */

    public function __destruct() {

    }

}

class DB_Oracle extends DB {

    protected $limit;

    public function __construct(& $db_info, $db_key, $fetch_mode) {

        $this->db_key = $db_key;

        $this->dsn =& $db_info;

        $this->fecth_mode = $fetch_mode;

    }

    public function connect($type = "slave") {

        global $_configs;

        if ($type == "master" || !isset($this->dsn["slave"])) {

            $db_name = isset($this->dsn["master"]) ? $this->dsn["master"]["db_name"] : $this->dsn["db_name"];

            $db_user = isset($this->dsn["master"]) ? $this->dsn["master"]["db_user"] : $this->dsn["db_user"];

            $db_pass = isset($this->dsn["master"]) ? $this->dsn["master"]["db_pass"] : $this->dsn["db_pass"];

            $this->u_conn = oci_new_connect($db_user, $db_pass, $db_name);

            if (!$this->u_conn) {

                throw new DB_Exception('更新数据库连接失败');

            }

            if (!isset($this->dsn["slave"])) {

                $this->q_conn =& $this->u_conn;

            }

        } else {

            if (empty($this->dsn["slave"])) {

                $this->connect('master');

                return $this->q_conn =& $this->u_conn;

            }

            if (empty($_COOKIE[COOKIE_PREFIX . $this->db_key . '_db_no'])) {

                $db_no = array_rand($this->dsn["slave"]);

                setcookie(COOKIE_PREFIX . $this->db_key . '_db_no', $db_no, null, COOKIE_PATH, COOKIE_DOMAIN);

            } else {

                $db_no = $_COOKIE[COOKIE_PREFIX . $this->db_key . '_db_no'];

            }

            $db_info = $this->dsn["slave"][$db_no];

            $db_name = $db_info["db_name"];

            $db_user = $db_info["db_user"];

            $db_pass = $db_info["db_pass"];

            $this->q_conn = oci_new_connect($db_user, $db_pass, $db_name);

            if (!$this->q_conn) {

                if (!$this->u_conn) {

                    $this->connect('slave');

                }

                $this->q_conn =& $this->u_conn;

                if (!$this->q_conn) {

                    throw new DB_Exception('查询数据库选择失败');

                }

            }

        }

        return true;

    }

    public function close() {

        if (is_resource($this->u_conn)) {

            oci_close($this->u_conn);

        }

        if (is_resource($this->q_conn)) {

            oci_close($this->q_conn);

        }

    }

    public function query($sql, $limit = null, $quick = false) {

        if ($limit != null) {

            $limit = explode(',', $limit);

            foreach ($limit as $key => $value) {

                $limit[$key] = (int) trim($value);

            }

            if (count($limit) == 1) {

                $limit[1] = $limit[0];

                $limit[0] = 0;

            }

        } else {

            $limit[0] = 0;

            $limit[1] = -1;

        }

        $this->sqls[] = $sql;

        $this->q_sqls[] = $sql;

        $this->sql = $sql;

        $this->limit = $limit;

        if (!$this->q_conn) {

            $this->connect("slave");

        }

        if (!$this->qrs = oci_parse($this->q_conn, $sql)) {

            $e = oci_error($this->qrs);

            throw new DB_Exception('SQL解析失败:' . $e['message']);

        }

        if (!oci_execute($this->qrs)) {

            $e = oci_error($this->qrs);

            throw new DB_Exception('查询执行失败:' . $e['message']);

        }

        $this->query_num++;

        return $this->qrs;

    }

    public function fetch($rs, $fetch_mode = self::DB_FETCH_DEFAULT) {

        switch ($fetch_mode) {

            case 1:

                $fetch_mode = self::DB_FETCH_ASSOC;

                break;

            case 2:

                $fetch_mode = self::DB_FETCH_ROW;

                break;

            case 3:

                $fetch_mode = self::DB_FETCH_ARRAY;

                break;

            default:

                $fetch_mode = self::DB_FETCH_DEFAULT;

                break;

        }

        $record = oci_fetch_array($rs, $fetch_mode);

        return $record;

    }

    public function update($sql) {

        $this->sql = $sql;

        $this->sqls[] = $this->sql;

        $this->u_sqls[] = $this->sql;

        if (!$this->u_conn) {

            $this->connect("master");

        }

        if (!$this->urs = oci_parse($this->u_conn, $sql)) {

            $e = oci_error($this->urs);

            throw new DB_Exception('SQL解析失败:' . $e['message']);

        }

        if (!oci_execute($this->urs)) {

            $e = oci_error($this->urs);

            throw new DB_Exception('更新失败:' . $e['message']);

        } else {

            $this->update_num++;

            return $this->urs;

        }

    }

    public function getOne($sql) {

        if (!$rs = $this->query($sql, 1, true)) {

            return false;

        }

        $result = array();

        oci_fetch_all($rs, $result, $this->limit[0], $this->limit[1], self::DB_FETCH_ROW);

        $this->free();

        return $result[0][0];

    }

    public function getCol($sql, $limit = null) {

        if (!$rs = $this->query($sql, $limit, true)) {

            return false;

        }

        $result = array();

        oci_fetch_all($rs, $result, $this->limit[0], $this->limit[1], self::DB_FETCH_ROW);

        foreach ($result as $key => $value) {

            $this->free();

            return $value;

        }

    }

    public function getRow($sql, $fetch_mode = self::DB_FETCH_DEFAULT) {

        if (!$rs = $this->query($sql, 1, true)) {

            return false;

        }

        oci_fetch_all($rs, $result, $this->limit[0], $this->limit[1], $fetch_mode);

        $result = $this->changeData($result);

        $this->free();

        return $result[0];

    }

    public function getAll($sql, $limit = null, $fetch_mode = self::DB_FETCH_DEFAULT) {

        if (!$rs = $this->query($sql, $limit, true)) {

            return false;

        }

        $result = array();

        oci_fetch_all($rs, $result, $this->limit[0], $this->limit[1], $fetch_mode);

        $result = $this->changeData($result);

        $this->free();

        return $result;

    }

    public function changeData($data) {

        $result = array();

        if (is_array($data)) {

            foreach ($data as $key => $value) {

                if (is_array($value)) {

                    foreach ($value as $k => $v) {

                        $result[$k][strtolower($key)] = $v;

                    }

                }

            }

        }

        return $result;

    }

    public function rows() {

        return oci_num_rows($this->qrs);

    }

    public function free() {

        if ($this->qrs) {

            oci_free_statement($this->qrs);

        }

        if ($this->urs) {

            oci_free_statement($this->urs);

        }

        $this->qrs = null;

        $this->urs = null;

    }

    public function escape($str) {

        if (is_array($str)) {

            foreach ($str as $key => $value) {

                $str[$key] = $this->escape($value);

            }

        } else {

            return str_replace("'", "''", $str);

        }

    }

    public function __destruct() {

    }

}

class DB_Exception extends Exception {

}

/*

$db = DB::init($configs['db_info'], 'common', 1);

try {

    $rs = $db['common']->query('SELECT * FROM tj_session');

    while ($row = $db['common']->fetch($rs)) {

        $record[] = $row;

    }

    $records = $db['common']->getAll('SELECT * FROM tj_session');

    //mysql_connect

} catch (DB_Exception $e) {

    print_r($e);

}

*/

//end of script

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卢卡上学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值