在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
Dec 13 PHP
php生成随机密码的几种方法
Jan 17 PHP
PHP原生模板引擎 最简单的模板引擎
Apr 25 PHP
PHP设计模式之命令模式的深入解析
Jun 13 PHP
使用PHP生成二维码的两种方法(带logo图像)
Mar 14 PHP
thinkphp数据查询和遍历数组实例
Nov 28 PHP
php绘图之在图片上写中文和英文的方法
Jan 24 PHP
php版微信公众账号第三方管理工具开发简明教程
Sep 23 PHP
CI框架(ajax分页,全选,反选,不选,批量删除)完整代码详解
Nov 01 PHP
YII2自动登录Cookie总是失效的解决方法
Jun 28 PHP
laravel5.4利用163邮箱发送邮件的步骤详解
Sep 22 PHP
thinkphp5.1 框架钩子和行为用法实例分析
May 25 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
header()函数使用说明
2006/11/23 PHP
PHP 一个随机字符串生成代码
2010/05/26 PHP
php获取文件名称和扩展名的方法
2017/02/07 PHP
PHP的PDO大对象(LOBs)
2019/01/27 PHP
兼容所有浏览器的js复制插件Zero使用介绍
2014/03/19 Javascript
一种新的javascript对象创建方式Object.create()
2015/12/28 Javascript
AngularJS中实现动画效果的方法
2016/07/28 Javascript
js实现点击图片自动提交action的简单方法
2016/10/16 Javascript
node koa2实现上传图片并且同步上传到七牛云存储
2017/07/31 Javascript
js获取文件里面的所有文件名(实例)
2017/10/17 Javascript
AngularJS的$location使用方法详解
2017/10/19 Javascript
vue的一个分页组件的示例代码
2017/12/25 Javascript
JS 实现缓存算法的示例(FIFO/LRU)
2018/03/20 Javascript
微信小程序MUI侧滑导航菜单示例(Popup弹出式,左侧不动,右侧滑动)
2019/01/23 Javascript
微信小程序全选多选效果实现代码解析
2020/01/21 Javascript
JS面向对象编程——ES6 中class的继承用法详解
2020/03/03 Javascript
openlayers实现图标拖动获取坐标
2020/09/25 Javascript
Python中的异常处理try/except/finally/raise用法分析
2019/02/28 Python
python opencv 二值化 计算白色像素点的实例
2019/07/03 Python
windows中安装Python3.8.0的实现方法
2019/11/19 Python
Keras中 ImageDataGenerator函数的参数用法
2020/07/03 Python
python中altair可视化库实例用法
2021/01/26 Python
css3实现针线缝合效果(图解步骤)
2013/02/04 HTML / CSS
css3实现冲击波效果的示例代码
2018/01/11 HTML / CSS
iRobot官网:改变生活的家用机器人品牌
2016/09/20 全球购物
施华洛世奇加拿大官网:SWAROVSKI加拿大
2018/06/03 全球购物
Martinelli官方商店:西班牙皮鞋和高跟鞋品牌
2019/07/30 全球购物
英国珠宝和手表专家:Pleasance & Harper
2020/10/21 全球购物
工程催款通知书
2015/04/17 职场文书
2015国庆节66周年标语
2015/07/30 职场文书
七年级数学教学反思
2016/02/17 职场文书
Python 流媒体播放器的实现(基于VLC)
2021/04/28 Python
如何解决.cuda()加载用时很长的问题
2021/05/24 Python
Python中的xlrd模块使用整理
2021/06/15 Python
Elasticsearch 批量操作
2022/04/19 Python
Apache POI操作批量导入MySQL数据库
2022/06/21 Servers