自制PHP框架之模型与数据库


Posted in PHP onMay 07, 2017

什么是模型?

我们的WEB系统一定会和各种数据打交道,实际开发过程中,往往一个类对应了关系数据库的一张或多张数据表,这里就会出现两个问题。

1.类和数据表,一方修改会导致另一方的修改,只要数据表结构不定下来,业务逻辑的开发几乎没法开工

2.获取数据时会牵涉很多SQL语句的拼接,如果数据结构变动,这些SQL需要改写

假如要开发一个博客系统,我们先设计两个Model和两张数据表

第一张数据表,表名是post,存储了博客文章,数据如下:

自制PHP框架之模型与数据库

第二章数据表,表名是comment,存储了博客文章的评论,数据如下:

自制PHP框架之模型与数据库

post和comment是一对多的关系,每一篇博客文章对应了多条评论,每一条评论只属于一篇文章。

Model类的设计之前,我们先定义好三个接口

interface IModel{
	public static function all();
	public static function get($id);
	public static function where($condition,$value);
}

定义Model类

class Model implements IModel{
	public static $table;
	
	public static $db;
	public function __construct(){
		self::$db=new MySQL();
	}
	
	public static function get($id){
		return self::where('id',$id);
	}
	
	public static function where($condition,$value){
		$sql=sprintf("select * from %s where %s='%s'",self::$table,$condition,$value);
		return self::$db->Query($sql);
	}

	public static function all(){
		$sql=sprintf("select * from %s",self::$table);
		return self::$db->Query($sql);
	}
}

这三个接口分别负责了三种查询:遍历查询,条件查询,按编号查询,其实这三种接口的设计并不是最科学的,甚至get方法不过是where的一种特殊形式,但是这样的设计并不影响我们工程,甚至也有助于理解,我们后期会对这段代码做改动。

之所以在Model类里就完成了SQL的拼接,就是希望在子类中不必重复再写SQL。

然后是Post类的定义

class PostModel extends Model{	
	public $postid;
	public function __construct(){
		parent::__construct();
		parent::$table='post';
	}
}

还有Comment类的定义

class CommentModel extends Model{
	public $commentid;
	public function __construct(){
		parent::__construct();
		parent::$table='comment';
	}
}

我们可以在控制器的方法中写这样的代码来完成调用数据

$post=new PostModel();
$post::all();
$arr=$post::get('1');
var_dump($arr);

$comment=new CommentModel();
$arr=$comment::get('2');
var_dump($arr);

我们发现,这样的代码很简洁,但是问题也随之而来,我们SQL查询时候,还有很多复杂的联表查询如join操作,如此,拼接SQL还是不可避免的,这个复杂的问题,我们放在后面解决。

模型与数据库

先写一个DB抽象类,规定类需要实现的方法

abstract class DB{
	
	private $IP;
	private $user;
	private $pwd;
	private $name;
	private $connection;
	
	abstract public function Execute($sql);
	abstract public function Query($sql);
}

这里以MySQL数据为例,当然你也完全可以实现一套Sqlite数据库的接口。

class MySQL extends DB{

	public function MySQL(){
		
		/*Config*/
		$this->IP='*';
		$this->ServerID='*';
		$this->ServerPassword='*';
		$this->DataBaseName='*';
		/*End of Config*/
		
		$this->connection=mysqli_connect($this->IP,$this->ServerID,$this->ServerPassword,$this->DataBaseName);
		
		if(!$this->connection){
			die('Could not connect'.$this->connection);
		}
		
		mysqli_query($this->connection,'set names utf8');
	}

	public function Execute($sql){
		return mysqli_query($this->connection,$sql);	
	}

	public function Query($sql){
		$result=mysqli_query($this->connection,$sql);
		$arr=array();
		while($row=mysqli_fetch_array($result)){
			$arr[]=$row;
		}
		return $arr;
	}
	public function Close(){
		mysqli_close($this->connection);
	}
}

谈到数据库类,上述的写法仍不是最好的,因为我们可以使用单例模式来保证DB类只有一次初始化,来节省硬件资源的开销,但这不是本节的主题,我们把设计模式放在之后来谈。 

