ThinkPHP 与 CodeIgniter 开发框架的粗略简单不细致比较

第1章 绪    论

1.1  研究背景

许多PHP程序员经历了各种开发环境之后,肯定有自己的一套框架选择池,不同的网站和应用需要不同的框架,但是此论文的论述不在这里讨论,只对ThinkPHPCodeIgniter的一些配置,语法,和一些特性区别给予论述,使读者对这两个框架有更好的了解.

1.2  使用框架

开发者可能出于不同的考虑而使用PHP开发框架,不过首当其冲的原因是为了加速开发过程。相似工程之间的代码重用能够节省开发者大量的时间和精力。PHP开发框架内置了预建的模块,免去了冗长又令人厌烦的编程工作。这样开发者就能够把时间活在开发实际程序上,而不是每一次都要为每一个项目重建基础模块。

稳定性是开发者使用框架的另一个重要原因。尽管简单是PHP最大的资本,也是许多人喜爱这个脚本语言的原因,它也是PHP潘多拉之盒”,尤其是那些初学者而言,PHP是如此的简单以至于他们会完全没有意识地写出低质量的代码。这样的PHP程序可能在大多数时间内仍正常工作,但你可能已在代码中留下了巨大的安全漏洞,使其易受攻击。要时刻牢记PHP是一门很宽松的语言十分重要,因此确保不在代码中遗留任何安全漏洞是重中之重——即使程序看起来工作正常。

最后一点,PHP开发框架是可扩展的,并且有许多框架可供选择。你也可以创造你自己的,不过许多开发者决定从那些流行的知名的开发框架中做选择,因为它们往往有着庞大的支持团队,以及相关的论坛/社区方便你与其他使用同一个框架的开发者相互交流。注意,你应当事先检验你的项目是否需要使用框架,这里提供一份简单的列表以供参考:使用框架能否节省你(和其他任何会使用它的人)的时间和精力?是否能够让程序得到更好的表现?能否提高稳定性?如果你对上面任何一个问题的回答是肯定的,那么使用PHP开发框架对于这个项目就可能是正确的选择。 

1.3  开发环境

实验环境:Windows 7 Professional + Apache 2.0 + Mysql 5.0 +PHP 5.4

文件目录:根目录/TPCI

TPCI下包括TPCI两个文件夹,分别作TP实验台的根目录和CI实验台根目录.

ThinkPHP版本 3.0

CodeIgniter 版本2.1.2

使用编辑器 Notepad++

第2章 ThinkPHP 和CodeIgniter 

2.1  ThinkPHP

2.1.1  ThinkPHP 介绍

ThinkPHP可以支持WIN/Unix服务器环境,正式版需要PHP5.0以上版本支持,支持Mysql、PgSQL、Sqlite以及PDO等多种数据库,ThinkPHP框架本身没有什么特别模块要求,具体的应用系统运行环境要求视开发所涉及的模块。

使用ThinkPHP,你可以更方便和快捷的开发和部署应用,当然不仅仅是企业级应用,任何PHP应用开发都可以从ThinkPHP的简单、兼容和快速的特性中受益。简洁、快速和实用是ThinkPHP发展秉承的宗旨,为此ThinkPHP会不断吸收和融入更好的技术以保证其新鲜和活力,提供WEB应用开发的最佳实践。  作为一个整体开发解决方案,ThinkPHP能够解决应用开发中的大多数需要,因为其自身包含了底层架构、兼容处理、基类库、数据库访问层、模板引擎、缓存机制、插件机制、角色认证、表单处理等常用的组件,并且对于跨版本、跨平台和跨数据库移植都比较方便。并且每个组件都是精心设计和完善的,应用开发过程仅仅需要关注您的业务逻辑。  ThinkPHP遵循 Apache2 开源许可协议发布,意味着用户可以免费使用ThinkPHP,甚至允许把用户的ThinkPHP应用采用商业闭源发布.[1]

2.1.2  ThinkPHP 的分层架构

ThinkPHP的分层架构采用三层架构模式:

表现层:包含模板视图、用户界面、JSFlash等通过模板引擎的支持,可以使用标签定义简化表现层的定义工作。

业务层:包含业务接口层、业务逻辑层、实体层、数据访问层Action控制器作为业务接口层,提供系统各种业务操作的入口。因此,不提倡在控制器类中写过多的业务逻辑代码,虽然说很难严格控制。具体的业务逻辑应该封装到数据访问对象(Dao)类中实现,如果觉得过于复杂,还可以把子业务在Helper类中包装后统一调用。业务处理过程一般会构造出业务实体对象(如Vo对象),对业务实体对象的存取通过数据访问层完成。数据访问层把实体对象和数据库数据之间建立映射关系,并且封装了通用的数据操作。

数据层:目前支持的数据库有MySqlMsSqlPgSqlOracleSqlite,最新版本已经提供PDO的支持,数据库的选用和业务逻辑没有关系。 [1]

2.1.3  ThinkPHP 的MVC模式

模型(M):模型的定义由Model类来完成。Model类位于项目目录下面的LibModel目录。  

控制器(C):应用控制器(核心控制器)和Action控制器都承担了控制器的角色,区别在于Action控制器完成业务过程,而应用控制器(App类)负责调度控制。Action控制器位于项目目录下面的LibAction目录。  

视图(V):模板的实现是和框架无关的,做到了100%分离,可以独立预览和制作。模板目录位于项目目录下面的Tpl目录。 独创的核心编译和项目编译机制 .[1]

2.1.4  ThinkPHP 独创的核心编译和项目编译机制

ThinkTemplate是一个使用了XML标签库技术的编译型模板引擎,支持两种类型的模板标签,使用了动态编译和缓存技术,而且支持自定义标签库。其特点包括:

  1)支持XML标签库和普通标签的混合定义;

  2)编译一次,下次直接运行而无需重新编译;

  3)模板文件更新后,自动更新模板缓存;

  4)自动加载当前操作的模板缓存文件,无需指定模板文件名称;

  5)支持编码转换和Content-Type更换;

6)模板变量输出前缀支持,避免变量名称冲突;  

7)模板常量替换,无需设置模板变量;  

8)支持变量组合调节器和格式化功能;  

9)支持替换其它模板引擎插件使用;  

10)支持获取模板页面内容[1]

2.1.5  ThinkPHP 特性

内置XML模板引擎,支持标签库

富模型支持

1)聚合模型:

聚合模型是一种虚拟模型,用于把数据表的字段抽象化,更加容易理解和操作。

我们可以把数据表中的某些属性进行数据封装,这样就把枯燥的数据表字段赋予更好的可读性。

2)静态模型:

静态模型可以让模型的数据静态化,而不需要频繁和数据库打交道,可以用于不经常不变的数据表。而且ThinkPHPORM层上面模拟实现了数据库的视图功能,这是ThinkPHP独创的一项技术,使得多表的关联查询具有更高的效率和可操作性,而无需定义复杂的关联关系,让关联关系更加浅显易懂。

