| 论坛注册| 加入收藏 | 设为首页| RSS
Google
您当前的位置:首页 > Linux频道 > Linux开发区 > WEB开发

Oop+模板编程初级示例

时间:2007-03-28 11:06:11  来源:Linux联盟收集整理  作者:
下面的文章是国际村上的。对于习惯于写面向过程的PHP程序员转向OOP很有帮助,就贴在这儿了。提供实例的教程文章很少,看过些文的希望你们将PHP OOP方面的资料共享下,非常感谢!
   

Oop+模板编程初级示例与类库下载 ivQLinux联盟
 ivQLinux联盟
作者: lwg888 来源:
http://www.phpx.com ivQLinux联盟
ivQLinux联盟

前言:ivQLinux联盟
对PHP,有很多人不赞成用OOP方式编程,反对使用模板者更众,我曾经也是极力排斥,但通过一段时间的尝试之后,发现OOP+模板虽然在速度上慢了可忽略不计的一点时间,编写起来确实爽,尤其表现在业务逻辑的处理与代码的维护性上。ivQLinux联盟
费话少说,下面我就谈谈我的一点学习心得,希望对初学者有所帮助,也希望高手指正。ivQLinux联盟
ivQLinux联盟
系统文件存储结构:ivQLinux联盟
先列出树形列表,再解释。ivQLinux联盟
ivQLinux联盟
├─ivQLinux联盟
│ index.phpivQLinux联盟
ivQLinux联盟
├─sources //子功能模块(业务逻辑)文件目录ivQLinux联盟
│   index.phpivQLinux联盟
│   list.phpivQLinux联盟
│   details.phpivQLinux联盟
.....ivQLinux联盟
│ ivQLinux联盟
├─template //模板文件目录ivQLinux联盟
│   index.tplivQLinux联盟
.....ivQLinux联盟
│ ivQLinux联盟
├─cache //缓存文件目录ivQLinux联盟
│   gfdgr5123f4sfd9rwfdyt543fdsf12gf.htmlivQLinux联盟
.....ivQLinux联盟
│ ivQLinux联盟
├─css //CSS 样式表文件目录ivQLinux联盟
│   style.cssivQLinux联盟
ivQLinux联盟
├─images //图片目录ivQLinux联盟
│   1.gifivQLinux联盟
│   .....ivQLinux联盟
│ ivQLinux联盟
├─include //包括目录ivQLinux联盟
│ │ config.inc.php //系统全局配置文件ivQLinux联盟
│ │ functions.inc.php //系统全局函数ivQLinux联盟
│ │ivQLinux联盟
│ ├─lib //系统基础类ivQLinux联盟
│ │  Application.inc.phpivQLinux联盟
│ │  .....ivQLinux联盟
│ │ivQLinux联盟
│ └─data //数据目录(IP文件)ivQLinux联盟
│ ip.dativQLinux联盟
│    .....ivQLinux联盟
ivQLinux联盟
├─js //JS文件目录ivQLinux联盟
│   checkForm.jsivQLinux联盟
│   .....ivQLinux联盟
ivQLinux联盟
├─admin //后台管理目录ivQLinux联盟
│ │ index.phpivQLinux联盟
│ │ivQLinux联盟
│ ├─sources //子功能模块(业务逻辑)文件目录ivQLinux联盟
│ │   index.phpivQLinux联盟
│ │   list.phpivQLinux联盟
│ │   update.phpivQLinux联盟
│ │ .....ivQLinux联盟
│ │ ivQLinux联盟
│ └─template //模板文件目录ivQLinux联盟
│     index.tplivQLinux联盟
│   .....ivQLinux联盟
ivQLinux联盟
└─tmp //上传临时目录ivQLinux联盟
ivQLinux联盟
ivQLinux联盟
主目录下的index.php,仅提供转向,转到sources目录下的index.php。同样admin下的index.php转向到admin/sources/index.php。你可以直接用header("location:sources/index.php"),也可以输出一段提示再转向,:正在进入,请稍候...<script>location.href="sources/index.php"</script>ivQLinux联盟
ivQLinux联盟
为什么要这样做呢?ivQLinux联盟
sources目录下的index.php是一个统一应用程序接口,通过接收$_GET或$_POST的action参数决定执行相应的子功能模块。例如index.php?action=list,即要执行list.php文件;index.php?action=insert即要执行insert.php文件。这样把应用程序接口index.php和其它子功能模块放在同一级目录,使得业务逻辑更方便;另外sources目录与模板文件目录template在同一级目录,使得模板文件被调用时,其中的图片等外部链接仍然有效,不会出现因目录级别不同找不到图片的现象。 ivQLinux联盟
 ivQLinux联盟