PHP 相关文章推荐
Oracle 常见问题解答
Oct 09 PHP
window+nginx+php环境配置 附配置搭配说明
Dec 29 PHP
PHP+Mysql+jQuery实现动态展示信息
Oct 08 PHP
php获取网页中图片、DIV内容的简单方法
Jun 19 PHP
php数组排序usort、uksort与sort函数用法
Nov 17 PHP
php中使用key,value,current,next和prev函数遍历数组的方法
Mar 17 PHP
Zend Framework开发入门经典教程
Mar 23 PHP
10个对初学者非常有用的PHP技巧
Apr 06 PHP
动态表单验证的操作方法和TP框架里面的ajax表单验证
Jul 19 PHP
解决laravel groupBy 对查询结果进行分组出现的问题
Oct 09 PHP
phpcmsv9.0任意文件上传漏洞解析
Oct 20 PHP
详解Go与PHP的语法对比
May 29 PHP
自制PHP框架之路由与控制器
May 07 #PHP
PHP-CGI远程代码执行漏洞分析与防范
May 07 #PHP
PHP关键特性之命名空间实例详解
May 06 #PHP
PHP 中使用explode()函数切割字符串为数组的示例
May 06 #PHP
Thinkphp 空操作、空控制器、命名空间(详解)
May 05 #PHP
thinkPHP实现的联动菜单功能详解
May 05 #PHP
thinkPHP实现的省市区三级联动功能示例
May 05 #PHP
You might like
destoon文章模块调用企业会员资料的方法
2014/08/22 PHP
php使用ob_flush不能每隔一秒输出原理分析
2015/06/02 PHP
PHP数据库表操作的封装类及用法实例详解
2016/07/12 PHP
CI(CodeIgniter)框架中URL特殊字符处理与SQL注入隐患分析
2019/02/28 PHP
JQuery 写的个性导航菜单
2009/12/24 Javascript
基于jquery的划词搜索实现(备忘)
2010/09/14 Javascript
一个关于javascript匿名函数的问题分析
2012/03/30 Javascript
jquery 中多条件选择器,相对选择器,层次选择器的区别
2012/07/03 Javascript
禁用页面部分JavaScript方法的具体实现
2013/07/31 Javascript
JavaScript异步编程:异步数据收集的具体方法
2013/08/19 Javascript
NodeJS的url截取模块url-extract的使用实例
2013/11/18 NodeJs
js的隐含参数(arguments,callee,caller)使用方法
2014/01/28 Javascript
使用伪命名空间封装保护独自创建的对象方法
2016/08/04 Javascript
JavaScript自动点击链接 防止绕过浏览器访问的方法
2017/01/19 Javascript
微信小程序 定位到当前城市实现实例代码
2017/02/23 Javascript
js常用的继承--组合式继承
2017/03/06 Javascript
JS对象的深度克隆方法示例
2017/03/16 Javascript
关于vue的语法规则检测报错问题的解决
2018/05/21 Javascript
详解vue中的computed的this指向问题
2018/12/05 Javascript
JS实现随机点名器
2020/04/12 Javascript
vue data变量相互赋值后被实时同步的解决步骤
2020/08/05 Javascript
Node.js中的异步生成器与异步迭代详解
2021/01/31 Javascript
Python 连连看连接算法
2008/11/22 Python
python创建线程示例
2014/05/06 Python
有关wxpython pyqt内存占用问题分析
2014/06/09 Python
详细解读Python的web.py框架下的application.py模块
2015/05/02 Python
Python中 Lambda表达式全面解析
2016/11/28 Python
python实现日常记账本小程序
2018/03/10 Python
基于DataFrame筛选数据与loc的用法详解
2018/05/18 Python
Python3 实现文件批量重命名示例代码
2019/06/03 Python
使用Rasterio读取栅格数据的实例讲解
2019/11/26 Python
高校生生产实习自我鉴定
2013/09/21 职场文书
工程部主管岗位职责
2013/11/17 职场文书
高二英语教学反思
2014/01/19 职场文书
小学教师师德承诺书
2014/05/23 职场文书
2014医学院领导班子对照检查材料思想汇报
2014/09/19 职场文书