有些时候,数据表的数据一旦添加后就不再容易变化,我们更希望把这样的模型数据静态化,而不需要再次访问数据库。ThinkPHP支持静态模型的概念,一旦把模型设置为静态,那么会在第一次初始化的时候获取数据表的全部数据,并生成缓存,以后不会再连接数据库。而只需要直接访问模型的dataList数据即可。

3)视图模型

ThinkPHPORM模型里面模拟实现了数据库的视图模型,该功能可以用于多表查询。  要定义视图对象,需要设置viewModeltrue,然后设置viewFields属性即可。

CURD和操作高度自动化支持

ThinkPHP提供了灵活和方便的数据操作方法,不仅实现了对数据库操作的四大基本操作(CURD):创建、读取、更新和删除的实现,还内置了很多实用的数据操作方法,提供了ActiveRecords模式的最佳体验。

丰富的查询语言支持

ThinkPHP大多数情况使用的都是对象查询,因为充分利用了ORM查询语言,了解查询条件的定义对使用对象查询非常有帮助,对于复杂的查询,或者从安全方面考虑,可以使用HashMap对象或者索引数组来传递查询条件。

目录结构自动创建THINKPHP目录结构

ThinkPHP具有项目目录自动创建功能,你只需要定义好项目的入口文件,第一次执行入口文件的时候,系统会自动创建项目的相关目录结构,如果是linux环境下面需要给项目入口文件里面指定的路径设置可写权限。

分布式数据库支持

ThinkPHP的模型支持主从式数据库的连接,配置DB_DEPLOY_TYPE1可以采用分布式数据库支持。

多数据库连接和切换支持

如果需要在特殊的时候连接多个数据库,那么可以尝试使用ThinkPHP的多数据库连接特性:包括相同类型的数据库和不同类型的数据库。(注意:所谓的相同类型数据库的定义是指和项目配置文件或者模型的数据库连接的数据库类型相同。)

ActiveRecords模式和丰富的ROR特性

ThinkPHP实现了ActiveRecords模式的ORM模型,采用了非标准的ORM模型:表映射到类,记录(集)映射到对象,字段属性映射到对象的虚拟属性。最大的特点就是使用方便,从而达到敏捷开发的目的。

灵活简单的项目配置

ThinkPHP提供了灵活的配置功能,采用最有效率的PHP返回数组方式定义,支持惯例配置、项目配置、调试配置和模块配置,并且会自动生成配置缓存文件,无需重复解析的开销。对于有些简单的应用,你无需配置任何配置文件,而对于复杂的要求,你还可以增加模块配置文件,另外ThinkPHP的动态配置使得你在开发过程中可以灵活的调整配置参数。

ThinkPHP在项目配置上面创造了自己独有的分层配置模式,其配置层次体现在:惯例配置-->项目配置-->模块配置-->操作(动态)配置,优先顺序从右到左(在没有生效的前提下)。

模型自动验证和处理

系统内置了数据对象的自动验证功能,而大多数情况下面,数据对象是由表单提交的$_POST数据创建。需要使用系统的自动验证功能,只需要在Model类里面定义$_validate属性,是由多个验证因子组成的数组,支持的验证因子格式:验证字段,验证规则,错误提示,验证条件,附加规则,验证时间。

静态页面生成和多元化缓存机制

ThinkPHP内置了静态缓存的功能,并且支持静态缓存的规则定义。要使用静态缓存功能,需要开启HTML_CACHE_ON参数,并且在项目配置目录下面增加静态缓存规则文件htmls.php。  

丰富的数据库及PDO支持

SEO和URL路由支持

AJAX支持

易扩展的系统基类库

系统基类库

ThinkPHP框架通过基类库的概念把所有系统类库都集成在一起,包括ThinkPHP的核心类库。

目前的基类库分成Think核心类库、ORG扩展类库,在这主要介绍的是核心基类库,核心基类库的作用是完成框架的通用性开发而必须的基础类和常用工具类等,包含有:

  Think.Core 核心类库包

  Think.Db 数据库类库包

  Think.Util 系统工具类库包

  Think.Template 内置模板引擎类库包

  Think.Exception 异常处理类库包函数库

  ThinkPHP内置了一个系统公共函数库,提供了一些系统需要的函数,系统函数库位于ThinkPHPCommon目录下面,名称为functions.php

每个项目可以定义自己的函数库,位于项目的Common目录下面的common.php文件。  

如果项目在Common目录下面有定义自己的common.php文件,框架会在初始化的时候自动导入,而无需自己导入。

  匹配导入

  Import方法是ThinkPHP内建的类库和文件导入方法,提供了方便和灵活的类似于命名空间的文件导入机制。

  自动编码转换

  ThinkPHP框架的文件全部采用UTF-8编码格式,UTF-8的支持和自动输出编码转换的功能让页面表现更加灵活。您可以配置输出的页面编码格式,如gb2312等(默认采用UTF-8输出)。系统根据配置文件中设置的编码格式自动对页面进行编码转换,支持iconv和mb_string两种方式,为了提高效率,如果系统的模板编码设置和输出编码设置项相同,则不会进行编码转换。ThinkPHP可以设置模板编码、输出编码和数据库编码,并自动完成转换工作,让你的应用不再受编码的苦恼。  

组件和插件支持

基于角色的权限控制体系  

企业级的应用是离不开安全保护的,ThinkPHP以基于Spring的Acegi安全系统作为参考原型,并做了简化,以适合目前的ThinkPHP结构,提供了一个多层的、可定制的安全体系来为应用开发提供安全控制。安全体系中主要有: 安全拦截器、认证管理器、决策访问管理器 、运行身份管理器。[2]

2.2 CodeIgniter

2.2.1  CodeIgniter 介绍

CodeIgniter 是一套给 PHP 网站开发者使用的应用程序开发框架和工具包。它提供一套丰富的标准库以及简单的接口和逻辑结构,其目的是使开发人员更快速地进行项目开发。使用 CodeIgniter 可以减少代码的编写量,并将你的精力投入到项目的创造性开发上。

CodeIgniter是由Ellislab公司的CEORickEllis开发的。其核心框架是为这个程序特别编写的,而其他很多类库、辅助函数和子系统则来自于RickEllisPaulBurdick编写的内容管理系统ExpressionEngine。来自RubyonRails灵感启发我们创造了一个PHP框架,并且将框架的概念引入到网络社区的一般意识中。[2]

2.2.2  CodeIgniter 技术和架构

CodeIgniter 的目标是在最小化,最轻量级的开发包中得到最大的执行效率、功能和灵活性。  

为了达到这个目标,我们在开发过程的每一步都致力于基准测试、重构和简化工作,拒绝加入任何对实现目标没有帮助的东西。

从技术和架构角度看,CodeIgniter 按照下列目标创建:

动态实例化。在 CodeIgniter 中,组件的导入和函数的执行只有在被要求的时候才执行,而不是在全局范围。除了最小的核心资源外,不假设系统需要任何资源,因此缺省的系统非常轻量级。被 HTTP 请求所触发的事件,以及你设计的控制器和视图将决定它们什么时候被引用。

松耦合。耦合是指一个系统的组件之间的相关程度。越少的组件相互依赖那么这个系统的重用性和灵活性就越好。我们的目标是一个非常松耦合的系统。

