(3)php框架开发---数据库模型开发

今天有空再写一篇php的数据库模型类开发,这次的数据库类采用的是pdo来实现的,因为pdo有较好的适用性,所以使用pdo比mysql,mysqli都要好用。

首先就是要确定基本的思路,首先要有一个模型类model.php,然后这个模型类有一个保护成员变量,这个变量用来保存数据库的对象,所以这里要使用一个数据库管理类db.php来规范管理所有的数据库对象,这些对象都保存在一个数据中,然后就可以非常的容易切换,之后就是各个数据库驱动mysql,mysqli等,这些驱动都要继承最基本的驱动类dirver.php这个驱动基本类。

基本的结构如下图:


数据库驱动文件类,这个类封装了基本的sql方法和变量,因为大多数的sql都使用到这些方法,所以做一个封装,然后让其它类继承。

driver类:

<?php
/**
 * Created by PhpStorm.
 * User: DMF
 * Date: 2017/9/23
 * Time: 15:59
 */

namespace Dphp\core\database;


class driver
{
    //数据库配置
    protected $config = array(
        'type'              =>  'mysql',     // 数据库类型
        'hostname'          =>  '127.0.0.1', // 服务器地址
        'database'          =>  'test',          // 数据库名
        'username'          =>  'root',      // 用户名
        'password'          =>  'root',          // 密码
        'hostport'          =>  '8081',        // 端口
        'dsn'               =>  'mysql:host=localhost;dbname=test', //pdo连接信息
    );

    //数据库pdo连接id 支持多个连接
    protected $linkId = array();
    //当前pdo连接id
    protected $_linkId = null;
    //pdo操作实例
    protected $pdoStatement = null;
    // 事务指令数
    protected $transTimes = 0;
    //当前sql指令
    protected $querySql = '';
    // 错误信息
    protected $error      = '';
    //pdo连接参数
    protected $options = array(

    );
    protected $bind = array(); // 参数绑定

    //连接数据库函数
    public function connect($config=array()){
        if(empty($config)){
            $config = $this->config;
        }
        try{
            $this->_linkId = new \PDO($config['dsn'],$config['username'],$config['password']);
            echo "连接成功<br/>";
        }catch (\PDOException $e) {
            echo $e->errorInfo(),$e->getMessage();
            die ("Error!: " . $e->getMessage() . "<br/>");
        }

        return $this->_linkId;
    }

    //释放查询结果
    public function free(){
        $this->pdoStatement = null;
    }



    //执行查询,并返回结果集
    public function query($sql,$fetchSql=false){

        echo '<br/>'.$sql.'<br/>';
        $this->initConnect();
        //判断是否初始化失败
        if(!$this->_linkId)return fasle;
        try{
            //pdo执行sql语句准备
            $this->pdoStatement = $this->_linkId->prepare($sql);

        }catch (\PDOException $e) {
            echo $e->getMessage();
            return false;
        }
        if($this->pdoStatement === false){
            return false;
        }

        //数据绑定
        foreach($this->bind as $k=>$v){
            $this->pdoStatement->bindParam($k,$v);
        }

        //执行完成清空绑定数据数组
        $this->bind = array();

        //执行sql语句
        $this->pdoStatement->execute();
        //返回sql执行结果集
        return $this->pdoStatement->fetchAll(\PDO::FETCH_ASSOC);

    }

    //执行查询,并返回结果集
    public function execute($sql,$fetchSql=false){

        echo '<br/>'.$sql.'<br/>';
        $this->initConnect();
        //判断是否初始化失败
        if(!$this->_linkId)return fasle;
        try{
            //pdo执行sql语句准备
            $this->pdoStatement = $this->_linkId->prepare($sql);

        }catch (\PDOException $e) {
            echo $e->getMessage();
            return false;
        }

        if($this->pdoStatement === false){
            return false;
        }

        //数据绑定
        foreach($this->bind as $k=>$v){
            $this->pdoStatement->bindParam($k,$v);
        }

        //执行完成清空绑定数据数组
        $this->bind = array();

        //执行sql语句
        return $this->pdoStatement->execute();

        //var_dump($this->pdoStatement->errorInfo());

    }


    //启动事务
    public function startTransaction(){
        $this->connect();
        if(!$this->_linkId)return false;
        if($this->transTimes == 0){
            $this->_linkId->beginTransaction();
        }
        $this->transTimes++;
    }

    //提交数据,要非自动提交
    public function commit(){
        if($this->transTimes>0){
            $result = $this->_linkId->commit();
            $this->transTimes = 0;
            if(!$result){
                $this->error();
                return false;
            }
        }
        return true;
    }

