分享
 
 
 

一种PHP设计模式:DPT

王朝php·作者佚名  2006-11-24
窄屏简体版  字體: |||超大  

一、DPT介绍

PHP为什么在主流的应用中总是那么不出色,总是不如.Net/Java,就是因为在PHP处理大型应用的时候,那些不完整的面向对象机制、数据库处理的单一,不通用性等等,影响了PHP做大型应用。那么,如何来改变这个状况呢?当然就是需要引进一些新的设计方法,把PHP中不健全的面向对象机制完整起来,进行更好的PHP大中型应用的开发。

从Java过来的MVC模式非常流行,而且已经有部分已经引伸进了PHP领域,设计模式的引进,就是为了更好的控制项目开发。今天我要说一种设计模式,类似于MVC,它叫DPT模式。其实有时候我也觉得有点象Java里面的DAO(Data Access Object),不过DAO是夹在业务逻辑层和数据库资源层之间的,而DPT更多的是把业务逻辑也封装在类里,和DAO层在相同的内容中。

D - Data,数据收集层

P - Php,PHP数据调用层

T - Template,模板层

首先,我们要对它进行简单的了解。

Data,就是我们的数据层,它不是数据库抽象类,而是通过数据库接口,执行一些SQL,把数据获取的过程,一般把这种操作封装在类里面,就形成了我们的数据收集层。

Php,就是对我们收集的数据进行整理,规划,同时解析模板进行数据的显示。

Template,模板层,就是我们的HTML页,里面不包含任何PHP代码,只有模板标签的内容,通过它来控制数据在页面中有格式的显示。

我们这里三层中,每一层都是鼓励由一个人来开发,然后通过PHPDoc之类的工具,把源代码中的API生成文档,由P层的人进行调用。

那么,在实际的项目开发中,它是怎么运作的呢,我们又如何把这种设计模式引进我们的项目中呢?

我们下面将运用一个实际的项目来讲解DPT模式。阅读一下内容必须具备基本的PHP4的面向对象编程、数据库抽象类、模板等知识。

我们目前为了加速PHP的开发,都使用PHP封装了部分功能,比如数据库操作抽象类,模板类等等,这些都是为了开发复杂应用而应运而生的。目前比较主流的数据库抽象类有phplib db、PEAR::DB、ADODB等等,模板处理类有phplib template、smartTemplate、Smarty等等。本文中都是使用PHP Group推荐的产品,数据口抽象类使用PEAR::DB,模板处理类使用Smarty,如果对这两个类库不熟悉的读者,请参考文章后面的链接。

二、项目体系结构

下面我们来构建我们基于DPT模式的PHP应用。(以下部分内容参考《MVC模式、类封装还是黑客代码》)

文件目录结构(只涉及到关键的目录)

class 类库,包含所有的数据收集层

template 模板文件存放目录

include 常用库,包括PEAR、Smarty等类库,同时还有自己定义的基本函数

config.inc.php 基本配置文件,包括数据库配置,其他基本信息配置

security.inc.php 安全处理页,主要多传递的变量进行处理

init.inc.php

error.php 错误处理页

class目录中存放了我们数据收集层中的内容,一般的建议是每个类文件只是针对一个表进行操作,比如cmsMessage.class.php,那么这个类就是属于功能CMS里面的,只负责操作Message这个表。所有的数据库交互和操作都是封装在类里的,在P层不允许出现任何直接操作数据库的语句。

template目录中存放了我们的网页模板,模板中都是使用Smarty标签进行排列的,同时,在模板中,都是建议使用JS+CSS来控制页面,模板中只有DIV标签来简单的排版,这样,非常利于网站改版和更换皮肤。

include目录就是对常用文件的包含,比如PEAR::DB类、Smarty类库文件等。config.inc.php就是基本的配置文件,包括数据库、基本常量等等,security.inc.php是安全处理页,我们这里主要是做一个变量的安全检查,下面内容我们将仔细介绍。init.inc.php是一个初始化操作的页面,包括初始化数据库链接,实例化模板处理类等等操作,error.php是错误信息处理页,所有的错误信息通过URL编码后转到该页。

三、项目基本配置代码

关键页代码实例:

/**

* config.inc.php

* 配置文件

*/

/* 数据库配置 */

define('DB_HOST', 'localhost'); //数据库主机

define('DB_USER', 'root'); //数据库链接用户

define('DB_PASS', ''); //连接密码

define('DB_NAME', 'cms'); //默认数据库

define('DB_PORT', '3306'); //数据库端口

define('DB_TYPE', 'mysql'); //数据库类型

define('DB_OPT', '1'); //是否长期链接

/* 模板信息配置 */

define('TPL_TEMPLATE_DIR', './template/'); //模板目录

define('TPL_COMPILE_DIR', './template/templates_c/'); //模板编译目录

define('TPL_CONFIGS_DIR', './template/configs/'); //模板配置文件目录

define('TPL_CACHE_DIR', './template/cache/'); //模板缓存目录

define('TPL_LIFTTIME', '1'); //缓存时间

define('TPL_CACHEING', 'true'); //是否缓存

define('TPL_LEFT_DELIMITER', '{'); //左边界符

define('TPL_RIGHT_DELIMITER', '}'); //右边界符

/* 网站路径配置 */