组件专一性。专一是指组件有一个非常小的专注目标。在 CodeIgniter 里,为了达到最大的用途,每个类和它的功能都是高度自治的。 CodeIgniter 是一个动态实例化,高度组件专一性的松耦合系统。它在小巧的基础上力求做到简单、灵活和高性能。 

2.2.3 CodeIgniter 设计和目录

CodeIgniter 是基于模型-视图-控制器这一设计模式的。MVC 是一种将应用程序的逻辑层和表现层进行分离的方法。在实践中,由于表现层从 PHP 脚本中分离了出来,所以它允许你的网页中只包含很少的脚本。[3]

 模型(Model) 代表你的数据结构。通常来说,你的模型类将包含取出、插入、更新你的数据库资料这些功能。

 视图(View) 是展示给用户的信息。一个视图通常是一个网页,但是在 CodeIgniter 中,一个视图也可以是一个页面片段,如页头、页尾。它还可以是一个 RSS 页面,或任何其它类型的页面。 

控制器(Controller) 是模型、视图以及其他任何处理 HTTP 请求所必须的资源之间的中介,并生成网页。 CodeIgniter 在 MVC 使用上非常宽松,因此模型不是必需的。如果你不需要使用这种分离方式,或是发觉维护模型比你想象中的复杂很多,你可以不用理会它们而创建自己的应用程序,并最少化使用控制器和视图。CodeIgniter 也可以和你现有的脚本合并使用,或者允许自行开发此系统的核心库,其目的是,使你可以以最适合你的方式工作。 [2]

2.2.3  CodeIgniter 特性

开发框架优秀与否与它有多少特性没有太大的关系。你从特性中不能推断出用户的体验、不能体验到框架设计是不是直截了当,是不是智能。特性也不能告诉你框架代码的质量如何、性能如何、细节处理的如何、安全性如何。判断一个框架的唯一办法是在使用中了解它。安装CodeIgniter很简单,所以,请你使用它。CodeIgniter的主要特性如下:

  基于 MVC 体系

  超轻量级

  对数种数据库平台的全特性支持的数据库类

  * Active Record 支持

  表单与数据验证

  安全性与 XSS 过滤

  * Session 管理

  邮件发送类,支持附件,HTML 或文本邮件,多协议(sendmail, SMTP 和 Mail)及更多。  

图像处理类库(剪裁,缩放,旋转等)。支持 GDImageMagick 和 BetPBM

  文件上传类

  * FTP 

  本地化

  分页 

 数据加密 

 基准测试

  全页面缓存

  错误日志

  应用程序评测

  日历类

  * User-Agent 

  * Zip 编码类

  模板引擎类

  * Trackback 

  * XML-RPC 类库

  单元测试类

  * “搜索引擎友好的 URL

  灵活的 URI 路由

  支持钩子和类扩展

  大量的辅助函数 [3]

第3章 ThinkPHP 和 CodeIgniter在应用中比较

3.1  配置ThinkPHP

在使用ThinkPHP之前,要先配置,我用的是ThinkPHP 3.0ThinkPHP 的框架包只有一个名为ThinkPHP4.63MB的文件夹,将他拷到网站目录下后,要建立一个index.php的入口文件。ThinkPHP 2.0 的入口文件和ThinkPHP3.0的入口文件有很大区别,最明显的一点就不用再写run()方法,ThinkPHP 3.0是自动进行run.

在拷贝的时候就发现,ThinkPHP 一直在做一个轻量级开发框架,CodeIgniter框架包比ThinkPHP 还要小,说明CodeIgniter ThinkPHP还要轻巧,在后面的叙述中会有详细解释.

下面写ThinkPHP的入口文件,一个ThinkPHP的入口文件包括了几项.载入框架入口文件

(1) 定义THINK_PATH 框架路径

(2) 定义APP_NAME 项目名称

(3) 定义APP_PATH 项目路径

(4) 定义APP_DEBUG 定义调试模式

(5) 定义SHOW_PAGE_TRACE 显示页面轨迹

(6) 加载入口文件(此步为必须,以上为可选)

如果不定义项目路径, ThinkPHP就会自动在ThinkPHP的当前框架目录下生成四个文件夹,它们是 Common,Conf,Lang,Lib,Runtime,Tpl,他们基本都是空文件夹,用来存放相应的文件信息:

3.1 ThinkPHP目录结构

Common

项目公共文件目录,一般放置项目的公共函数

Conf

项目配置目录,项目所有的配置文件都放在这里

Lang

项目语言包目录(可选 如果不需要多语言支持 可删除)

Lib

项目类库目录,通常包括ActionModel子目录

Tpl

项目模板目录,支持模板主题

Runtime

项目运行时目录,包括Cache(模板缓存)、Temp(数据缓存)、Data(数据目录)和Logs(日志文件)子目录,如果存在分组的话,则首先是分组目录。

[3]

 

3.1 ThinkPHP 项目目录机构1

通过图片可以看到,如果不定义项目路径,文件夹和框架ThinkPHP的文件夹在同一级目录下,所以显得杂乱,一般的我们都定义一个项目路径,而项目路径就是以项目名为文件夹,ThinkPHP框架同一级.修改后的项目目录结构如下图

3.2 ThinkPHP 项目目录机构2

其中TP文件夹包含了Common,Conf,Lang,Lib,Runtime,Tpl,四个文件夹,下面是入口文件index.php的内容

define("THINK_PATH","./ThinkPHP/");

define("APP_NAME","TP");

define("APP_DEBUG",true);

// 开启调试模式

define("SHOW_PAGE_TRACE",true);

define("APP_PATH","TP/");//定义项目路径

require THINK_PATH.'ThinkPHP.php';

之后再浏览器中输入TP的路径http://127.0.0.1/TPCI/TP/ 显示如下,说明配置成功

3.3 ThinkPHP 项目测试主页

ThinkPHP 没有提供入口文件,所以如果不配置index.php,是无法直接打开的,CodeIgniter 把框架拷贝过来后,入口文件是已经配置好的.

 

3.2 配置CodeIgniter

在使用CodeIgniter之前,也要配置,我用的是CodeIgniter 2.1.2. CodeIgniter 的框架包包括application 和 system 两个文件夹和一个,1.28MB, application里面是用户需要操作的,system里是系统核心,index.php 是入口文件

3.4 CodeIgniter 项目目录

拷贝过来之后,就可以直接运行,在浏览器中输入相应路径,会出现如下图

3.5 CodeIgniter 项目初始化主页

由于入口文件已经给出,所以下面对入口文件进行解析.

CodeIgniter的入口文件内容比ThinkPHP多很多下面我们进行一一解析

define('ENVIRONMENT', 'development')

定义环境类型,此处有三项可以选择,分别是"deveopment"(开发),"testing"(实验)"production"(产品),网站建设初期用development,这也是CodeIgniter的默认选择,

下面针对定义的ENVIRONMENT进行判断错误信息报告,这里对网站安全可以提供保障,如果是development 环境,将提示所有警告,错误信息,如果是testing则提示系统相应的的设置的警告,错误信息,如果是production环境,将屏蔽所有警告.

