(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这个函数。
- (3)php框架开发---数据库模型开发
- PHP开发框架Laravel数据库操作方法总结
- PHP开发框架总结
- PHP开发框架
- PHP开发框架总结
- CodeIgniter php开发框架
- 关于PHP开发框架
- php开发框架搭建
- php开发框架搭建
- [转]PHP开发框架
- PHP开发框架总结
- php开发框架
- 关于 PHP 开发框架
- php开发框架
- PHP开发框架
- PHP开发框架比较
- PHP开发框架
- PHP 开发框架扩展
- 第15章 磁盘配额(Quota)与进阶文件系统管理
- PS CS6移动工具中图层与组设置快捷键切换(ps动作录制的妙用)
- redis的测试学习小结
- vue-chat项目之重构与体验优化
- 51nod 1055 最长等差数列
- (3)php框架开发---数据库模型开发
- 校招准备系列:每天一道算法题(13)-斐波那契数列
- Gym 101142A Anniversary Cake
- 移动架构10_面向切面设计AOP
- Lintcode138 Subarray Sum solution 题解
- Dubbo 详细介绍
- FutureTask源码解析
- 最完美的“婚”鞋? NMD_R2“囍”(台灣愛迪達)
- Linux如何加载U盘