在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语法(4)
Oct 09 PHP
php IP及IP段进行访问限制的代码
Dec 17 PHP
PHP JSON格式数据交互实例代码详解
Jan 13 PHP
PHP中获取文件扩展名的N种方法小结
Feb 27 PHP
解析php5配置使用pdo
Jul 03 PHP
析构函数与php的垃圾回收机制详解
Oct 28 PHP
php中stream(流)的用法
Mar 25 PHP
php创建和删除目录函数介绍和递归删除目录函数分享
Nov 18 PHP
YII使用url组件美化管理的方法
Dec 28 PHP
PHPCMS V9 添加二级导航的思路详解
Oct 20 PHP
PHP实现二维数组中的查找算法小结
Jun 09 PHP
基于laravel缓冲cache的用法详解
Oct 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
利用static实现表格的颜色隔行显示
2006/10/09 PHP
PHP 过滤页面中的BOM(实现代码)
2013/06/29 PHP
php批量转换文件夹下所有文件编码的函数类
2017/08/06 PHP
PHPMailer ThinkPHP实现自动发送邮件功能
2018/06/10 PHP
PHP实现的用户注册表单验证功能简单示例
2019/02/25 PHP
关于PHP5.6+版本“No input file specified”问题的解决
2019/12/11 PHP
PHP如何防止用户重复提交表单
2020/12/09 PHP
js可突破windows弹退效果代码
2008/08/09 Javascript
Dom 结点创建 基础知识
2011/10/01 Javascript
jquery访问ashx文件示例代码
2014/08/11 Javascript
JS限制文本框只能输入数字和字母方法
2015/02/28 Javascript
javascript动态添加checkbox复选框的方法
2015/12/23 Javascript
JavaScript动态检验密码强度的实现方法
2016/11/09 Javascript
AngularJS入门教程之Helloworld示例
2016/12/25 Javascript
关于Javascript中document.cookie的使用
2017/03/08 Javascript
VueJS 集成 Medium Editor的示例代码 (自定义编辑器按钮)
2017/08/24 Javascript
表格展示利器 Bootstrap Table实例代码
2017/09/06 Javascript
vue左侧菜单,树形图递归实现代码
2018/08/24 Javascript
Nodejs把接收图片base64格式保存为文件存储到服务器上
2018/09/26 NodeJs
vue中axios实现数据交互与跨域问题
2019/05/12 Javascript
[02:07]DOTA2新英雄展现中国元素,完美“圣典”亮相央视
2016/12/19 DOTA
[01:03:50]DOTA2-DPC中国联赛 正赛 CDEC vs DLG BO3 第二场 2月7日
2021/03/11 DOTA
基于Python 装饰器装饰类中的方法实例
2018/04/21 Python
python logging模块的使用总结
2019/07/09 Python
Python3 文章标题关键字提取的例子
2019/08/26 Python
python中取绝对值简单方法总结
2020/07/24 Python
基于python模拟bfs和dfs代码实例
2020/11/19 Python
介绍一下UNIX启动过程
2013/11/14 面试题
新闻专业个人自我评价
2013/09/21 职场文书
计算机毕业大学生推荐信
2013/12/01 职场文书
2014年高三毕业生自我评价
2014/01/11 职场文书
自动化毕业生专业自荐书范文
2014/02/04 职场文书
群众路线教育实践活动心得体会
2014/03/07 职场文书
党员批评与自我批评思想汇报(集锦)
2014/09/14 职场文书
大国崛起日本观后感
2015/06/02 职场文书
安全教育第一课观后感
2015/06/17 职场文书