if (defined('ENVIRONMENT'))

{

switch (ENVIRONMENT)

{

case 'development':

error_reporting(E_ALL);

break;

case 'testing':

case 'production':

error_reporting(0);

break;

default:

exit('The application environment is not set correctly.');

}

}

之后便是指定$system_path $application_folder , system_path对应的就是框架中的system文件夹,application_folder 对应的就是框架中的application文件夹,由于安全问题或者为了开发便捷,可能会有改动,所以在这里可以定义.我们为了说明简单,使用系统默认.

$system_path = 'system';

$application_folder = 'application';

下面就是针对配置文件进行设置

如果配置文件加载了STDIN,则改变目录到 __FILE__所在的目录如果system文件夹的目录不存在,将在目录后加"/" ,再不成,则提示系统目录错误.

if (defined('STDIN'))

{

chdir(dirname(__FILE__));

}

if (realpath($system_path) !== FALSE)

{

$system_path = realpath($system_path).'/';

}

// ensure there's a trailing slash

$system_path = rtrim($system_path, '/').'/';

// Is the system path correct?

if ( ! is_dir($system_path))

{

exit("Your system folder path does not appear to be set correctly. Please open the following file and correct this: ".pathinfo(__FILE__, PATHINFO_BASENAME));

}

之后对系统变量进行定义,包括文件名,php文件扩展名,系统路径等基础变量.

define('SELF', pathinfo(__FILE__, PATHINFO_BASENAME));

define('EXT', '.php');

define('BASEPATH', str_replace("\\", "/", $system_path));

define('FCPATH', str_replace(SELF, '', __FILE__));

define('SYSDIR', trim(strrchr(trim(BASEPATH, '/'), '/'), '/'));

对项目文件夹进行定义,ThinkPHP,项目文件夹就是项目名,而在CodeIgniter,项目文件夹就是application文件夹,

if (is_dir($application_folder))

{

define('APPPATH', $application_folder.'/');

}

else

{

if ( ! is_dir(BASEPATH.$application_folder.'/'))

{

exit("Your application folder path does not appear to be set correctly. Please open the following file and correct this: ".SELF);

}

define('APPPATH', BASEPATH.$application_folder.'/');

}

在所有定义完之后,ThinkPHP一样,进行载入启动项目核心文件

require_once BASEPATH.'core/CodeIgniter.php';

这样在浏览器输入相应地址后,就会出现前面提到的那个网页.

3.3 Hello World

作为程序员,每接触一个新的语言或者框架,都有一个习惯就是输出一个"Hello World",我也是这样的,下面就两个框架输出Hello World ,ThinkPHPCodeIgniter做对比.

3.3.1 ThinkPHP 输出

ThinkPHP 在入口文件建好后,就会自动的有显示,通过常规思维就可以知道,修改那几个字就可以出现Hello World,那在哪修改呢? ThinkPHP MVC模式非常强大,"M"和对应的文件夹在Lib/Model ,"C"对应的文件夹在Lib/Action,"V "对应的文件夹在Tpl,由于ThinkPHP是编译型框架,模板引擎的使用十分强大,ThinkPHP的模板文件的扩展名为html,无法使用原生PHP,只能按照ThinkPHP的模板引擎的标签规则进行操作但是我们可以看到,现在Tpl文件夹里是空的,那是怎么显示的文字呢这就要看ThinkPHP Action. 

Action文件夹里,有一个名为 IndexAction.class.php的文件,里面就一个相应的输出,如下图

3.6 ThinkPHP IndexAction

有上图可以看出几点:

所有自定义Action类都是继承Action,拥有Aciton的所有方法

ThinkPHP的控制器Action采用面向对象的方法

Index 是默认方法,并且第一个字母不用大写.而文件名第一个字母和Aciton的第一字母要大些,并且名字和Aciton名相同

ThinkPHP编译过程中,会执行index()方法,index()方法里的输出会直接输出在浏览器里

我们将文件进行修改后,输出"Hello World".

(由于本文只对ThinkPHPCodeIgniter的一些性质对比,PHP语法不做过多解释header()函数的用法就是发送头,以后不再对PHP语法进行解释)

class IndexAction extends Action {

    public function index(){

echo "Hello World";

    }

}

输入相应地址后出现期待结果如下图

,

3.7 ThinkPHP 显示HelloWorld

虽然出现了想要的结果,但是ThinkPHP 的设计理念里,Action里输出内容是不可取的,不符合MVC的形式,在为了和CodeIgniter比较,我们在这里载入相对应的view(也就是模板),IndexAction里加入

  $this->display();

Indexview(模板)文件名(不写扩展名),相当于和index view进行连接组合,最后通过$this->display()将模板显示.再运行之后出现报错,如下图

3.8 ThinkPHP 的错误提示

通过提示可以看出ThinkPHP的一些特性,错误提示页面很友好,并把错误出现位置,错误解释,和文件轨迹全部显示出来用来用户参考,这是在调试过程中,在产品中,这个页面会被404错误页面取代.

通过错误信息可以看出ThinkPHP的模板文件放在Tpl,并且以控制器名字命名文件夹,文件夹内再以方法名命名类,这是ThinkPHP默认的方式,当然也可以通过给定变量来改变这一方式,这里先用默认方法.

我们按照提示建立文件,及时是空文件,刷新页面后,显示正常说明Tpl的模板找到后可以执行编译.通过报错信息,我们还可以简单了解到ThinkPHP的编译过程.

当然,由于本次操作并没有进行数据库操作,但是也是完成了ThinkPHP的一次页面实例化,开启缓存机制后,编译后的文件会在runtime目录下的Cache中存在,编译后的文件是以加密后的名字命名,里面使用原生的php语法,提高访问效率,但是每次改动后,最好都要删除runtime文件夹下的内容,防止缓存延误修改的内容.

ThinkPHP是怎样通过模板输出控制器(Action)中的变量的呢?

ThinkPHPIndexAction控制器里编辑

class IndexAction extends Action {

    public function index(){

$data="Hello World";

$this->assign('hello',$data);

$this->display();

    }

}

这样"$this->assign('hello',$data);"将控制器和模板联系起来,此句的意思就是将控制器中的$data变量赋值给模板中的$hello变量.我们在模板文件里书写如下语句

{$hello}

这样,遍通过模板,显示了$hello变量的内容,通过编译后的文件可以看到

<?php if (!defined('THINK_PATH')) exit(); echo ($hello); ?>

输出了$hello变量内容.

3.3.2 CodeIgniter 输出

CodeIgniter的输出显然比ThinkPHP的输出方式正规一些,在官方的默认中,控制器controllers(ThinkPHP中为Action文件夹)文件夹中有一个名为welcome.php的文件,在项目配置文件中config\routes.php,可以配置默认的控制器方法,框架包中默认的是welcome.php方法,我们可以修为index,对应的是controllers\index.php\welcome方法,所以,你可以用三种方法访问welcome.

3.9 CodeIgniter主页URL形式1

3.10 CodeIgniter主页URL形式2

3.11 CodeIgniter主页URL形式3

