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

来源:互联网 发布:生命周期假说 知乎 编辑:程序博客网 时间:2024/06/04 01:13

今天有空再写一篇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这个函数。