http://bbs.php.cn/thread-25165-1-1.html
FleaPHP 开发基础 - 第一部分
一、开始前的准备工作
为了避免各种不同开发环境配置对学习 FleaPHP 造成的干扰,因此建议你按照本文配置一个专门用于学习 FleaPHP 的开发环境。
二、FleaPHP 中的 MVC 模式
理解 FleaPHP 中,MVC 模式是如何实现的,以及其特点,可以帮助你更好的运用 FleaPHP。
简单来说,设计模式(Pattern)就是解决某一类问题的特定方法。由于这种特定方法在解决同类问题时具有通用性,所以我们就可以一次又一次的利用已有的经验。具体到程序编写上,就是我们可以用类似的程序结构和代码解决同类型的问题。有关设计模式的详细内容,可以阅读经典著作《设计模式》,这里我就不班门弄斧了。
MVC 实际上是一系列略有不同的模式。FleaPHP 采用的是Passive(被动)MVC 模式。
在 Passive MVC 模式中,Model(模型)完全不知道自己身处于 MVC 结构之中。换句话说,Model 就是一个普通的对象,与 MVC 模式里面的其他组成部分完全没有关联。具体而言,MVC 模式涉及到下列三类对象:
M 代表 Model,即模型,用于封装与业务逻辑有关的代码和数据。例如对订单的各种计算。
V 代表 View,即视图,用于呈现内容给用户(也就是将程序运行的结果返回给浏览器显示)。例如商品列表页面、后台登录页面。
C 代表 Controller,即控制器,用于接收用户输入(通过浏览器发起的请求),然后调用模型(Model)对输入数据进行处理并获得处理结果。最后将结果传递到视图(View),从而让用户能够看到自己操作的结果。例如用户点击删除文章按钮后,控制器调用操作文章的模型,删除掉指定文章,最后通过视图显示成功删除文章的提示信息。
经过这样简单的分离,我们就把应用程序操作数据的代码(绝大部分 Web 应用程序都是对数据进行操作)和处理用户输入输出的代码分离开来了。
这种分离有许多好处:
清晰的将应用程序分隔为独立的部分;
业务逻辑代码能够很方便的在多处重复使用;
方便开发人员分工协作;
如果需要,可以方便开发人员对应用程序各个部分的代码进行测试。
如果你上面的文字让你觉得很无聊或者不够严谨,那么说明你已经很熟悉 MVC 模式了。如果你看到上面的文字感到无所适从,那说明你还需要多阅读一些面向对象相关的书籍和文档。
应用程序执行流程下面的插图描述了基于 FleaPHP 应用程序的执行流程。
index.php 是应用程序的入口文件,负责定义一些应用程序必须的常量,并载入 FleaPHP 框架,然后执行 run() 函数;
过滤器链完成 HTTP 请求数据解析、MagicQuotes 处理等工作;
应用程序控制根据 HTTP 请求,调用领域逻辑、表数据入口、组件等,并将处理结果传送到视图/模板;
视图/模板根据应用程序控制器提供的数据生成输出内容并传送到浏览器。
在 FleaPHP 中,index.php 里面的 run() 在调用过滤器链后,会运行一个调度器。该调度器根据 HTTP 请求参数决定要调用的应用程序控制器。例如 index.php?controller=blog&action=list 这个请求表示要调用名为 blog 的应用程序控制器的 list 动作。然后调度器会调用这个控制器的动作。
在 FleaPHP 应用程序中,控制器实现为一个类,控制器动作就是该类的一个方法。
在控制器(MVC 模式中的 Controller)方法中,通过调用领域逻辑代码(MVC 模式中的 Model)来处理 HTTP 请求提交的数据并获得结果。然后再将结果传递给视图(MVC 模式中的 View)。视图根据控制器方法提供的参数从模板文件构造最终的页面内容,并返回给浏览器。
三、应用程序入口
与许多开发框架一样,FleaPHP 通常也使用一个入口文件来启动框架,并运行应用程序代码。虽然 FleaPHP 并不要求应用程序必须使用单一的入口文件,不过在本系列文章中,我大部分时间都使用单一入口文件。
单一入口应用程序在 FleaPHP 应用程序使用 MVC 模式时,应用程序的所有功能都通过一个单一的文件来调用。这种通过单一文件来执行所有功能的应用程序,称为单一入口应用程序。有关单一入口应用程序的一些信息,可以参考 ChinaUnix 上的一篇帖子。
许多著名的 PHP 应用程序都是单一入口,例如 Drupal、WordPress、XOOPS、Mambo 等。当然也有 phpMyAdmin 这样的非单一入口应用程序。
创建入口文件现在,我们来创建一个最简单的入口文件。打开文本编辑器,创建 htdocs/index.php 文件,内容如下:
<?phprequire('FLEA/FLEA.php');FLEA::runMVC();现在启动浏览器,输入地址:http://localhost/index.php,应该就可以看到如下的画面:
这个画面显示了一个错误信息,但是也表明 index.php 中的两行代码已经成功启动了 FleaPHP 框架。
实现我们的第一个控制器在 FleaPHP 应用程序中,应用程序包含多个控制器。每一个控制器又提供一组控制器动作(后文及本系列文章中都简称为“动作”)。每一个浏览器发送给 FleaPHP 应用程序的请求,都是由一个动作来处理的。将一组相关的动作集中到一起,就形成了一个控制器。
现在我们来实现第一个控制器:
创建 htdocs/APP/Controller 目录,并创建文件 htdocs/APP/Controller/Default.php (注意严格匹配目录名和文件名的大小写),内容如下:
<?phpclass Controller_Default{ function actionIndex() { echo "My first controller."; }}同时修改 index.php 入口文件,内容改为:
<?phprequire('FLEA/FLEA.php');FLEA::import(dirname(__FILE__) . '/APP');FLEA::runMVC();现在切换到浏览器,点击“刷新”按钮,可以看到 Default.php 文件中的 actionIndex 方法正确执行了。
从刚刚这个例子可以看到,每一个控制器实际上就是一个类,而一个动作则是该类的一个方法。
添加更多的动作现在我们为这个控制器添加更多的 Action 方法:
<?phpclass Controller_Default{ function actionIndex() { echo "My first controller."; } function actionSay() { echo "Oh, FleaPHP great!"; }}切换到浏览器,将浏览地址从 http://localhost/index.php 改为 http://localhost/index.php?action=say 并按回车键。可以看到输出内容改变了。
由此可见,action 参数的值决定了要调用控制器中的哪一个动作方法。在上面的例子中,action=say 时,调用的动作方法为 actionSay。因为 FleaPHP 默认要求每一个动作方法必须加上前缀 action。如果不提供 action 参数,则名为 index 的动作方法 actionIndex() 会被调用。
实现更多的控制器创建新文件 htdocs/APP/Controller/Book.php,并输入内容:
<?phpclass Controller_Book{ function actionIndex() { echo "Book controller default action."; } function actionSayTitle() { echo h("<< Boost up with FleaPHP >>"); }}现在切换到浏览器,输入地址 http://localhost/index.php?controller=Book&action=sayTitle,并按回车键。可以看到我们成功的调用了另一个控制器的动作方法。
与使用 action 参数指定要调用的动作类似,用 controller 参数可以指定要调用的控制器。而此时 action 参数指定的就是该控制器的动作。
四、命名规范和目录结构
FleaPHP 的命名规则和目录结构初看上去比较复杂,但习惯以后,你会发现这种命名规则带来许多好处。因此像 Zend Framework 也是采用同样的做法。
当然,FleaPHP 对于应用程序的命名规则和目录结构没有强制性要求。只不过采用一致的命名规则和目录结构,可以方便对应用程序维护。同时 FleaPHP 应用程序开发者之间也可以更容易的进行协作。
全局函数的命名规则全局函数的命名规则是用“_”分隔全小写的单词。例如 get_cache()。同时,函数的名字采用“动词+宾语”的形式。例如 write(动词)_cache(宾语)。
不过有些全局函数为了和 PHP 中已有的类似函数保持一致,采用了不同的命名方式(顺便抱怨一下,PHP 自身的全局函数命名比较混乱,各种形式的都有)。
类的命名规则所有 FleaPHP 自带的类,都以 FLEA_ 开头。然后根据用途命名。例如 FLEA_Controller_Action、FLEA_Helper_ImgCode。然后将类名字中的“_”替换为目录分隔符,就是这个类的定义文件所在位置。
举例:
FLEA_Controller_Action 类,保存文件为 FLEA/Controller/Action.php
FLEA_Db_TableDataGateway 类,保存文件为 FLEA/Db/TableDataGateway.php
这种命名规则和目录结构的优缺点如下:
优点:
避免命名冲突
根据类名字就能找到文件存放位置
应用程序中可以使用 FleaPHP 的 FLEA::import()、FLEA::loadClass() 方法方便的载入类定义文件
如果使用 PHP5,可以很方便的用 __autoload() 来自动载入需要的类定义:
<?phpfunction __autoload($className) { FLEA::loadClass($className, true);}缺点:
类名字较长,不便于输入,例如 FLEA_Rbac_UsersManager
也许和现有习惯不同,需要时间来适应
对于第一个缺点,使用 Zend Development Environment 或者 Eclipse 这样的 IDE 可以缓解。这些 IDE 提供强大的输入自动完成功能,通常输入类名字的开头几个字母,就会显示候选列表让开发者选择。
变量和常量命名在 FleaPHP 中,变量分为全局变量、临时变量和模版变量三类。
全局变量和常量 全局变量和常量都使用全大写,以“_”分隔。例如 $GLOBALS['CLASS_PATH'] 和 FLEA_DIR。不过 FleaPHP 中尽量避免了使用全局变量和常量,因此一般来说不会和应用程序产生冲突。
临时变量 函数、类方法中使用的变量都是临时变量,命名规则是第一个单词小写,后续的单词第一个字母大写。例如 $requestFilters、$dispatcherClass 等。
模版变量 之所以要把模版变量单独列出来,是因为不同的模版引擎对变量名有不同的规范。从我个人来说,我倾向于模版变量使用全小写单词,并以“_”分隔,例如 $latest_products_list。这样在程序里面一眼就能看出哪些变量是用于模版的。
FleaPHP 的目录结构一个典型的 FleaPHP 应用程序具有如下的目录结构:
这个应用程序的目录主要分为 LIBS 和 WEBROOT。其中 LIBS 保存程序的所有代码,而 WEBROOT 目录下只保存用户可以访问的部分,例如 index.php 入口文件、图片、CSS 样式表和 JS 脚本。
LIBS 下又分为 FLEA、SHARED、ADMIN、FRONT 等目录。FLEA 目录保存 FleaPHP 的核心文件,而 SHARED 目录保存应用程序前后台共享的文件、ADMIN 目录保存应用程序后台专有的代码、FRONT 目录保存前台程序专有的代码。开发者在规划目录结构时,可以参照这种方式。
WEBROOT 是保存用户使用浏览器可以直接访问的内容,因此需要修改服务器或虚拟主机设置,将网站的根目录指向 WEBROOT 目录。例如 www.example.com 指向 /example/WEBROOT/。
这里介绍的目录结构有如下优点:
优点:
代码文件放置在浏览器访问不到的地方,提高了安全性
程序员和设计人员可以在不同的目录工作,降低了发生冲突的几率
目录结构更清晰,容易理解
而主要的缺点就是需要修改服务器设置,将网站根目录指向 WEBROOT 目录。而有些虚拟主机不允许这样做,或者需要联系服务器管理员,比较麻烦。
对于这种目录结构,放置在 WEBROOT 中的 index.php 入口文件应该明确调用 FLEA::import() 将 LIBS 目录添加到类定义搜索路径中。否则 FLEA::loadClass() 会找不到需要的文件。
<?phprequire('../LIBS/FLEA/FLEA.php');FLEA::import('../LIBS/SHARED/');....FLEA::runMVC();对于虚拟主机用户,可以将 LIBS 目录移动到 WEBROOT 目录中。形成如下的目录结构:
上图中,所有文件都保存在应用程序的根目录 cdhlss 中,而代码文件保存在 LIBS 子目录中。
相应的 index.php 需要修改为:
<?phprequire('libs/FLEA/FLEA.php');FLEA::import('LIBS/APP/');....FLEA::runMVC();在实际开发中,由于 FleaPHP 并没有强制要求命名规范和目录结构。所以开发者可以继续沿用自己熟悉的方式来开发应用程序。
本篇文章来源于PHP论坛 文章地址:http://bbs.php.cn/thread-25165-1-1.html