路径的形式和ThinkPHP类似,index.php是入口文件,以后的所有操作都是在index.php之后完成的,但是可以对Apache 服务器进行操作使其将index.php隐藏,在网站根目录下建立".htaccess"文件,由于Apache是在Linux下诞生的,文件的形式是Linux下的隐藏文件,"."开头,没有扩展名.在这个文件里用文本编辑器打开输入如下内容后即可,要求Apache服务器打开 rewrite模块

<IfModule mod_rewrite.c>

RewriteEngine on

RewriteCond %{REQUEST_FILENAME} !-d

RewriteCond %{REQUEST_FILENAME} !-f

RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]

</IfModule>

CodeIgniter框架里application文件夹下的config文件夹下包含了项目的配置文件,其中有routes.php的配置文件,里面有两个项目,一个就是主页的设置,默认为welcome,我们在以后的使用中,将其改为index,还有一个是404错误页面的自定义,我们默认为空.

$route['default_controller'] = "index";

$route['404_override'] = '';

按照使用习惯,我们把默认路由改为index.也就是$route['default_controller'] = "index"

同时在view文件夹下建立index.php的视图文件,这一点和ThinkPHP有很大不同,这和CodeIgniter不是编译型框架有很大关系,CodeIgniter的框架视图里,可以随时使用原生PHP语法,当然ThinkPHP也是可以的,但是ThinkPHP的视图(模板),要用到ThinkPHP提供的大量标签,比如<volist>,<if condition=? >之类的,CodeIgniter,则使用原生的PHP语法即可.比如foreach 和 <volist>是同等的.

建立index.php视图后,通过浏览器并不能直接浏览,因为CodeIgniter也符合MVC规范,需要在controallers里建立index.php的控制器.在默认的welcome.php控制器里,我们已经可以看到,默认类之前给出一句话

if ( ! defined('BASEPATH')) exit('No direct script access allowed');

这是为了防止跨网站攻击用的,而在ThinkPHP里是没有的,还是因为ThinkPHP是编译型框架,在编译过程中,已经为每个网页里添加了一句放跨站攻击的语句,这句话可以再ThinkPHP项目目录下的runtime文件夹下的Cache文件夹下的任意一缓存(编译后的)文件里找到这样一句话

if (!defined('THINK_PATH')) exit();

这也是放跨站攻击,THINK_PATH会在项目里定义,如果没定义,说明非本网站请求,给予拒绝.

说到放跨站攻击机制,CodeIgniter在每个目录下,都建立一个index.html的文件,如果有非正常请求,会在浏览器端显示index.html内容"Directory access is forbidden.";

ThinkPHP类似,index.php的控制器里编辑index

class Index extends CI_Controller {

public function __construct()

{

parent::__construct();

}

public function index()

{

echo "Hello World";

$this->load->view('index');

}

}

在自定义index类继承CI_Controller的类之后,还要对父类进行构造,否则无法加载CodeIgniter的函数库.修改后,输入相应地址,我们发现,由于我们新建立的index.php视图文件是空的,但符合了规则.浏览器中输出了"Hello World".这也说明了,controller,仍然可以向浏览器输出数据,这和ThinkPHP是类似的.但是CodeIgniter的控制器和视图(view)的数据传送和ThinkPHP有些不同.

CodeIgniter,我们要先把数据复制到$data数组里,之后将$data数组导入到视图,但是视图中并不存在$data变量,而存在$data变量里键名为变量名的变量.所以我们将"Hello World"复制给"$data["hello"]",之后将$data导入到视图

public function index()

{

$data["hello"]="Hello World";

$this->load->view('index',$data);

}

同时,在新建立的view index.php,编辑简单的一句话来打印变量

<?=$hello?>

这样,我们刷新页面发现,"Hello World"被打印了出来.

在这个方面,CodeIgniterThinkPHP倒是有类似的地方,区别并不是太大.

3.4 $_POST 和 $_GET方法

在表单应用中,CodeIgniter可以利用它自有的函数库,建立表单,在本论文中不讨论,我将在CodeIgniterThinkPHP 两个项目视图中建立两个相同的表单,并提交到index 输出观察结果从而讨论区别.

IndexAction类中加入test()方法

class IndexAction extends Action {

    public function index(){

$this->display();

    }

public function test(){

dump($_POST);

}

}

test方法里,接收POST变量,打印出$_POST数组,这里用了ThinkPHP的一个dump()函数,var_dump()类似.

下面是而对应的ThinkPHP的表单代码

<form action="__APP__/Index/test" method="post" >

<input type="text" name="name" />

<input type="submit" value="TP submit" />

</form>

__APP__ThinkPHP的项目路径.

CodeIgniter对应的index.php的控制器类添加test()方法

class Index extends CI_Controller {

public function __construct()

{

parent::__construct();

$this->load->helper("url");

}

public function index()

{

$this->load->view('index');

}

public function test(){

var_dump($_POST);

}

}

为了方便操作,在测试中,使用了CodeIgniter的函数库,"url"使其可以使用"base_url()"函数,方便在view中路径的编辑.

下面是CodeIgniter的表单代码

<form action="<?=base_url(); ?>index.php/Index/test" method="post" >

<input type="text" name="name" />

<input type="submit" value="CI submit" />

</form>

方法和表单都设置好后,我们开始进行测试.

3.4.1 ThinkPHP 的表单

ThinkPHP的表单值得一提的是,它为每一个表单都默认加了一个hash,防止表单的重复过多提交,但是这个强硬的加入易导致一些问题,比如用Javascript 增加表单时,就会因为双引号问题而无法使用,唯一一个解决办法就是取消hash,ThinkPHP的配置文件里面设置.由于本次试验不涉及JS内容,所以没有取消hash规则

3.12 ThinkPHP测试表单

网页源代码为

<form action="/TPCI/TP/index.php/Index/test" method="post" >

 <input type="text" name="name" /> 

<input type="submit" value="TP submit" />

 <input type="hidden" name="__hash__" value="296b375d2dcddb9c3fbb513ac64ea343_a500e3a3d75eb08d2b1cb89142b4aa73" /></form>

可以看出ThinkPHP已经自动为表单添加了__hash__隐藏变量.

那么输入"Hello World" 并提交后,页面显示

array(2) {

  ["name"] => string(11) "Hello World"

  ["__hash__"] => string(65) "296b375d2dcddb9c3fbb513ac64ea343_a500e3a3d75eb08d2b1cb89142b4aa73"

}

已经提交过来,并正常显示.

将表单的提交形式改为 "get",在控制器中也将"$_POST"改为"$_GET" 再进行测试后,页面显示

array(3) {

  ["name"] => string(11) "Hello World"

  ["__hash__"] => string(65) "296b375d2dcddb9c3fbb513ac64ea343_a500e3a3d75eb08d2b1cb89142b4aa73"

  ["_URL_"] => array(2) {

    [0] => string(5) "Index"

    [1] => string(4) "test"

  }

}

除了我们之前说的"__hash__",有多了一个"_URL"数组,另外在URL解析上,ThinkPHP也有其独特之处.

