在PHP中使用灵巧的体系结构


Posted in PHP onOctober 09, 2006

很久以前我就想写这篇文章了,但是一直都没有时间。这里并不是想要告诉你怎样做,我希望它可以投石问路,和大家讨论一下如何开发一个好的、扩展性佳的web应用。

我从事开发已经有2-3年了,回望刚开始做的程序,真有点不相信是自己写的,现在我的web开发技巧已经得到了很大的提高,例如sourceForge(http://sourceforge.net/)就是我较为成熟的一个作品,代码都被分成各种的类和函数。数据库的结构也很清晰。站点的不同部分都是与其它部分独立开来的。

不过这个站点也不是完美的。如果我必需再写一遍,我将会通过对象或者函数库的方式,让HTML层与数据库层更明显地区分开来。

我发现不少的管理者都喜欢用图表的形式来表示自己的想法,这里我也提供一个。这种体系的意念是要将你的逻辑从表层中独立开来,这意味着任何复杂的东西都会下放到“API/数据访问层”。

对于安全检查、更新等代码,你最好不要放在HTML层中,你应该将这些理论上的代码放到API层。HTML层将只会进行简单的函数调用,并且返回数组、对象或者我最喜爱的数据库结果集。

在这个图中,HTML接口或者直接调用API层,或者调用一个HTML工具库(例如产生弹出窗口等),而那些库通过一个数据库抽象层可调用数据库(这样你就不必绑定在某种数据库上)。

基本的要点
对于一个灵巧的体系来说,有以下基本的要点:
1。数据库独立
2。表示层独立
3。便于修改
4。面向对象或者至少拆成函数库调用
这些都是我想到的,除了以上提到的外,肯定还有其它的要点,你可以在论坛中提出来。

以下就让我们详细地讨论一下以上各点:

1。数据库独立
你在设计的时候,或许不会知道自己的站点的负担究竟有多大,应此你应该记住一点,不能绑定在轻量级的数据库上,例如MS Access或者其它。因此你应该考虑到扩展性,如果更换数据库的话,你不用做太大的改动,甚至不用做什么改动,这是最理想的。

使用PHP时,对于各种数据库的函数调用都是不同的,你需要针对使用的数据库进行不同的编码。为了改变这种情况,你可以使用一个数据库抽象层,例如类似PHPLib或者其它人开发的库。
2。表示层独立
假如你要开发一个真正巨大、复杂的应用,你就必需开始考虑数据库的接口问题,这样你可以少做很多复制和粘贴的工作。例如你需要让你的站点具有WAP功能,以便移动电话的用户可以访问到它。如果你的应用设计得好的话,你只需要写一个轻便的WAP表示层调用所有你的数据库访问对象就行了,但是,如果你的应用体系设计得不好,你就可能需要重新写一个,这样你就需要同时维护一个HTML版本和一个WAP版本。

例如在开发SourceForge站点时,我们有大量的用户要提交他们的bug和任务等。开始时我们将它设计为全部通过web接口进行。后来在某些人的压力下,我们决定使用XML接口展现数据库。我们成功地将站点的核心逻辑由表示层中分离出来。现在的SourceForge上的bug跟踪和其它工具都使用两个不同的库--HTML库类和数据库类。数据类负责检测输入的值是否有效,并且处理安全检测,而表示层只是根据成功/失败返回true或者false。 为了简化,在我必须解释基类和其它对象如何扩展这些基类时,这个例子将不会基于一个完美的对象模型。不过我想这个例子能帮你建立一些概念。

HTML类的例子

//连接数据库
require ("database.php");

//通常使用的HTML头部/页脚
require ("html.php");

//数据访问库类
require ("bug_data.php");

echo site_header("Page Title");

echo "
Updating A Bug

";

if (bug_data_update($field1,$field2,$field3)) {

echo "

Update Failed!
";

} else {

echo "
Updated Bug Successfully
";
//显示全局错误字符串
echo $feedback;
}

echo site_footer();

?>

Example Data Access Lib

/**
* 控制更新数据库中的一个bug
* 进行数据有效性和安全的检查,并且在成功时返回true,
* 失败时返回false
*
*
*/

function bug_data_update ($field1,$field2,$field3) {
//全局字符串,返回错误
global $feedback;

//$field1 and $field2 are required
if (!$field1 || !$field2) {
$feedback="Field 1 And Field 2 Are Required";
return false;
}

//确认用户有权更新
if (!user_isadmin()) {
$feedback="You Must Be An Admin To Update a Bug";
return false;
}

//现在可以更新该bug

$result=db_query("UPDATE bug ".
"SET field2='$field2',".
"field3='$field3' ".
"WHERE id='$field1'");

//现在检查你的语句是否执行成功
if (!$result) {
//update failed
return false;
} else {
return true;
}
}

?>
3。便于修改
你当然不会在整个应用中都使用绝对的URL,不过我还要求更进一步,颜色的选择、元素的名字、字体和其它可能的选项最好也不是绝对的,它们应该在一个配置文件中设置,并且在每一页中将该文件包含进来。站点的风格也应该独立开来--这样你就无需在每个页面都进行拷贝粘贴的工作,我通常都将这些HTML放在一个函数中,然后就可以在需要时调用。

对于数据库密码、数据库连接等,同样也放在数据库抽象层中。

4。面向对象/函数
我们可以将流程处理拆分成不同的函数调用。每个调用都做一件事情,有时只需要调用其它的函数并且返回结果。

一个很好的例子是在每页中检查一个用户是否已经登录。如果不使用对象或者函数的话,在你的认证系统变动的时候,你就必须在每一页作修改,而不是仅仅改变库中一个函数的调用。在写一段代码之前,你要想一下,如果它在站点中要使用不止一次,你就必须将它移到库中实现。 还有补充吗?
肯定我还有一些地方没有想到,因此请提出你的想法。特别是,你写了一个很大、很复杂的应用,我很想知道如果要你重新再写一次,你会建立怎样的体系并且会做什么改变。

PHP 相关文章推荐
JAVA/JSP学习系列之六
Oct 09 PHP
php数组函数序列之array_splice() - 在数组任意位置插入元素
Nov 07 PHP
解析posix与perl标准的正则表达式区别
Jun 17 PHP
ThinkPHP写数组插入与获取最新插入数据ID实例
Nov 03 PHP
php通过修改header强制图片下载的方法
Mar 24 PHP
学习php设计模式 php实现模板方法模式
Dec 08 PHP
PHP数组去重比较快的实现方式
Jan 19 PHP
CI框架扩展系统核心类的方法分析
May 23 PHP
php session的应用详细介绍
Mar 22 PHP
php检查函数必传参数是否存在的实例详解
Aug 28 PHP
PDO::rollBack讲解
Jan 29 PHP
php设计模式之建造器模式分析【星际争霸游戏案例】
Jan 23 PHP
PHP脚本的10个技巧(8)
Oct 09 #PHP
用PHP实现小型站点广告管理
Oct 09 #PHP
一个域名查询的程序
Oct 09 #PHP
PHP脚本的10个技巧(7)
Oct 09 #PHP
PHP脚本的10个技巧(6)
Oct 09 #PHP
复杂检索数据并分页显示的处理方法
Oct 09 #PHP
PHP脚本的10个技巧(5)
Oct 09 #PHP
You might like
PHP中使用addslashes函数转义的安全性原理分析
2014/11/03 PHP
php遍历替换目录下文件指定内容的方法
2016/11/10 PHP
详解ThinkPHP3.2.3验证码显示、刷新、校验
2016/12/29 PHP
php设计模式之工厂模式用法经典实例分析
2019/09/20 PHP
PHP反射原理与用法深入分析
2019/09/28 PHP
解决laravel-admin 自己新建页面里 js 需要刷新一次的问题
2019/10/03 PHP
使用prototype.js 的时候应该特别注意的几个问题.
2007/04/12 Javascript
php gethostbyname获取域名ip地址函数详解
2010/01/24 Javascript
js各种验证文本框输入格式(正则表达式)
2010/10/22 Javascript
JS实现QQ图片一闪一闪的效果小例子
2013/07/31 Javascript
通过Javascript读取本地Excel文件内容的代码示例
2014/04/08 Javascript
JavaScript框架(iframe)操作总结
2014/04/16 Javascript
基于KO+BootStrap+MVC实现的分页控件代码分享
2016/11/07 Javascript
Bootstrap treeview实现动态加载数据并添加快捷搜索功能
2018/01/07 Javascript
Vue之mixin全局的用法详解
2018/08/22 Javascript
JS/HTML5游戏常用算法之路径搜索算法 随机迷宫算法详解【普里姆算法】
2018/12/13 Javascript
[00:10]DOTA2 TI9勇士令状明日上线
2019/05/07 DOTA
Python httplib,smtplib使用方法
2008/09/06 Python
使用Python中的线程进行网络编程的入门教程
2015/04/15 Python
python利用lxml读写xml格式的文件
2017/08/10 Python
django实现用户登陆功能详解
2017/12/11 Python
python单例模式获取IP代理的方法详解
2018/09/13 Python
Python判断以什么结尾以什么开头的实例
2018/10/27 Python
python实现微信自动回复机器人功能
2019/07/11 Python
python使用信号量动态更新配置文件的操作
2020/04/01 Python
Python fileinput模块如何逐行读取多个文件
2020/10/05 Python
phonegap常用事件总结(必看篇)
2017/03/31 HTML / CSS
美国东北部户外服装和设备零售商:Eastern Mountain Sports
2016/10/05 全球购物
JBL英国官网:JBL UK
2018/07/04 全球购物
普通PHP程序员笔试题
2016/01/01 面试题
护理专业应届毕业生推荐信
2013/11/15 职场文书
毕业自我评价
2014/02/05 职场文书
会计个人实习计划书
2014/08/15 职场文书
文员试用期转正自我鉴定
2014/09/14 职场文书
计划生育工作总结2015
2015/04/03 职场文书
上学路上观后感
2015/06/16 职场文书