程序设计:ivQLinux联盟
首先,我们有一个统一的应用程序接口sources/index.php。我们看一下index.php的内容:ivQLinux联盟
ivQLinux联盟
[PHP]ivQLinux联盟
<?ivQLinux联盟
include (dirname(__FILE__)."/../include/lib/Application.inc.php");ivQLinux联盟
$app = new Application();ivQLinux联盟
$app->setRoot(dirname(__FILE__)) ;ivQLinux联盟
$app->setDefaultAction("main");ivQLinux联盟
$app->run();ivQLinux联盟
?>ivQLinux联盟
ivQLinux联盟
[/PHP] ivQLinux联盟
ivQLinux联盟
上面的代码很简单:ivQLinux联盟
第1行:载入应用程序接口类Application.inc.php。有很多朋友使用include和require时,在多级调用后经常出现找不到文件的问题,如果象上面那样:绝对路径+相对路径,包你永远正确。扯远了。。。^_^ivQLinux联盟
第4行:$app->setRoot(dirname(__FILE__)) ;设置子功能模块根目录。由于index.php与子功能模块文件在同一目录,因此设为dirname(__FILE__)ivQLinux联盟
第5行:$app->setDefaultAction("main");设置默认子功能模块,即没有$_GET['action']和$_POST['action']时执行main.php。ivQLinux联盟
很重要的在第六行$app->run(),开始执行子功能模块。ivQLinux联盟
ivQLinux联盟
下面就来看下Application.inc.php中run()是如何运作:ivQLinux联盟
代码如下:ivQLinux联盟
ivQLinux联盟
[PHP]ivQLinux联盟
<?ivQLinux联盟
function run()ivQLinux联盟
{ivQLinux联盟
$action = $this->getAction();ivQLinux联盟
$page_class_file = $this->root . $action . '.php';ivQLinux联盟
include_once($page_class_file);ivQLinux联盟
$page = & new CPage($this);ivQLinux联盟
$page->execute();ivQLinux联盟
exit ();ivQLinux联盟
}ivQLinux联盟
?>ivQLinux联盟
[/PHP] ivQLinux联盟
ivQLinux联盟
首先我们通过getAction()得到参数action的值,ivQLinux联盟
比如list,当前路径+list+.php就是将要执行的子模块ivQLinux联盟
include_once($page_class_file); 载入list.phpivQLinux联盟
很显然,在list.php中有一个类CPage ,并有一个方法函数execute()作为接口来处理数据并显示该页。ivQLinux联盟
在初始化CPage类时,我们将$app对象用$this作为参数传给了CPage,那么在CPage中就可以使用$app对象中封装的所有方法。因此我们可以在$app中封装多一些的常用方法。比如,可以将数据库的初始化,模板的初始化封装进去。ivQLinux联盟
完整代码如下:ivQLinux联盟
Application.inc.phpivQLinux联盟
[PHP]ivQLinux联盟
<?phpivQLinux联盟
if(!defined("__CLASS_APPLICATION__"))ivQLinux联盟
{ivQLinux联盟
define("__CLASS_APPLICATION__",1);ivQLinux联盟
ivQLinux联盟
require(dirname(__FILE__)."/PhpClass.inc.php");ivQLinux联盟
ivQLinux联盟
ivQLinux联盟
class Application extends PhpClassivQLinux联盟
{ivQLinux联盟
var $db = null;ivQLinux联盟
var $defaultAction ;ivQLinux联盟
var $root;ivQLinux联盟
ivQLinux联盟
//构造函数ivQLinux联盟
ivQLinux联盟
function Application($root='')ivQLinux联盟
{ivQLinux联盟
if (!defined(ACTIONSTR))define("ACTIONSTR","action");ivQLinux联盟
if (!empty($root))$this->setRoot($root);ivQLinux联盟
}ivQLinux联盟
ivQLinux联盟
//设置子功能模块所在的根目录ivQLinux联盟
ivQLinux联盟
function setRoot($root='')ivQLinux联盟
{ivQLinux联盟
if (empty($root))$root = dirname($_SERVER['SCRIPT_FILENAME']);ivQLinux联盟
if (!is_dir($root)) return $this->catchErr("无效的路径");ivQLinux联盟
if ( substr($root,-1) != DIRECTORY_SEPARATOR) $root .= DIRECTORY_SEPARATOR;ivQLinux联盟
$this->root = $root;ivQLinux联盟
}ivQLinux联盟
ivQLinux联盟
//设置默认要执行的功能页ivQLinux联盟
ivQLinux联盟
function setDefaultAction($name)ivQLinux联盟
{ivQLinux联盟
$this->defaultAction = $name;ivQLinux联盟
}ivQLinux联盟
ivQLinux联盟
//执行子功能页ivQLinux联盟
ivQLinux联盟
function run()ivQLinux联盟
{ivQLinux联盟
$action = $this->getAction();ivQLinux联盟
$page_class_file = $this->root . $action . '.php';ivQLinux联盟
include_once($page_class_file);ivQLinux联盟
$page = & new CPage($this);ivQLinux联盟
$page->execute();ivQLinux联盟
exit ();ivQLinux联盟
}ivQLinux联盟
ivQLinux联盟
//获取参数action的值ivQLinux联盟
ivQLinux联盟
function getAction()ivQLinux联盟
{ivQLinux联盟
$_name = (isset($_POST[ACTIONSTR])) ? $_POST[ACTIONSTR] : $_GET[ACTIONSTR];ivQLinux联盟
if (empty($_name)) $_name = $this->defaultAction;ivQLinux联盟
return $_name;ivQLinux联盟
}ivQLinux联盟
ivQLinux联盟
//模板ivQLinux联盟
ivQLinux联盟
function tpl($templateDir='') {ivQLinux联盟
$this->includeClass('Vant');ivQLinux联盟
if (empty($templateDir)) $templateDir = $this->root . 'templates/'ivQLinux联盟
$tpl = & new Vant($templateDir);ivQLinux联盟
return $tpl;ivQLinux联盟
}ivQLinux联盟
ivQLinux联盟
//载入类文件ivQLinux联盟
ivQLinux联盟
function includeClass ($fileName, $path = '', $lastName = '.inc.php')ivQLinux联盟
{ivQLinux联盟
if ( substr($path,0,1) != DIRECTORY_SEPARATOR) $path = DIRECTORY_SEPARATOR . $path;ivQLinux联盟
if ( substr($path,0,-1) != DIRECTORY_SEPARATOR) $path .= DIRECTORY_SEPARATOR;ivQLinux联盟
if (empty($fileName) ) return $this->catchErr("无效的class名");ivQLinux联盟
ivQLinux联盟
include(dirname(__FILE__) . $path . $fileName . $lastName);ivQLinux联盟
}ivQLinux联盟
ivQLinux联盟
//数据库连接ivQLinux联盟
ivQLinux联盟
function connectDb($host='',$username='',$password='',$database='')ivQLinux联盟
{ivQLinux联盟
$this->includeClass('DB');ivQLinux联盟
ivQLinux联盟
$db = new DB($host,$username,password,database);ivQLinux联盟
$db->connect();ivQLinux联盟
$this->db = & $db;ivQLinux联盟
return $db;ivQLinux联盟
}ivQLinux联盟
ivQLinux联盟
}
//end classivQLinux联盟
ivQLinux联盟
ivQLinux联盟
}
//end if definedivQLinux联盟
ivQLinux联盟
ivQLinux联盟
?>ivQLinux联盟
ivQLinux联盟
[/PHP] ivQLinux联盟
作者: lwg888 发布日期: 2004-7-02 ivQLinux联盟
上面的代码中有一个方法includeClass(),专门用来包含类与函数等文件,注意,请不要用它来包含配置文件、普通PHP文件等。ivQLinux联盟
Application类还继承了PhpClass类。PhpClass类里面是些什么东些呢?在我所有的类库中,基本上每个类中都要用到一些相同的方法与属性,比如错处理catchErr()等,将它们封装起来,作为所有类的祖类。ivQLinux联盟
PhpClass的完整代码如下:ivQLinux联盟
PhpClass.inc.phpivQLinux联盟
[PHP]ivQLinux联盟
<?phpivQLinux联盟
ivQLinux联盟
if(!defined("__CLASS_PHPCLASS__"))ivQLinux联盟
{ivQLinux联盟
define("__CLASS_PHPCLASS__",1);ivQLinux联盟
ivQLinux联盟
ivQLinux联盟
class PhpClass{ivQLinux联盟
ivQLinux联盟
var $debug = false;
//是否显示调式信息ivQLinux联盟
ivQLinux联盟
var $debugMsg = '';
//记录调式信息ivQLinux联盟
ivQLinux联盟
var $errMsg = '';
//记录第一次的错误信息ivQLinux联盟
ivQLinux联盟
var $error_report = true;
//是否输出错误信息ivQLinux联盟
ivQLinux联盟
var $error_halt = true;
//出错后是否停止执行ivQLinux联盟
ivQLinux联盟
ivQLinux联盟
//为成员变量赋值ivQLinux联盟
ivQLinux联盟
function setVal($name,$value)ivQLinux联盟
{ivQLinux联盟
$this->$name = $value;ivQLinux联盟
}ivQLinux联盟
ivQLinux联盟
//取得成员变量的值ivQLinux联盟
ivQLinux联盟
function getVal($name)ivQLinux联盟
{ivQLinux联盟
return $this->$name;ivQLinux联盟
}ivQLinux联盟
ivQLinux联盟
//捕获错误ivQLinux联盟
ivQLinux联盟
function catchErr($msg)ivQLinux联盟
{ivQLinux联盟
if(empty($this->errMsg)) $this->errMsg = $msg;ivQLinux联盟
ivQLinux联盟
if ($this->error_report) echo $this->errMsg;ivQLinux联盟
ivQLinux联盟
if ($this->error_halt) exit;ivQLinux联盟
ivQLinux联盟
return false;ivQLinux联盟
}ivQLinux联盟
ivQLinux联盟
//输出错误ivQLinux联盟
ivQLinux联盟
function err($exit = false)ivQLinux联盟
{ivQLinux联盟
if (!empty($this->errMsg))ivQLinux联盟
{ivQLinux联盟
echo $this->errMsg;ivQLinux联盟
if ($exit) exit;ivQLinux联盟
}ivQLinux联盟
}ivQLinux联盟
ivQLinux联盟
}
// end classivQLinux联盟
ivQLinux联盟
ivQLinux联盟
}
// end if definedivQLinux联盟
ivQLinux联盟
?>ivQLinux联盟
[/PHP] ivQLinux联盟
ivQLinux联盟
下面我们回到list.php中去,看子功能模块如何运作ivQLinux联盟
从前面的介绍我们知道了list.php,必有一个类CPage且其中必定有两个函数:ivQLinux联盟
一个构造函数CPage(),一个execute()ivQLinux联盟
通过构造函数的参数将$app对象接收到,那么简单代码如下:ivQLinux联盟
ivQLinux联盟
[PHP]ivQLinux联盟
list.phpivQLinux联盟
<?phpivQLinux联盟
class CPageivQLinux联盟
{ivQLinux联盟
function CPage(& $app)
//$app就是Application对象的实例ivQLinux联盟
ivQLinux联盟
{ivQLinux联盟
}ivQLinux联盟
ivQLinux联盟
function execute()ivQLinux联盟
{ivQLinux联盟
}ivQLinux联盟
}ivQLinux联盟
?>ivQLinux联盟
[/PHP] ivQLinux联盟
ivQLinux联盟
由于很多子功能模块可能要完成一些共同的功能,如显示logo,copyright等,我们可以将这样共同的功能封装在一个类中,命名为Page类,作为所有子功能模块的父类,所有子功能模块都从它继承。ivQLinux联盟
看一下Page.inc.php:ivQLinux联盟
ivQLinux联盟
[PHP]ivQLinux联盟
<?ivQLinux联盟
class PageivQLinux联盟
{ivQLinux联盟
var $app;ivQLinux联盟
var $vars=array();ivQLinux联盟
ivQLinux联盟
function Page(&$app)ivQLinux联盟
{ivQLinux联盟
$this->app = & $app;ivQLinux联盟
}ivQLinux联盟
function setCopyRight()ivQLinux联盟
{ivQLinux联盟
$this->vars['copyright'] = "CopyRightwg888";ivQLinux联盟
}ivQLinux联盟
}ivQLinux联盟
?>ivQLinux联盟
[/PHP] ivQLinux联盟
ivQLinux联盟
list.php中的CPage类就从Page类继承ivQLinux联盟
代码示例:ivQLinux联盟
ivQLinux联盟
[PHP]ivQLinux联盟
<?phpivQLinux联盟
include("Page.inc.php");ivQLinux联盟
ivQLinux联盟
class CPage extends PageivQLinux联盟
{ivQLinux联盟
var $pt;ivQLinux联盟
var $app;ivQLinux联盟
ivQLinux联盟
function CPage(& $app)ivQLinux联盟
{ivQLinux联盟
$this->age($app);ivQLinux联盟
}ivQLinux联盟
ivQLinux联盟
function execute()ivQLinux联盟
{ivQLinux联盟
$db = $this->app->connectDb();
//利用Application对象中的数据库连接方法ivQLinux联盟
ivQLinux联盟
$sql= "select * from table ...";ivQLinux联盟
$this->app->includeClass ('PageTurn');
//载入PageTurn.inc.php翻页类文件ivQLinux联盟
ivQLinux联盟
$pt = & new PageTurn(20);
//初始化翻页类,每页显示20条ivQLinux联盟
ivQLinux联盟
$pt->query($sql,$db->conn);
//执行SQL语句ivQLinux联盟
ivQLinux联盟
$this->pt = & $pt;ivQLinux联盟
$this->show();
//显示网页ivQLinux联盟
ivQLinux联盟
}ivQLinux联盟
ivQLinux联盟
function show()ivQLinux联盟
{ivQLinux联盟
$tpl=$this->app->tpl();
//建立模板对象ivQLinux联盟
ivQLinux联盟
$tpl->set("loop",$this->pt->field);ivQLinux联盟
$tpl->set("copyright",$this->vars['copyright']);
//Page类中的 $vars['copyright']ivQLinux联盟
ivQLinux联盟
echo $tpl->parse('list.tpl');
//显示模板ivQLinux联盟
ivQLinux联盟
}ivQLinux联盟
}ivQLinux联盟
?>ivQLinux联盟
ivQLinux联盟
[/PHP] ivQLinux联盟
ivQLinux联盟
上面用到了分页类PageTurn与模板类Vant,大家可以参考下载中的相关类ivQLinux联盟
ivQLinux联盟
讲了这么多,我们已经基本上弄清了用OOP+模板方式写程式的方法,下面就来总结它的好与歹。ivQLinux联盟
如果你不喜欢用OOP方式编程,你可以说:类=累。我同意,但不以OOP方式编程,运行速度是会快一些,而你会变的很累,不管是业务逻辑的组织还是今后代码的维护,都不是一件轻松的事。在机器性能日益提高和网络宽频日益普及的今天,速度不是单方面追求的目标,我们要在速度与代码易用性、易编写性之间取得平衡。ivQLinux联盟
ivQLinux联盟
从上面的讲解我们可以看出:完全实现了Model模型/逻辑、View视图/界面、Controller控制/流程 的分离。使得结构非常清晰,维护非常方便,模型设计者,界面设计者与流程控制设计者能更好的分工与合作。代码可重用,今后如果要开发一个新的项目,很快就能完成,因为你可能只需叫美工重新设计一下模板,或者稍稍修改一下子功能模块。ivQLinux联盟
ivQLinux联盟
还有一点不得不提:ivQLinux联盟
index.php是一个统一应用程序接口,通过$_GRT['action']或$_POST['action'],决定执行哪个子功能模块。当它执行该模块时是将它include进来,因此所有的操作都是在index.php中进行,所呈现的网页都是index.php?action=...,这样使我们控制流程非常方便。比如要显示用户列表,只需调用list.tpl模板,要显示错误信息,只需调用errmsg.tpl模板,甚至不必要使用header("location:..")来转向,不管是显示用户列表还是显示错误信息,所有的$_GRT或$_POST或其它变量都还在,不用象转向时那样用?xx=...传一大堆变量过去,不是有不少人常问“数组能不能传递?”“对象能不能传递?”,ivQLinux联盟
ivQLinux联盟
写到这里,一点劣见,望大家指正 。
ivQLinux联盟

来顶一下
近回首页
返回首页
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
相关文章
栏目更新
栏目热门