ThinkPHP框架基于模块和操作的方式进行访问,由于ThinkPHP框架的应用采用单一入口文件来执行,因此网站的所有的模块和操作都通过URL的参数来访问和执行。这样一来,传统方式的文件入口访问会变成由URL的参数来统一解析和调度。

ThinkPHP支持四种URL模式,可以通过设置URL_MODEL参数来定义,包括普通模式、PATHINFOREWRITE和兼容模式。

一、普通模式:设置URL_MODEL 0

采用传统的URL参数模式

http://serverName/appName/?m=module&a=action&id=1

二、PATHINFO模式(默认模式):设置URL_MODEL 1

默认情况使用PATHINFO模式,ThinkPHP内置强大的PATHINFO支持,提供灵活和友好URL支持。PATHINFO模式自动识别模块和操作,例如

http://serverName/appName/module/action/id/1/ 或者

http://serverName/appName/module,action,id,1/

在不考虑路由的情况下,第一个参数会被解析成模块名称(如果启用了分组的话,则依次往后递推),第二个参数会被解析成操作,后面的参数是显式传递的,而且必须成对出现,例如:

http://serverName/appName/module/action/year/2008/month/09/day/21/

其中参数之间的分割符号由URL_PATHINFO_DEPR参数设置,默认为”/”,例如我们设置URL_PATHINFO_DEPR“-”的话,就可以使用下面的URL访问

http://serverName/appName/module-action-id-1/

注意不要使用”:” ”&”符号进行分割,该符号有特殊用途。

略加修改,就可以展示出富有诗意的URL,呵呵~

如果想要简化URL的形式可以通过路由功能(后面会有描述)以及空模块和空操作。

PATH_INFO模式下面,会把相关参数转换成GET变量,以及并入REQUEST变量,因此不妨碍URL里面的GETREQUEST变量获取。

三、REWRITE模式: 设置URL_MODEL 2

URL模式和PATHINFO模式功能一样,除了可以不需要在URL里面写入口文件,和可以定义.htaccess 文件外。在开启了ApacheURL_REWRITE模块后,就可以启用REWRITE模式了,具体参考下面的URL重写部分。

四、兼容模式: 设置URL_MODEL 3

兼容模式是普通模式和PATHINFO模式的结合,并且可以让应用在需要的时候直接切换到PATHINFO模式而不需要更改模板和程序,还可以和URL_WRITE模式整合。兼容模式URL可以支持任何的运行环境。

兼容模式的效果是:

http://serverName/appName/?s=/module/action/id/1/

并且也可以支持参数分割符号的定义,例如在URL_PATHINFO_DEPR~的情况下,下面的URL有效:

http://serverName/appName/?s=module~action~id~1

其实是利用了VAR_PATHINFO参数,用普通模式的实现模拟了PATHINFO的模式。但是兼容模式并不需要自己传s变量,而是由系统自动完成URL部分。正是由于这个特性,兼容模式可以和PATHINFO模式之间直接切换,而不需更改模板文件里面的URL地址连接。[2]

3.4.2 CodeIgniter的表单

CodeIgniter的表单功能也很强大,并且,CodeIgniter提供了表单验证函数,ThinkPHP并没有表单验证的函数,但是在ThinkPHPModel,有对字段的验证,放在下一章节讨论.下图是CodeIgniter的表单

3.13 CodeIgniter测试表单

源代码为

<form action="http://127.0.0.1/TPCI/CI/index.php/Index/test" method="post" >

<input type="text" name="name" />

<input type="submit" value="CI submit" />

</form>

可以看到,只是base_url()函数被替换成地址外,其他的并没有什么改动.我们提交"Hello World"

页面中只显示了一行,并没有其他附加的东西.

array(1) { ["name"]=> string(11) "Hello World" } 

接下来,我们将post改为get,结果是一样的.

既然ThinkPHPCodeIgniter的结果类似,我为什么还拿出来比较呢,因为还有一点没有测试.

我们在浏览器地址栏中输入

http://127.0.0.1/TPCI/TP/index.php/Index/test/name/HelloWorld 

会看到浏览器输出

array(2) {

  ["name"] => string(10) "HelloWorld"

  ["_URL_"] => array(4) {

    [0] => string(5) "Index"

    [1] => string(4) "test"

    [2] => string(4) "name"

    [3] => string(10) "HelloWorld"

  }

}

这是ThinkPHP的结果,那么输入

http://127.0.0.1/TPCI/CI/index.php/Index/test/name/HelloWorld 

浏览器出输出array(0) { } ,没有结果.

这边是ThinkPHPCodeIgniter在地址解析方面的区别.

CodeIgniter则在URL上没有这么多选择,只有一个启用查询字符串,使用浏览器常规的显示方法,ThinkPHP的 URL_MODEL 0.其他的则有 添加任意后缀(为了网站安全考虑)等小的功能,无法和ThinkPHP强大的URL路由相比.

但是CodeIgniter的控制器里可以添加参数,CodeIgniter控制器index.phptest方法改为

public function test($name){

echo $name;

}

然后再浏览器中浏览

http://127.0.0.1/TPCI/CI/index.php/Index/test/HelloWorld 

会发现,浏览器打印出"Hello World". 通过实验可以知道,$name赋值为"HelloWorld",CodeIgniter,可以吧URL的一部分,转换问方法的参数,ThinkPHP则没有这个功能.

3.5 Model的使用

ThinkPHPCodeIgniter比较大的一个区别就是Model的使用,对于其相似的类型设置,因为只是部分不一样,其效果是一样的,不在讨论范围,下文只对其中区别较大的地方做讨论.

3.5.1 ThinkPHP的Model

ThinkPHP模型类一般位于项目的Lib/Model 目录下面,当我们创建一个UserModel类的时候,其实已经遵循了系统的约定。模型类的命名规则是除去表前缀的数据表名称,采用驼峰法命名,并且首字母大写,然后加上模型类的后缀定义ModelUserModel为例

3.2 ThinkPHP Model

模型名(类名)

