在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 相关文章推荐
NOT NULL 和NULL
Jan 15 PHP
php中文字符截取防乱码
Mar 28 PHP
php 分库分表hash算法
Nov 12 PHP
PHP判断文件是否存在、是否可读、目录是否存在的代码
Oct 03 PHP
用Php编写注册后Email激活验证的实例代码
Mar 11 PHP
php unset全局变量运用问题的深入解析
Jun 17 PHP
分享一个php 的异常处理程序
Jun 22 PHP
php字符串截取函数用法分析
Nov 25 PHP
php验证码生成代码
Nov 11 PHP
DEDE实现转跳属性文档在模板上调用出转跳地址
Nov 04 PHP
php 调用ffmpeg获取视频信息的简单实现
Apr 03 PHP
使用git迁移Laravel项目至新开发环境的步骤详解
Apr 06 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安装为Apache DSO
2006/10/09 PHP
深入php中var_dump方法的使用详解
2013/06/24 PHP
php另类上传图片的方法(PHP用Socket上传图片)
2013/10/30 PHP
PHP通过API获取手机号码归属地
2015/05/28 PHP
php mysql 封装类实例代码
2016/09/18 PHP
鼠标经过的文本框textbox变色
2009/05/21 Javascript
javascript 可以拖动的DIV(二)
2009/06/26 Javascript
js中关于new Object时传参的一些细节分析
2011/03/13 Javascript
jQuery判断密码强度实现思路及代码
2013/04/24 Javascript
Javascript WebSocket使用实例介绍(简明入门教程)
2014/04/16 Javascript
4种JavaScript实现简单tab选项卡切换的方法
2016/01/06 Javascript
jQuery实现鼠标跟随提示层效果代码(可显示文本,Div,Table,Html等)
2016/04/18 Javascript
js实现精确到秒的倒计时效果
2016/05/29 Javascript
Node.js的文件权限及读写flag详解
2016/10/11 Javascript
React复制到剪贴板的示例代码
2017/08/22 Javascript
详解基于vue-router的动态权限控制实现方案
2017/09/28 Javascript
vue-cli开发环境实现跨域请求的方法
2018/04/07 Javascript
vue自动化表单实例分析
2018/05/06 Javascript
利用d3.js制作连线动画图与编辑器的方法实例
2019/09/05 Javascript
[00:37]DOTA2上海特级锦标赛 OG战队宣传片
2016/03/03 DOTA
[50:02]完美世界DOTA2联赛PWL S2 Magma vs FTD 第三场 11.29
2020/12/03 DOTA
Python3通过Luhn算法快速验证信用卡卡号的方法
2015/05/14 Python
详解python进行mp3格式判断
2016/12/23 Python
Python函数基础实例详解【函数嵌套,命名空间,函数对象,闭包函数等】
2019/03/30 Python
PyQt5组件读取参数的实例
2019/06/25 Python
linux 下selenium chrome使用详解
2020/04/02 Python
如何理解transaction事务的概念
2015/05/27 面试题
银行会计财务工作个人的自我评价
2013/10/29 职场文书
母亲追悼会答谢词
2014/01/27 职场文书
不打扫卫生检讨书
2014/02/12 职场文书
环境整治工作方案
2014/05/18 职场文书
党员一帮一活动总结
2014/07/08 职场文书
关键在于落实心得体会
2014/09/03 职场文书
小学教师自我剖析材料
2014/09/29 职场文书
建国大业观后感600字
2015/06/01 职场文书
Android 中的类文件和类加载器详情
2022/06/05 Java/Android