自制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学习笔记之面向对象编程
Dec 29 PHP
php中将字符串转为HTML的实体引用的一个类
Feb 03 PHP
基于PHP Web开发MVC框架的Smarty使用说明
Apr 19 PHP
解析php中eclipse 用空格替换 tab键
Jun 24 PHP
PHP统计nginx访问日志中的搜索引擎抓取404链接页面路径
Jun 30 PHP
php中单个数据库字段多列显示(单字段分页、横向输出)
Jul 28 PHP
php动态生成版权所有信息的方法
Mar 24 PHP
php简单smarty入门程序实例
Jun 11 PHP
PHP预定义超全局数组变量小结
Aug 20 PHP
php从数据库读取数据,并以json格式返回数据的方法
Aug 21 PHP
PHP获取对象属性的三种方法实例分析
Jan 03 PHP
php封装实现钉钉机器人报警接口的示例代码
Aug 08 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中处理模拟rewrite 效果
2006/12/09 PHP
js和php邮箱地址验证的实现方法
2014/01/09 PHP
php表单处理操作
2017/11/16 PHP
基于php数组中的索引数组和关联数组详解
2018/03/12 PHP
redis+php实现微博(一)注册与登录功能详解
2019/09/23 PHP
JS动画效果代码3
2008/04/03 Javascript
CSS+Jquery实现页面圆角框方法大全
2009/12/24 Javascript
JS对外部文件的加载及对IFRMAME的加载的实现,当加载完成后,指定指向方法(方法回调)
2011/07/04 Javascript
namespace.js Javascript的命名空间库
2011/10/11 Javascript
JavaScript伸缩的菜单简单示例
2013/12/03 Javascript
基于Jquery实现万圣节快乐特效
2015/11/01 Javascript
javascript 数组的正态分布排序的问题
2016/07/31 Javascript
深入理解Node.js的HTTP模块
2016/10/12 Javascript
JS实现Ajax的方法分析
2016/12/20 Javascript
Javascript实现base64的加密解密方法示例
2017/06/27 Javascript
javaScript之split与join的区别(详解)
2017/11/08 Javascript
vue2.0 实现导航守卫的具体用法(路由守卫)
2018/05/17 Javascript
ng-events类似ionic中Events的angular全局事件
2018/09/05 Javascript
微信小程序webview与h5通过postMessage实现实时通讯的实现
2019/08/20 Javascript
vue iview实现动态新增和删除
2020/06/17 Javascript
js实现ajax的用户简单登入功能
2020/06/18 Javascript
微信小程序清空输入框信息与实现屏幕往上滚动的示例代码
2020/06/23 Javascript
python调用系统ffmpeg实现视频截图、http发送
2018/03/06 Python
python使用sessions模拟登录淘宝的方式
2019/08/16 Python
python程序 线程队列queue使用方法解析
2019/09/23 Python
Python3操作读写CSV文件使用包过程解析
2020/04/10 Python
python继承threading.Thread实现有返回值的子类实例
2020/05/02 Python
如何基于Python pygame实现动画跑马灯
2020/11/18 Python
python爬虫利用代理池更换IP的方法步骤
2021/02/21 Python
一款基于css3的动画按钮代码教程
2014/11/23 HTML / CSS
html5+css3气泡组件的实现
2014/11/21 HTML / CSS
电气个人求职信范文
2014/02/04 职场文书
法律讲堂观后感
2015/06/11 职场文书
浅谈node.js中间件有哪些类型
2021/04/29 Javascript
goland 设置project gopath的操作
2021/05/06 Golang
解决Swagger2返回map复杂结构不能解析的问题
2021/07/02 Java/Android