自制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 相关文章推荐
php 动态执行带有参数的类方法
Apr 10 PHP
php数组函数序列之in_array() - 查找数组中是否存在指定值
Nov 07 PHP
基于curl数据采集之正则处理函数get_matches的使用
Apr 28 PHP
php加密解密函数authcode的用法详细解析
Oct 28 PHP
php下foreach提示Warning:Invalid argument supplied for foreach()的解决方法
Nov 11 PHP
PHP 下载文件时如何自动添加bom头及解释BOM头和去掉bom头的方法
Jan 04 PHP
crontab无法执行php的解决方法
Jan 25 PHP
PHP MySql增删改查的简单实例
Jun 21 PHP
PHP判断JSON对象是否存在的方法(推荐)
Jul 06 PHP
PHP验证码无法显示的原因及解决办法
Aug 11 PHP
PHP安装BCMath扩展的方法
Feb 13 PHP
PHP接入支付宝接口失效流程详解
Nov 10 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
PHP获取短链接跳转后的真实地址和响应头信息的方法
2014/07/25 PHP
thinkPHP5框架导出Excel文件简单操作示例
2018/08/03 PHP
PHP实现提高SESSION响应速度的几种方法详解
2019/08/09 PHP
JavaScript事件处理器中的event参数使用介绍
2013/05/24 Javascript
js hover 定时器(实例代码)
2013/11/12 Javascript
jquery统计输入文字的个数并对其进行判断
2014/01/07 Javascript
javascript计时器详解
2015/02/28 Javascript
JavaScript计算两个日期时间段内日期的方法
2015/03/16 Javascript
jquery实现仿新浪微博带动画效果弹出层代码(可关闭、可拖动)
2015/10/12 Javascript
JavaScript中数组的22种方法必学(推荐)
2016/07/20 Javascript
微信小程序 本地存储及登录页面处理实例详解
2017/01/11 Javascript
Javascript ES6中数据类型Symbol的使用详解
2017/05/02 Javascript
Angular中自定义Debounce Click指令防止重复点击
2017/07/26 Javascript
angular5 httpclient的示例实战
2018/03/12 Javascript
Vue-cli3项目引入Typescript的实现方法
2019/10/18 Javascript
微信小程序修改数组长度的问题的解决
2019/12/17 Javascript
vue组件开发之slider组件使用详解
2020/08/21 Javascript
[02:45]2016年中国刀塔全程回顾,完美“圣”典即将上演
2016/12/15 DOTA
python调用摄像头拍摄数据集
2019/06/01 Python
Tensorflow 模型转换 .pb convert to .lite实例
2020/02/12 Python
python使用gdal对shp读取,新建和更新的实例
2020/03/10 Python
基于virtualenv创建python虚拟环境过程图解
2020/03/30 Python
细说CSS3中的选择符
2008/10/17 HTML / CSS
CSS3 函数技巧 用css 实现js实现的事情(clac Counters Tooltip)
2017/08/15 HTML / CSS
瑞典领先的汽车零部件网上零售商:bildelaronline24.se
2017/01/12 全球购物
新西兰便宜隐形眼镜购买网站:QUICKLENS New Zealand
2019/03/02 全球购物
介绍Java的内部类
2012/10/27 面试题
项目开发计划书
2014/01/09 职场文书
十八届三中全会感言
2014/03/10 职场文书
计算机多媒体专业自荐信
2014/07/04 职场文书
小学安全汇报材料
2014/08/14 职场文书
技术入股合作协议书
2014/10/07 职场文书
2015年会计年终工作总结
2015/05/26 职场文书
2015年暑期社会实践方案
2015/07/14 职场文书
MyBatis自定义SQL拦截器示例详解
2021/10/24 Java/Android
vmware虚拟机打不开vmx文件怎么办 ?vmware虚拟机vmx文件打开方法
2022/04/08 数码科技