    //回滚数据
    public function rollback(){
        if($this->transTimes>0){
            $result = $this->_linkId->rollback();
            $this->transTimes = 0;
            if(!$result){
                $this->error();
                return false;
            }
        }
        return true;
    }

    //初始化连接
    protected function initConnect(){
        //判断是否存在连接对象
       if(!$this->_linkId)$this->_linkId = $this->connect();
    }

    //关闭数据库
    public function close(){
        $this->_linkId = null;
    }

    //数据库错误信息
    public function error(){
        if($this->pdoStatement){
            $error = $this->pdoStatement->errorInfo();
            $this->error = $error[1].':'.$error[2];
        }else{
            $this->error = '';
        }
        return $this->error;
    }

    //析构函数
    public function __destruct()
    {
        // TODO: Implement __destruct() method.
        if($this->pdoStatement){
            $this->free();
        }
        //关闭数据库连接
        $this->close();
    }

    /*
     * 数据绑定
     * $name:名
     * $value:值
     */
    public function bindParam($name,$value){
        $this->bind[':'.$name] = $value;
    }


    /*
     * 插入数据
     * $table:数据表
     * $data:插入数据
     */
    public function insert($table='',$data=array()){
        if(empty($data)){
            die('数据不能为空!');
        }

        //字段名处理
        foreach($data as $k=>$v){
            $fields[] = $k;
            $values[] = $v;
            $this->bindParam($k,$v);
        }

        //insert的sql语句处理
        $sql = 'INSERT INTO '.$table.' ( '.implode(',',$fields)
            .') VALUES (';
        foreach($fields as $k=>$v){
            $sql.=':'.$v.',';
        }
        $sql = rtrim($sql,',');
        $sql .= ')';
        echo '<br/>'.$sql.'<br/>';

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

    /*
     * 删除数据
     * $table:表名
     * $data:插入数据
     */
    public function delete($table='',$id=''){
        $sql = 'DELETE FROM '.$table.' WHERE id='.$id;
        echo $sql.'<br/>';
        return $this->execute($sql);
    }

    /*
     * 修改数据
     * $table:表名
     * $data:插入数据
     */
    public function update($table='',$data=array()){
        if(empty($data)){
            die('数据不能为空!');
        }

        $sql = 'UPDATE '.$table.' SET ';
        //字段名处理
        foreach($data as $k=>$v) {

            $sql = $sql.$k.'=:'.$k.',';

            $this->bindParam($k,$v);
        }
        $sql = rtrim($sql,',');
        $sql = $sql.' WHERE id='.$data['id'];
        #echo $sql.'<br/>';
       return $this->execute($sql);
    }

    /*
     * 查询数据
     * $table:表名
     * $data:插入数据
     */
    public function select($table='',$option=array()){

        $sql = 'SELECT * FROM '.$table.' WHERE ';
        foreach($option as $k=>$v){
            $sql .= $k.'=:'.$k .' AND ';
        }
        $sql = rtrim($sql,' AND ');
        echo $sql.'<br/>';
        foreach($option as $k=>$v) {

            $this->bindParam($k,$v);
        }

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

}

继承驱动类的mysqli类,这里可以写一些mysqli独有的方法,方便拓展开来

mysqli类:

<?php
/**
 * Created by PhpStorm.
 * User: DMF
 * Date: 2017/9/23
 * Time: 17:12
 */

namespace Dphp\core\database\sqlDriver;


class mysqli extends \Dphp\core\database\driver
{

}


db类其实就是用来全局静态的方法获取数据库实例对象,这样做的好处是,在使用同一个数据库对象的时候,我只要new一次就可以了。这里防止重复new相同的数据库,所以性能上是会有一定的提升。

db类:

<?php
/**
 * Created by PhpStorm.
 * User: DMF
 * Date: 2017/9/23
 * Time: 15:55
 */

namespace Dphp\core;


class db
{
    static private $instance = array();     //数据库连接实例
    static private $_instance = null;       //当前数据库实例
    //获取数据库实例
    static public function getInstance($config=array()){

        $md5 = md5(serialize($config));
        //判断是否存在数据库实例对象
        if(!isset(self::$instance[$md5])){
            $class = 'Dphp\\core\\database\\sqlDriver\\mysqli';
            self::$instance[$md5] = new $class();
            echo 'new了一个数据库对象<br/>';
        }
        else {
            echo '缓存一个数据库对象<br/>';
        }
        return self::$instance[$md5];
    }



}

直接提供操作数据库的接口方法。

model类:

<?php
/**
 * Created by PhpStorm.
 * User: DMF
 * Date: 2017/9/25
 * Time: 13:12
 */

namespace Dphp\core;


class model
{
    //数据库对象
    protected $db;


    //初始化数据库对象
    public function __construct($name='')
    {
        $this->db();
    }

    //数据库对象实例化
    public function db(){
        if($this->db)return $this->db;
        //获取数据库对象
        $this->db = \Dphp\core\db::getInstance();
        return $this->db;
    }

    /*
     * 数据添加
     * $table:表名
     * $data:添加的数据
     */
    public function add($table='',$data=array()){

        if(empty($table)||empty($data)){
            die('数据表为空或数据为空');
        }

        return $this->db->insert($table,$data);
        //var_dump($data2);
    }

    /*
     * 数据更新
     * $table:表名
     * $data:添加的数据
     */
    public function update($table='',$data=array()){

        if(empty($table)||empty($data)){
            die('数据表为空或数据为空');
        }

        return $this->db->update($table,$data);
        //var_dump($data2);
    }

    /*
     * 数据删除
     * $table:表名
     * $data:添加的数据
     */
    public function delete($table='',$id=null){

        if(empty($table)||empty($id)){
            die('数据表为空或数据为空');
        }

        return $this->db->delete($table,$id);
        //var_dump($data2);
    }

    /*
    * 数据查找
    * $table:表名
    * $data:添加的数据
    */
    public function select($table='',$option=array()){

        if(empty($table)||empty($option)){
            die('数据表为空或数据为空');
        }

        return $this->db->select($table,$option);
        //var_dump($data2);
    }
}



2017.10.31

在上面的数据库写法上,其实存在着一个bug和不方便的地方。


这里面我的数据库driver里面没写人性化,因为query的时候没用给你绑定数据的参数传入。所以更改后应该是这样子的。

<?php
/**
 * Created by PhpStorm.
 * User: DMF
 * Date: 2017/9/23
 * Time: 15:59
 */

namespace core\database;

class driver
{
    //数据库配置
    protected $config = array(
        'type'              =>  'mysql',     // 数据库类型
        'hostname'          =>  '127.0.0.1', // 服务器地址
        'database'          =>  '123',          // 数据库名
        'username'          =>  'root',      // 用户名
        'password'          =>  'root',          // 密码
        'hostport'          =>  '3306',        // 端口
        'dsn'               =>  'mysql:host=localhost;dbname=automobileRepairStation', //pdo连接信息
    );

    //数据库pdo连接id 支持多个连接
    protected $linkId = array();
    //当前pdo连接id
    protected $_linkId = null;
    //pdo操作实例
    protected $pdoStatement = null;
    // 事务指令数
    protected $transTimes = 0;
    //当前sql指令
    protected $querySql = '';
    // 错误信息
    protected $error      = '';
    //pdo连接参数
    protected $options = array(

    );
    protected $bind = array(); // 参数绑定

    //连接数据库函数
    public function connect($config=array()){
        if(empty($config)){
            $config = $this->config;
        }
        try{
            $this->_linkId = new \PDO($config['dsn'],$config['username'],$config['password']);
            #echo "连接成功<br/>";
        }catch (\PDOException $e) {
            #echo $e->errorInfo(),$e->getMessage();
            die ("Error!: " . $e->getMessage() . "<br/>");
        }

        return $this->_linkId;
    }

    //释放查询结果
    public function free(){
        $this->pdoStatement = null;
    }


    //启动事务
    public function startTransaction(){
        $this->connect();
        if(!$this->_linkId)return false;
        if($this->transTimes == 0){
            $this->_linkId->beginTransaction();
        }
        $this->transTimes++;
    }

    //提交数据,要非自动提交
    public function commit(){
        if($this->transTimes>0){
            $result = $this->_linkId->commit();
            $this->transTimes = 0;
            if(!$result){
                $this->error();
                return false;
            }
        }
        return true;
    }

    //回滚数据
    public function rollback(){
        if($this->transTimes>0){
            $result = $this->_linkId->rollback();
            $this->transTimes = 0;
            if(!$result){
                $this->error();
                return false;
            }
        }
        return true;
    }

    //初始化连接
    protected function initConnect(){
        //判断是否存在连接对象
       if(!$this->_linkId)$this->_linkId = $this->connect();
    }

    //关闭数据库
    public function close(){
        $this->_linkId = null;
    }

    //数据库错误信息
    public function error(){
        if($this->pdoStatement){
            $error = $this->pdoStatement->errorInfo();
            $this->error = $error[1].':'.$error[2];
        }else{
            $this->error = '';
        }
        return $this->error;
    }

    //析构函数
    public function __destruct()
    {
        // TODO: Implement __destruct() method.
        if($this->pdoStatement){
            $this->free();
        }
        //关闭数据库连接
        $this->close();
    }



    //执行查询,并返回结果集
    public function query($sql,$fetchSql=false){

        #echo '<br/>'.$sql.'<br/>';
        $this->initConnect();
        //判断是否初始化失败
        if(!$this->_linkId)return fasle;
        try{
            //pdo执行sql语句准备
            $this->pdoStatement = $this->_linkId->prepare($sql);

        }catch (\PDOException $e) {
            echo $e->getMessage();
            return false;
        }

        return $this;
    }

    /*
     * 数据绑定
     * $name:名
     * $value:值
     */
    public function bindParam($name,$value){
        $this->bind[':'.$name] = $value;
    }

    /*
     * 数据绑定
     * $params:键值对参数数组
     */
    public function bind($params=null){

        if(is_array($params)){
            foreach($params as $k=>$v){

                $this->bindParam($k,$v);
            }
        }

        return $this;
    }

    /*
 * 执行并返回数据
 */
    public function fetch(){

        if(!empty($this->bind)){
            //数据绑定
            foreach($this->bind as $k=>&$v){
                $this->pdoStatement->bindParam($k,$v);
            }

        }

        //执行完成清空绑定数据数组
        $this->bind = array();
        //执行sql语句
        $this->pdoStatement->execute();

        //返回sql执行结果集
        return $this->pdoStatement->fetch(\PDO::FETCH_ASSOC);
    }

    /*
     * 执行并返回数据集
     */
    public function fetchAll(){

        if(!empty($this->bind)){
            //数据绑定
            foreach($this->bind as $k=>&$v){
                $this->pdoStatement->bindParam($k,$v);
            }

        }

        //执行完成清空绑定数据数组
        $this->bind = array();
        //执行sql语句
        $this->pdoStatement->execute();

        //返回sql执行结果集
        return $this->pdoStatement->fetchAll(\PDO::FETCH_ASSOC);
    }

    //执行查询
    public function execute(){

            //数据绑定
            foreach($this->bind as $k=>&$v){

                $this->pdoStatement->bindParam($k,$v);
            }


        //执行sql语句
        $flag =  $this->pdoStatement->execute();

        //执行完成清空绑定数据数组
        $this->bind = array();

        if($flag){
            return true;
        }
        return false;

    }

    /*
     * 插入数据
     * $table:数据表
     * $data:插入数据
     */
    public function insert($table='',$data=array()){
        if(empty($data)){
            die('数据不能为空!');
        }

        //字段名处理
        foreach($data as $k=>$v){
            $fields[] = $k;
            $values[] = $v;
            $this->bindParam($k,$v);
        }

        //insert的sql语句处理
        $sql = 'INSERT INTO '.$table.' ( '.implode(',',$fields)
            .') VALUES (';
        foreach($fields as $k=>$v){
            $sql.=':'.$v.',';
        }
        $sql = rtrim($sql,',');
        $sql .= ')';
        echo '<br/>'.$sql.'<br/>';

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

    /*
     * 删除数据
     * $table:表名
     * $data:插入数据
     */
    public function delete($table='',$id=''){
        $sql = 'DELETE FROM '.$table.' WHERE id='.$id;
        echo $sql.'<br/>';
        return $this->execute($sql);
    }

    /*
     * 修改数据
     * $table:表名
     * $data:插入数据
     */
    public function update($table='',$data=array()){
        if(empty($data)){
            die('数据不能为空!');
        }

        $sql = 'UPDATE '.$table.' SET ';
        //字段名处理
        foreach($data as $k=>$v) {

            $sql = $sql.$k.'=:'.$k.',';

            $this->bindParam($k,$v);
        }
        $sql = rtrim($sql,',');
        $sql = $sql.' WHERE id='.$data['id'];
        #echo $sql.'<br/>';
       return $this->execute($sql);
    }

    /*
     * 查询数据
     * $table:表名
     * $data:插入数据
     */
    public function select($table='',$option=array()){

        $sql = 'SELECT * FROM '.$table.' WHERE ';
        foreach($option as $k=>$v){
            $sql .= $k.'=:'.$k .' AND ';
        }
        $sql = rtrim($sql,' AND ');
        echo $sql.'<br/>';
        foreach($option as $k=>$v) {

            $this->bindParam($k,$v);
        }

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

}


仔细观察的话,我是将里面的方法细化了,加多了bind方法,fetch方法,fetchAll方法,execute方法。这样子就能够将query方法获取到pdoStatement,后再绑定数据到全局变量bind里面,然后再执行返回什么方法的结果集。

在使用bind的方法中,肯定会使用到bindParam的方法,这里面存在一个坑点,那就是bindParam(键,&值)的形式来进行绑定值的,所以当你使用foreach($values as $k=>$v)的时候,就会出现一直都是引用$v这个变量的值,所以一直都是最后面的获取到的值。所以这里要采用foreach($values as $k=>&$v)或是binValue这个函数。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值