define('ROOT_PATH', dirname(__FILE__)); //网站所在根目录

define('URL_PATH', dirname($_SERVER[PHP_SELF])); //网站URL地址路径

define('DB_PATH', ROOT_PATH.'/include/db'); //PEAR::DB目录

define('TPL_PATH', ROOT_PATH.'/include/smarty'); //Smarty目录

/**

* security.inc.php

* 安全过滤文件

*/

/* 过滤规则 */

$arr_filtrate = array("'", '"', "\");

/* 过滤函数 */

function var_filtrate($var)

{

global $arr_filtrate;

foreach ($arr_filtrate as $value)

{

if (eregi($var, $value)) {

return true;

}

return false;

}

}

/* 获取不同版本下的GET和POST数组 */

if (phpversion() < '4.1.0') {

$get = &$HTTP_GET_VARS;

$post = &$HTTP_POST_VARS;

} else {

$get = &$_GET;

$post = &$_POST;

}

/* 检查GET变量 */

if (count($get)) {

foreach ($post as $get_var) {

if (var_filtrate($get_var)) {

exit('Commit get parameter falsity');

}

}

}

/* 检查POST变量 */

if (count($post)) {

foreach ($post as $post_var) {

if (var_filtrate($post_var)) {

exit('Commit post parameter falsity');

}

}

}

其实,以上过滤的方法也不是最好的,建议参考我的另两篇防注入文章获取更好的方法,链接参考附录。

/**

* error.php

* 错误处理页面

*/

if (!isset($get[msg])) {

exit('Not commit parameter');

}

echo "Error Message: ". $get[msg];

echo "<p><a href='javascript:history.back()'>返回上一页</a>";

就是一些错误处理的作用,一般出的GET方式传递过来的消息都是经过urlencode()过的字符。

/*

* init.inc.php

* 初始化程序

*/

require_once(dirname(__FILE__).'config.inc.php');

require_once(ROOT_PATH.'security.inc.php');

require_once(DB_PATH.'DB.php');

require_once(TPL_PATH.'Smarty.class.php');

/* 初始化数据库链接 */

$db = DB::connect("DB_TYPE://DB_USER@DB_PASS:DB_HOST/DB_NAME", DB_OPT);

if (DB::isErro($db)) {

return $dg->getMessage();

}

$tpl = &new Smarty();

/* 初始化模板 */

$tpl->templates_dir = TPL_TEMPLATE_DIR;

$tpl->compile_dir = TPL_COMPILE_DIR;

$tpl->cache_dir = TPL_CACHE_DIR;

$tpl->configs = TPL_CONFIGS_DIR;

$tpl->lifetime = TPL_LIFTTIME;

$tpl->caching = TPL_CACHEING;

$tpl->left_delimiter = TPL_LEFT_DELIMITER;

$tpl->right_delimiter = TPL_RIGHT_DELIMITER;

基本文件描述完毕。代码写了不少,只是为了更好的理解这个模式。

四、框架实际开发

说明:我们以下项目代码都是以cms数据库中topic表做例子,代码只是为了演示框架结构,没有对代码进行测试,不保证能够正常运行。

topic的表结构:

CREATE TABLE `topic` (

`id` int(11) NOT NULL auto_increment,

`title` varchar(255) NOT NULL default '',

`addtime` int(11) default NULL,

`author` varchar(50) default NULL,

`type` int(11) default NULL,

`option` int(11) default NULL,

PRIMARY KEY (`id`),

KEY `id` (`id`)

);

(一)Data层:数据采集层

Data层主要就是针对数据库的所有操作都封装起来,然后通过接口的形式提供给Php层进行调用,同时在Data层里也封装了一些原始的数据库操作(类似于Java中的DAO)。一般Data层都是类的形式,保存在我们上面的 /class目录下,一般的准则是一个类文件操作一个数据表,就是说不管具体的业务逻辑如何,所有的数据表操作都是封装在一个类文件里的。比如说我们有一个数据表叫做topic,那么我们对应操作的类文件就是:topic.class.php。其实这里是可以做扩展的,比如说,我们的项目非常庞大,有很多内容,比如包括有CMS、Blog、BBS等等,那么我们就必须给每一个栏目分配一个数据库,那么针对当前操作数据库的话,就使用类中封装的链接方法进行链接,就可以抛弃我们上面init.inc.php中初始化的操作,而操作在类里面进行的链接。

假设我们目前操作的栏目是CMS系统,数据库名叫做cms,那么我们下面构造一个操作cms数据库里面的topic表的类来。

/**

* cms_topic.class.php

* 文章处理类

*/

class cmsTopic

{

var cmsDBName; //数据库名

var cTableName; //当前操作的表名

var cDsn; //数据链接源

var cDebug; //是否打开调试,1为是,0为否

var cDbPointer //链接资源

var cfetchMode //获取数据库资料的方式

var cEncode //数据库中数据保存的编码格式,默认是UTF-8

/* 构造函数 */

function cmsTopic()

{

//配置信息从config.inc.php中设置

$this->cfetchMode = DB_FETCHMODE_DEFAULT;

$this->cTableName = "topic";

$this->cDsn = "mysql://".

DB_USER.":".

DB_PASS."@".

DB_HOST."/".

[1] [2] [3] 下一页

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有