自制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桌面中心(二) 数据库写入
Mar 11 PHP
php 中文处理函数集合
Aug 27 PHP
Zend 输出产生XML解析错误
Mar 03 PHP
来自phpguru得Php Cache类源码
Apr 15 PHP
PHP 小心urldecode引发的SQL注入漏洞
Oct 27 PHP
php下foreach提示Warning:Invalid argument supplied for foreach()的解决方法
Nov 11 PHP
PHP和Mysql中转UTF8编码问题汇总
Oct 10 PHP
PHP中使用substr()截取字符串出现中文乱码问题该怎么办
Oct 21 PHP
php封装的单文件(图片)上传类完整实例
Oct 18 PHP
微信 getAccessToken方法详解及实例
Nov 23 PHP
php 反斜杠处理函数addslashes()和stripslashes()实例详解
Dec 25 PHP
Laravel框架FormRequest中重写错误处理的方法
Feb 18 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
DC四月将推出百页特刊漫画 纪念小丑诞生80周年
2020/04/09 欧美动漫
php url路由入门实例
2014/04/23 PHP
php编程每天必学之验证码
2016/03/03 PHP
mysql查找删除重复数据并只保留一条实例详解
2016/09/24 PHP
PHP基于面向对象封装的分页类示例
2019/03/15 PHP
JQuery UI皮肤定制
2009/07/27 Javascript
document.getElementById方法在Firefox与IE中的区别
2010/05/18 Javascript
不使用浏览器运行javascript代码的方法
2013/07/24 Javascript
js的hasownproperty使用示例
2014/03/02 Javascript
js实现页面跳转的几种方法小结
2016/05/16 Javascript
判断是否存在子节点的实现代码
2016/05/18 Javascript
Vue.js组件tabs实现选项卡切换效果
2016/12/01 Javascript
Bootstrap基本组件学习笔记之按钮组(8)
2016/12/07 Javascript
Vue结合原生js实现自定义组件自动生成示例
2017/01/21 Javascript
Vue三层嵌套路由的示例代码
2018/05/05 Javascript
Vue页面骨架屏的实现方法
2018/05/22 Javascript
Easyui 关闭jquery-easui tab标签页前触发事件的解决方法
2019/04/28 jQuery
vue登录页面cookie的使用及页面跳转代码
2019/07/10 Javascript
layer插件实现在弹出层中弹出一警告提示并关闭弹出层的方法
2019/09/24 Javascript
[03:17]2016完美“圣”典风云人物:冷冷专访
2016/12/08 DOTA
调试Python程序代码的几种方法总结
2015/04/28 Python
解决Pyinstaller 打包exe文件 取消dos窗口(黑框框)的问题
2019/06/21 Python
使用python对多个txt文件中的数据进行筛选的方法
2019/07/10 Python
基于python实现数组格式参数加密计算
2020/04/21 Python
Python爬虫如何破解JS加密的Cookie
2020/11/19 Python
法拉利英国精品店:Ferraris Boutique UK
2019/07/20 全球购物
西班牙Polo衫品牌:Polo Club
2020/08/09 全球购物
西部世纪.net笔试题面试题
2014/04/03 面试题
会计学财务管理专业个人的自我评价
2013/10/19 职场文书
金融专业个人求职信范文
2013/11/28 职场文书
音乐教师求职信
2014/06/28 职场文书
学习张丽丽心得体会
2014/09/03 职场文书
学生乘坐校车安全责任书
2015/05/11 职场文书
2015年高三教学工作总结
2015/07/21 职场文书
Jupyter notebook 输出部分显示不全的解决方案
2021/04/24 Python
Pillow图像处理库安装及使用
2022/04/12 Python