自制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获取当前文件所在目录 getcwd()函数
May 13 PHP
用php实现让页面只能被百度gogole蜘蛛访问的方法
Dec 29 PHP
PHP+SQL 注入攻击的技术实现以及预防办法
Jan 27 PHP
Windows下部署Apache+PHP+MySQL运行环境实战
Aug 31 PHP
提高PHP编程效率的方法
Nov 07 PHP
php验证是否是md5编码的简单代码
Apr 01 PHP
php递归json类实例
Dec 02 PHP
php实现简易聊天室应用代码
Sep 23 PHP
PHP数学运算函数大汇总(经典值得收藏)
Apr 01 PHP
php导出csv文件,可导出前导0实例代码
Nov 16 PHP
php 从一个数组中随机的取出若干个不同的数实例
Dec 31 PHP
php获取是星期几的的一些常用姿势
Dec 15 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导出CSV抽象类实例
2014/09/24 PHP
PHP多进程编程实例
2014/10/15 PHP
thinkPHP分页功能实例详解
2017/05/05 PHP
基于jQuery的仿flash的广告轮播代码
2010/11/04 Javascript
jquery获得同源iframe内body下标签的值的方法
2014/09/25 Javascript
JavaScript计时器示例分析
2015/02/05 Javascript
jquery操作select方法汇总
2015/02/05 Javascript
JavaScript如何自定义trim方法
2015/07/28 Javascript
JS函数的定义与调用方法推荐
2016/05/12 Javascript
BootStrap学习系列之Bootstrap Typeahead 组件实现百度下拉效果(续)
2016/07/07 Javascript
JS实现快速的导航下拉菜单动画效果附源码下载
2016/11/01 Javascript
JS 拦截全局ajax请求实例解析
2016/11/29 Javascript
Angular.JS判断复选框checkbox是否选中并实时显示
2016/11/30 Javascript
Bootstrap基本插件学习笔记之标签切换(17)
2016/12/08 Javascript
详解Angular2 关于*ngFor 嵌套循环
2017/05/22 Javascript
VUE前端cookie简单操作
2017/10/17 Javascript
vue监听键盘事件的快捷方法【推荐】
2018/07/11 Javascript
JavaScript实现JSON合并操作示例【递归深度合并】
2018/09/07 Javascript
vue设置导航栏、侧边栏为公共页面的例子
2019/11/01 Javascript
node.js中 redis 的安装和基本操作示例
2020/02/10 Javascript
Vue之封装公用变量以及实现方式
2020/07/31 Javascript
element 动态合并表格的步骤
2020/12/31 Javascript
[02:28]DOTA2亚洲邀请赛 LGD战队巡礼
2015/02/03 DOTA
python定时利用QQ邮件发送天气预报的实例
2017/11/17 Python
Python中使用支持向量机SVM实践
2017/12/27 Python
face++与python实现人脸识别签到(考勤)功能
2019/08/28 Python
Python 3.8正式发布,来尝鲜这些新特性吧
2019/10/15 Python
浅谈html5 video 移动端填坑记
2018/01/15 HTML / CSS
Myprotein蛋白粉美国官网:欧洲畅销运动营养品牌
2016/11/15 全球购物
澳大利亚先进的皮肤和激光诊所购物网站:Soho Skincare
2018/10/15 全球购物
英国家具、照明、家居用品网上商店:Wayfair.co.uk
2020/02/13 全球购物
动画设计系毕业生求职信
2014/07/15 职场文书
解除劳动合同证明书
2014/09/26 职场文书
2014年党务公开工作总结
2014/12/09 职场文书
婚姻出轨保证书
2015/05/08 职场文书
解决Nginx 配置 proxy_pass 后 返回404问题
2021/03/31 Servers