自制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 什么是PEAR?(第三篇)
Mar 19 PHP
PHP 中文乱码解决办法总结分析
Jul 30 PHP
解析PHP将对象转换成数组的方法(兼容多维数组类型)
Jun 21 PHP
IIS6.0中配置php服务全过程解析
Aug 07 PHP
php递归获取目录内文件(包含子目录)封装类分享
Dec 25 PHP
PHP进程同步代码实例
Feb 12 PHP
PHP SPL标准库之数据结构堆(SplHeap)简单使用实例
May 12 PHP
PHP嵌套输出缓冲代码实例
May 12 PHP
Symfony2学习笔记之系统路由详解
Mar 17 PHP
CI分页类首页、尾页不显示的解决方法
Mar 28 PHP
PHP中加速、缓存扩展的区别和作用详解(eAccelerator、memcached、xcache、APC )
Jul 09 PHP
ecshop适应在PHP7的修改方法解决报错的实现
Nov 01 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
星际争霸秘籍
2020/03/04 星际争霸
PHP中生成UUID自定义函数分享
2015/06/10 PHP
详解PHP的Yii框架中的Controller控制器
2016/03/29 PHP
PHP调用接口API封装的例子
2019/10/11 PHP
prototype 学习笔记整理
2009/07/17 Javascript
Jsonp 跨域的原理以及Jquery的解决方案
2010/05/18 Javascript
javascript语言结构小记(一)
2011/09/10 Javascript
javascript游戏开发之《三国志曹操传》零部件开发(四)用地图块拼成大地图
2013/01/23 Javascript
JS图片无缝滚动(简单利于使用)
2013/06/17 Javascript
浅析jquery某一元素重复绑定的问题
2014/01/03 Javascript
javascript 实现子父窗体互相传值的简单实例
2014/02/17 Javascript
全面解析Bootstrap排版使用方法(文字样式)
2015/11/30 Javascript
AngularJS ng-change 指令的详解及简单实例
2016/07/30 Javascript
完美解决spring websocket自动断开连接再创建引发的问题
2017/03/02 Javascript
Vue的MVVM实现方法
2017/08/16 Javascript
vue.js 底部导航栏 一级路由显示 子路由不显示的解决方法
2018/03/09 Javascript
vue改变循环遍历后的数据实例
2019/11/07 Javascript
vue flex 布局实现div均分自动换行的示例代码
2020/08/05 Javascript
antd的select下拉框因为数据量太大造成卡顿的解决方式
2020/10/31 Javascript
[05:28]刀塔密之一:团结则存
2014/07/03 DOTA
[03:13]DOTA2-DPC中国联赛1月25日Recap集锦
2021/03/11 DOTA
使用Node.js和Socket.IO扩展Django的实时处理功能
2015/04/20 Python
Python用csv写入文件_消除空余行的方法
2018/07/06 Python
Python3中关于cookie的创建与保存
2018/10/21 Python
Python设计模式之解释器模式原理与用法实例分析
2019/01/10 Python
解决python3插入mysql时内容带有引号的问题
2020/03/02 Python
基于django2.2连oracle11g解决版本冲突的问题
2020/07/02 Python
澳洲小众品牌的集合网站:BNKR
2018/02/23 全球购物
Keds加拿大官网:购买帆布运动鞋和皮鞋
2019/09/26 全球购物
最新的咖啡店创业计划书
2013/12/30 职场文书
五年级音乐教学反思
2014/02/06 职场文书
党员创先争优公开承诺书
2014/03/28 职场文书
质监局领导班子践行群众路线整改方案
2014/10/26 职场文书
2015年医德医风工作总结
2015/04/02 职场文书
寻找成龙观后感
2015/06/12 职场文书
python中的被动信息搜集
2021/04/29 Python