约定对应数据表(假设数据库的前缀定义think_

UserModel

think_user

UserTypeModel

think_user_type

如果你的规则和上面的系统约定不符合,那么需要设置Model类的数据表名称属性。

ThinkPHP的模型里面,有两个关于数据表名称的属性定义:

3.3 ThinkPHP数据库表明属性定义

tableName

不包含表前缀的数据表名称,一般情况下默认和模型名称相同,只有当你的表名和当前的模型类的名称不同的时候才需要定义。

trueTableName

包含前缀的数据表名称,也就是数据库中的实际表名,该名称无需设置,只有当上面的规则都不适用的情况或者特殊情况下才需要设置。

dbName

定义模型当前对应的数据库名称,只有当你当前的模型类对应的数据库名称和配置文件不同的时候才需要定义。

ThinkPHP的命名规则十分严格,大小写的限制也很严谨,如果不遵守默认原则,除了要修改一些配置文件外,就会出错.

在使用Model的时候有许多方法,UserAction中使用"M"方法,或者"new Model('user')",实例化Model,同时还有一个D方法,D方法会自动判断,并且会提供一些M方法没有的函数供使用.同时空的Model,"M()"或者"new Model()"里 可以使用原生Sql语句查询.

ThinkPHPModel有两个属性十分有意思,一个是$_validate属性,还有一个是$_auto 属性,这两个属性分别对应的是自动验证,和自动完成

自动验证中,类型检查只是针对数据库级别的验证,所以系统还内置了数据对象的自动验证功能来完成模型的业务规则验证,而大多数情况下面,数据对象是由表单提交的$_POST数据创建。需要使用系统的自动验证功能,只需要在Model类里面定义$_validate属性,是由多个验证因子组成的二维数组。

示例:

protected $_validate = array(

array('verify','require','验证码必须!'), //默认情况下用正则进行验证

array('name','','帐号名称已经存在!',0,'unique',1), // 在新增的时候验证name字段是否唯一

array('value',array(1,2,3),'值的范围不正确!',2,'in'), // 当值不为空的时候判断是否在一个范围内

array('repassword','password','确认密码不正确',0,'confirm'), // 验证确认密码是否和密码一致

array('password','checkPwd','密码格式不正确',0,'function'), // 自定义函数验证密码格式

);

当使用系统的create方法创建数据对象的时候会自动进行数据验证操作,代码示例:

$User = D("User"); // 实例化User对象

if (!$User->create()){

// 如果创建失败 表示验证没有通过 输出错误提示信息

exit($User->getError());

}else{

// 验证通过 可以进行其他数据操作

}

通常来说,每个数据表对应的验证规则是相对固定的,但是有些特殊的情况下面可能会改变验证规则,我们可以动态的改变验证规则来满足不同条件下面的验证:

$User = D("User"); // 实例化User对象

$validate = array(

array('verify','require','验证码必须!'), // 仅仅需要进行验证码的验证

);

$User-> setProperty("_validate",$validate);

$result = $User->create();

if (!$result){

// 如果创建失败 表示验证没有通过 输出错误提示信息

exit($User->getError());

}else{

// 验证通过 可以进行其他数据操作

}

同时ThinkPHP也支持批量验证功能,只需要在模型类里面设置patchValidate属性为true( 默认为false),设置批处理验证后,getError() 方法返回的错误信息是一个数组,返回格式是:

array("字段名1"=>"错误提示1","字段名2"=>"错误提示2"... )

前端可以根据需要需要自行处理。

如果系统提供的规则不满足要求,可以使用手动验证,新版增加了一个check方法,用于个别需要的情况手动验证数据,支持部分自动验证的规则,用法如下:

check('验证数据','验证规则','验证类型') 

验证类型支持 in between equal length regex expire ip_allow ip_deny,默认为regex 结果返回布尔值 $model->check($value,'email'); $model->check($value,'1,2,3','in');[1]

3.5.2 CodeIgniter的Model

CodeIgniter的模型建立和ThinkPHP的有一定区别,CodeIgniter,事务是建立在Model中的,ThinkPHP没有强调这一点,致使事务的操作许多人都写在了Action,使得MVC并不标准.同时CodeIgniterModel类使用更贴近原生PHP,在继承CI_Model类后,要先构造父类之后再写自己的函数.更多的是符合PHP语法,ThinkPHP的封装很多,脱离了PHP的一些语法.

下面介绍CodeIgniterModel使用,仍然使用UserModel为例,但是在CodeIgniter,Model文件建在application\models,类名首字母大写并继承模型类,文件名是类名的小写版即可,而不用再像ThinkPHP一样添加class后缀.

application/models/usermodel.php

文件内容

class Usermodel extends CI_Model {

 function __construct()
  {
 parent::__construct();//构造父类
  }
}

如果需要使用数据库函数,则要在构造函数里写入$this->load->database();这样就可以使用CodeIgniter的一些特有的数据库操作

Usermodel类里可以编写例如 insert(), updata()一些函数,还有一些特殊的查询操作,之后再controllers 直接使用方法即可,同时在controllers,需要导入Usermodel类才能使用Usermodel类的操作

$this->load->model('usermodel');

这样就可以通过$this->usermodel->insert() 来使用自定义的数据库操作方法.

第4章 特性比较

4.1  编译与非编译型

ThinkPHP是编译型PHP框架,他的模板引擎非常出色,在网站在第一次执行的时候,或者网页第一次打开,框架会对项目文件进行编译,编译后的文件放在项目目录下的runtime/Cache文件夹下,以乱码命名,在使用中知道,ThinkPHP的视图(模板)文件时以html结尾,并且基本都是通过使用ThinkPHP提供的内置标签进行操作,比如<volist>,<foreach>,<for>,<switch>,<present>,<empty>,<define>等特有的标签,对应的操作可以根据标签的英文猜测到含义.其对应的都为PHP语法,在编译后的文件中可以看到.

我们在index.html模板里编辑如下

<foreach name="data" item="vo">

--{$vo.id}--<br/>

--{$vo.name}--<br/>

</foreach>

此处用的是ThinkPHP<foreach>标签,在控制器IndexAciton.php里编辑如下

class IndexAction extends Action {

    public function index(){

$data=array(array("id"=>"1","name"=>"A"),array("id"=>"2","name"=>"B"));

$this->assign('data',$data);

$this->display();

    }

}

在模板里打印$data的内容.

在浏览器里可以看到显示效果

3.14 ThinkPHP视图数据测试

在编译后的文件里打开查看文件内容

<?php if (!defined('THINK_PATH')) exit(); if(is_array($data)): foreach($data as $key=>$vo): ?>--<?php echo ($vo["id"]); ?>--<br/>

--<?php echo ($vo["name"]); ?>--<br/><?php endforeach; endif; ?>

可以看出,<foreach>标签最后的结果为PHP语法中的foreach循环,并且在循环前对数组进行了判断,之后进行打印.

ThinkPHP 模板的功能非常强大,可以自定义标签性质,引入标签库,在模板里注释也可以用"//""/**/"而不用理会模板扩展名为html.甚至可以在配置文件中修改定界符,例如实例中的{$vo},ThinkPHP默认定界符为{},我们可以自定义符号,比如"<{ }>",在使用中,就可以在这样"<{$vo}>"使用,原用法失效.为了防止混淆,尽量使用HTML语法里没有的符号或符号组合.同时,也可以自定义标签库的定界符,例如例子中的"<foreach>" 如果将定界符"< >"改为"[ ]",则必须这样使用"[foreach]"标签库函数.

在编译功能让人叹为观止的时候,如果使用JQuery就会遇到JQuery语法被错误解析成PHP的情况,因为JQuery语法里,筛选器中"$(this)"变量带有$,如果和"{}"一起用就会导致"{$"ThinkPHP错误解析成PHP变量,所以一个简单的方法就是在"{""$"中间隔一个空格因为ThinkPHP的模板引擎中"{$"连着是解析成PHP语法的.

同时还有两种方法可以避免这种情况,一个是使用内置的literal标签包含JS代码,<literal>JS代码</literal> 包含在literal标签中的代码将会直接输出,不进行任何解析,另外一个是定制模板引擎标签的定界符例如:'TMPL_L_DELIM'=>'<{','TMPL_R_DELIM'=>'}>'这样就和JQuery代码区别开来了。

ThinkPHP的模板引擎中,可以使用运算符,可以包含文件,可以使用函数,功能非常强大.

CodeIgniter是非编译型框架,所以视图view里的文件时以php为扩展名,view里面使用原生php语法,例如输出变量用"<?=$data ?>" 或者 "<?php echo $data; ?>"即可,没有过多的冗余.

下面附上ThinkPHP的编译过程:

加载公共入口文件
在实例化App类之前,我们需要首先加载系统的公共入口文件ThinkPHP.php,这个文件是ThinkPHP的总入口,让我们来一探究竟。在加载ThinkPHP.php文件的过程中,其实完成了下面的操作:
² 记录开始执行时间 $GLOBALS['_beginTime']
² 检测THINK_PATH定义,如果没有则创建;
² 检测项目名称APP_NAME,如果没有则按照一定规则自动定义;
² 检测项目编译缓存目录定义,没有则取项目的Temp目录;
² 加载系统定义文件defines.php和公共函数文件functions.php
² 如果项目编译缓存目录不存在,则自动创建项目目录结构;
² 加载系统核心类库(包括BaseAppActionModelViewThinkExceptionLog);
² 如果PHP版本低于5.2.0则加载兼容函数库compat.php
² 生成核心编译缓存~runtime.php
² 记录加载文件时间 $GLOBALS['_loadTime']
2、 项目初始化init
在加载完成ThinkPHP的公共入口文件之后,我们就开始执行应用了,而首先应该是初始化App应用。
² 设定错误和异常处理机制(set_error_handlerset_exception_handler);
² 项目预编译并载入;
² 设置时区支持;
² Session过滤器检查;
² session初始化;
² 检查并加载插件;
² URL分析和调度;
² 获取当前执行的模块和操作名;
² 加载模块配置文件;
² 页面防刷新机制检查;
² 语言检查并读取对应的语言文件;
² 模板检查并定义相关的模板变量;
² RBAC权限检测;
² 如果开启静态写入则读取静态缓存文件;
² 应用初始化过滤插件 app_init
² 记录应用初始化时间 $GLOBALS['_initTime']
3、 项目预编译
² 加载系统惯例配置文件convention.php
² 加载项目配置文件 config.php
² 加载项目公共文件 common.php
² 如果是调试模式加载系统调试配置文件 debug.php
² 如果定义了项目的调试配置文件则载入 debug.php
² 生成项目编译缓存文件~app.php
4、 URL分析Dispatcher
² 检查当前URL模式URL_MODEL
² 如果存在$_GET变量,则根据当前的URL模式和设置进行重定向;
² 进行路由定义检测;
² 分析PATH_INFOURL信息到数组;
² PATH_INFO得到的值和$_GET合并;
5、 获取模块和操作名
² 检查VAR_MODULE变量(包括GET POST),如果未定义,则获取默认模块名;
² 检查组件模块;
² 检查模块伪装;
² 检查VAR_ACTION变量(包括GET POST),如果未定义,则获取默认操作名;
² 检查操作链;
² 检查操作伪装;
6、 项目执行exec
² AUTO_LOAD_CLASS 检查 如果有则导入公共类;
² 实例化当前模块的Action控制器类;
² 如果Action控制器不存在则检查空模块 EmptyAction;
² 检查操作链,如果有执行操作链;
² 检查前置操作方法 _before_操作名;
² 执行模块的操作方法,调度转移给Action控制器;
² 执行后置操作方法 _after_操作名;
² 执行应用结束过滤器 app_end
² 如果开启日志记录,写入错误日志;
7、 执行控制器的操作
² 实例化视图类View
² 取得当前控制器名称;
² 控制器初始化_initialize
² 如果操作方法不存在检查空操作 _empty
² 如果空操作没有定义则检查对应的模板文件;
² 调用模型获取数据;
² 渲染视图进行输出;
8、 调用模型获取数据find
² 实例化模型类;
² 模型初始化 _initialize
² 判断当前模型名称和对应数据表;
² 实例化数据库操作对象;
² 数据表字段检测并缓存;
² 查询需要的数据;
² 判断是否视图模型;
² 如果是延时查询返回ResultIterator对象;
² 取出数据对象的时候记录乐观锁;
² 获取文本字段数据;
² 获取关联数据;
² 对数据对象自动编码转换;
² 记录当前数据对象;
² 返回定义的数据格式(数组或者stdClass对象)
9、 输出视图
² 模板变量赋值;
² 检测是否是布局输出;
² 检测页面输出编码;
² 缓存初始化过滤 ob_init;
² 页面缓存开启ob_start;
² 缓存开启后执行的过滤;
² 模版文件名过滤 template_file;
² 定位当前输出的模板文件;
² 模版变量过滤 template_var
² 根据不同模版引擎进行处理;
² 如果是PHP模板引擎,直接载入模板文件;
² 使用内置模板引擎,检测缓存有效期;
² 缓存无效则重新编译模板文件;
² 载入模板缓存文件;
² 获取并清空缓存;
² 输出编码转换;
² 输出过滤 ob_content
² 开启静态写入则写入静态文件;
² 如果输出则获取视图运行时间;
² 如果是display则渲染模板输出信息;
² 开启页面Trace则显示页面Trace信息;
² 如果是fetch则返回模板输出信息; 

第5章 结论

5.1  论文目的

ThinkPHPCodeIgniter 两个框架对非PHP爱好者来说,是比较陌生的,PHP程序员可能对其也进行过涉猎,不过都是掠影.PHP相关公司可能更多地是用公司自己的架构来编写网页和相关功能,本文目的在于让PHP爱好者更多的了解ThinkPHPCodelIgniter的一些功能,在自己使用中找到不足,发扬优点,填补缺陷.

5.1.1  使用习惯

论文通过将ThinkPHPCodeIgniter的一些操作进行了实例的操作,对一些基本操作也做了解释,有些人更习惯使用PHP的原生用法,则建议使用CodeIgniter框架,ThinkPHP框架虽然对PHP的一些语法进行了封装,这也使得一些对PHP不熟悉的人可以使用ThinkPHP框架开发出不错的网站,就像JAEESpring框架一样,使用高度封装的框架可以对程序语言本身不做太多了解即可使用.

5.1.2 网站效率

ThinkPHP是编译型框架,在第一次打开时会对页面进行编译,这一过程可能没有CodeIgniter打开的快,但是编译后的文件是纯PHP语法的文件,虽然我们没有大型网站测试的经验,但是多年的编程经验也知道,ThinkPHP编译后的网页打开效率是大于CodeIgniter打开的效率的,但是差别甚微,基本可以被网速忽略.同时这两个都是轻量级框架,CodeIgniter更轻量一些,所以大型的网站建议不要使用轻量级框架,会出现一些问题,不在叙述.

5.1.2 致初学者

对于PHP初学者,不建议使用框架编写网站,这样会导致PHP的语法混乱,建议先熟练掌握PHP原生语法后,在使用框架进行学习.

你可能感兴趣的:(ThinkPHP 与 CodeIgniter 开发框架的粗略简单不细致比较)