您的位置:首页 > 编程语言 > PHP开发

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

2017-10-04 22:12 218 查看
今天有空再写一篇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这个函数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息