在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 相关文章推荐
用 php 编写的日历
Oct 09 PHP
PHP 应用程序的安全 -- 不能违反的四条安全规则
Nov 26 PHP
php 文件上传后缀名与文件类型对照表(几乎涵盖所有文件)
May 16 PHP
解析argc argv在php中的应用
Jun 24 PHP
解析php下载远程图片函数 可伪造来路
Jun 25 PHP
PHP实现采集中国天气网未来7天天气
Oct 15 PHP
ThinkPHP独立分组使用的注意事项
Nov 25 PHP
php实现微信公众平台账号自定义菜单类
Dec 02 PHP
详解Yii2 rules 的验证规则
Dec 02 PHP
老生常谈PHP位运算的用途
Mar 12 PHP
Yii框架函数简单用法分析
Sep 09 PHP
php pdo连接数据库操作示例
Nov 18 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,不用COM,生成excel文件
2006/10/09 PHP
收藏的一个php小偷的核心程序
2007/04/09 PHP
基于php验证码函数的使用示例
2013/05/03 PHP
百度地图经纬度转换到腾讯地图/Google 对应的经纬度
2015/08/28 PHP
php获取当前月与上个月月初及月末时间戳的方法
2016/12/05 PHP
laravel migrate初学常见错误的解决方法
2017/10/11 PHP
PHP实现APP微信支付的实例讲解
2018/02/10 PHP
PHP const定义常量及global定义全局常量实例解析
2020/05/28 PHP
在vs2010中调试javascript代码方法
2011/02/11 Javascript
解读JavaScript代码 var ie = !-[1,] 最短的IE判定代码
2011/05/28 Javascript
JavaScript中的变量声明早于赋值分析
2012/03/01 Javascript
jquery链式操作的正确使用方法
2014/01/06 Javascript
DOM基础教程之事件类型
2015/01/20 Javascript
moment.js轻松实现获取当前日期是当年的第几周
2015/02/05 Javascript
JavaScript中的some()方法使用详解
2015/06/09 Javascript
浅析JavaScript动画
2015/06/10 Javascript
jQuery ajax中使用confirm,确认是否删除的简单实例
2016/06/17 Javascript
最全面的JS倒计时代码
2016/09/17 Javascript
简单的js表格操作
2016/09/24 Javascript
Vue的Class与Style绑定的方法
2017/09/01 Javascript
详解各版本React路由的跳转的方法
2018/05/10 Javascript
浅谈JavaScript面向对象--继承
2019/03/20 Javascript
详解基于React.js和Node.js的SSR实现方案
2019/03/21 Javascript
详解vue中使用axios对同一个接口连续请求导致返回数据混乱的问题
2019/11/06 Javascript
[02:30]辉夜杯主赛事第二日胜者组半决赛 CDEC.Y赛后采访
2015/12/26 DOTA
Python动态加载模块的3种方法
2014/11/22 Python
Python给你的头像加上圣诞帽
2018/01/04 Python
Python中的单下划线和双下划线使用场景详解
2019/09/09 Python
python 使用raw socket进行TCP SYN扫描实例
2020/05/05 Python
运动会班级口号
2014/06/09 职场文书
2014年小学重阳节活动策划方案
2014/09/16 职场文书
技能培训通讯稿
2015/07/18 职场文书
公务员学习中国梦心得体会
2016/01/05 职场文书
《开国大典》教学反思
2016/02/16 职场文书
如何计划开一家便利店?
2019/07/31 职场文书
关于vue-router-link选择样式设置
2022/04/30 Vue.js