ThinkPHP2.0将支持项目以’分组模式’进行部署,这是一项激动人心的新功能特性,让我们在使用TP开发时,又再有了新的目录结构可供选择,而且在使用习惯上,我们并不需要作出多少改变,却会因此带来更多的便利、省心和项目资源可以更方便地共享等等许多好处。
本文将对此模式使用的各方面进行详细介绍,并强烈推荐各位TPer朋友使用 。
分组模式的目录结构
当使用分组模式时,目录结构主要区别在于 项目下的Lib/Action目录和Tpl模板目录。
Action目录下可以根据配置,使用类似下图的方式:
Action目录结构:

相应地,模板目录结构是下图的方式:
default目录结构

而生成的模板缓存,同样会对应模板目录结构。模板目录不限于你的分组设定,例如上图的Public分组公用目录。
上面这些结构示图,不用细说已可以很清晰地看出,我现在把自己的项目按类型细分成了以下几个分组去部署:
Home 前台,
Admin 后台,
Blog 博客模块
User 用户中心模块
——————-
分组模块的概念,并不局限于将项目区分为前台和后台。
你可以按自己所需类型,进行明确细致的区分,这样非常方便于项目管理和开发部署。
同时对于多个分组模块,都可以自由共享项目的基类库进行继承,例如图中的BaseAction.class.php,放置在Action目录下,无须手动引入便可以自动加载。
目前测试通过的是一级项目分组,假如你的项目结构确实非常庞大,你仍可以像以前那样,将整个项目区分为前台后台,然后前台后台再用分组模式部署再次进行细分。在使用上不会有任何冲突,并且对空模块、空操作等等功能没有任何影响和使用上的区别。
—————————
与之产生的目录,还可以有各个分组的
独自的函数目录, (Myapp/Common/Admin/function.php)
独自的配置目录, (Myapp/Conf/Admin/config.php)
Model下的分组目录
而且这些都不是必需存在,但却是允许你使用的。
在项目运行时,系统会自动加载所有共用的函数和配置,
如果检测到Common下有分组目录并且有定义function.php文件,
或者检测到Cofn目录下有分组对应的目录和config.php文件,
都会一一对应进行自动加载,让各个项目拥有自己私有的函数和配置。
对于Model类,如果需要,也可以进行分组处理,并且不必对应项目分组。比如要将视图类模型独立区分出来,可以在Model下建立一个View目录,然后使用D(‘View.UserView’)实例化模型,自动对应Model/View/UserViewModel.class.php类。包括这个连缀的. ,都是可以通过GROUP_DEPR进行配置。多个项目组之间的模型类,统一放在Model目录下,直接使用D(‘ModelName’);实例化就可以。
分组模式配置
分组模式有五个相关配置:
VAR_GROUP
获取项目分组名称的变量 默认是g,
例如:index.php?g=Admin&m=Index&a=edit
DEFAULT_GROUP
默认的项目分组名称,系统默认是’Home’,该设置的作用请看URL访问方式。
APP_GROUP_LIST
项目分组所有名称列表,默认为‘ ‘(空字符串),若不设置则表示不启用分组模式。
需要注意的是,即使你在这设置上定义成默认的‘Home’,也会自动开启分组功能。
如果是多个组,之间请用逗号分隔 例如 ‘Admin,Home,Blog,User’,其中默认模式可以不用配置(建议也写上)。
项目分组名称配置不限大小写,会最终统一为首字母大写其余字母小写的形式。
APP_GROUP_DEPR
项目分组之间的分割符,默认是 . (点),用于A函数 D函数 和 路由配置中的分隔,往下阅读会有示例
TMPL_FILE_DEPR
模板文件MODULE_NAME与ACTION_NAME之间的分割符,默认是’/',只对项目分组部署有效
该设置同时也是语言文件中分组语言定义与语言文件之间的分隔符。
例如,当配置此参数为 _ 时,以Admin分组Index模块add操作说明:
1 对应的模板文件不再是下面所指的 Tpl/default/Admin/Index/add.html,
而是 Tpl/default/Admin/Index_add.html,通过这个配置,使模板目录结构减少了一层目录。
2 对应的分组语言定义文件也一样,默认的 AppName/Lang/Admin/lang.php会成为 Lang/Admin_lang.php
————————————————————————
要为分组项目添加独自的配置,可以在Conf目录下,建立与项目组名称相同的目录,注意目录命名格式是分组名称的首字母大写+其余字母小写的形式。
当分组名称的目录下有定义config.php文件时,每次访问该分组,会自动添加上分组的独立配置,并且会覆盖公共配置的设定。
(ps:HTML_URL_SUFFIX配置在系统开始处理URL调度时不会覆盖默认值,在项目应用中在会生效)
————————————————————————-
URL访问方式
如果启用了分组部署,多个分组全都会采用同一个入口文件进行访问的形式,因此在URL访问上会有一点区别,除了默认指定的项目名称外,其它的分组模块访问要在入口位置后加上一个项目组名称。
访问格式是:
域名/入口文件所在位置/项目组名称/模块名称/操作名称/变量名1/变量值1/更多参数
如果分组名称是所设定的默认项目分组名,分组名称可以省略不写。
如果开启了URL_CASE_INSENSITIVE,在URL中分组名称可以不区分大小写。
示例模拟:
假设域名是:tp.com,入口文件在根目录,配置上开启了rewrite功能和PATHINFO模式其它默认,分组如上列图,默认分组设置是Home,各种访问形式如下。
访问Home分组Index模块index操作。Home作为默认名称可以省略,当然,写上去也没关系。
http://tp.com/
http://tp.com/Index/
http://tp.com/Index/index
http://tp.com/index.php/
http://tp.com/index.php/Index/
http://tp.com/index.php/Index/index
http://tp.com/index.php/Home/
http://tp.com/Home/
可用形式可参考手册,默认分组是没有区别的。理解原理就行。或者看附件示例源码。
访问Admin分组/Index模块index操作
http://tp.com/Admin/
访问Admin分组/Other模块edit操作
http://tp.com/Admin/Other/edit
分组模式同样支持PATH_DEPR设置和静态配置等,例如设置PATH_DEPR为 _ 时,上面的访问URL可以变成
http://tp.com/Admin_Other_edit
跳转
跳转时,使用U函数或在Action中调用$this->redirect()方法时,分组名称与模块名称之间使用 – 作为分隔。
假设当前是默认分组的Index模块index操作
跳转到当前模块的edit操作
$this->redirect(‘edit’);
跳转到Admin分组默认模块默认操作
$this->redirect(‘Admin/’);
跳转到Admin分组默认模块其它操作
$this->redirect(‘Admin-Index/other’);
跳转到多项目部署+分组形式的 Newapp项目User分组A模块b操作
$this->redirect(‘Newapp://User-A/b’);
a标签href链接:
- <a href=”__APP__/Admin/Other/abc” title=”xxx”>Admin分组Other模块abc操作</a>
复制代码
从上面所有示例可以看出,唯一区别是多了一个分组项目名称的概念。
——————-
路由使用
路由的使用对于默认分组来说和原来的没有什么不同。(路由知识请参看手册)
非默认分组,只需要在格式中的模块项前加上一个项目组名称标识。
例如常规路由:
‘system’=>array(‘Admin.Index’,'routes1′,’id’),
这样就将Admin分组的Index模块routes1操作以system作为路由名称,使用这样的URL地址访问
http://tp.com/system/2
就会传入一个$_GET['id']变量到Admin分组Index模块routes1操作。
同样,下面的泛路由配置:
- ‘abc@’=>array(
- array(‘/^\/(\d+)(\/p\/\d)?$/’,'Admin.Index’,'routes2′,’id’),
- array(‘/^\/(\d+)\/(\d+)/’,'Admin.Index’,'routes2′,’year,month’),
- ),
复制代码
当使用http://tp.com/abc/123这样的url去访问,就会传入一个$_GET['id']变量到Admin分组Index模块routes2操作。
如果使用http://tp.com/abc/2009/06的url去访问,则是传入了两个变量year和month。
具体可以参看附件示例。
同样建议如果使用路由定义,即使是对于默认分组,也在模块参数中进行显式指定(不指定也没关系)
模板调用
模板调用方面由于使用了分组模式,需要注意调用路径的区别。
默认调用模板
当使用$this->display();对应的格式是
default/分组名/模块名/操作名.html
例如在Home分组中Index模块index操作像上面那样不传入任何参数调用。默认对应的是
default/Home/Index/index.html
虽然Home是默认的分组名称,可以不在URL中书写,但是Home分组中所有操作的模板仍然会对应Home目录。这点必须引起注意。
指定模板
调用当前项目组Other模块abc操作的abc.html
display(‘Other/abc’);
跨项目组调用
在Home项目中调用Admin项目组的Index模块add操作的模板文件add.html
display(‘Admin:Index/add’);
模板目录定制
如果不喜欢将模板目录分得太深,或有需要,可以指定模板分隔符参数,参看上面的参数说明,
项目公用目录Public相关
至于Public目录,__PUBLIC__常量,..Public/路径,无论是否启用分组部署模式,对应位置还是和原来一样的(包括__TMPL__)。
需要注意的是,如果你习惯定义PublicAction.class.php,在这个Action中定义了login登录这些操作。务必注意模板对应位置。
例如在Home分组中定义了PublicAction类,相应的默认位置是在default/Home/Public下,而不是系统定义的公用目录default/Public。
另外,对于默认的$this->success();和$this->error();的模板文件,需要放在default/Public下。
我们大可以利用这个机制,另各个项目组对以上操作提示使用不同的样式,拥有风格不同的提示模板。
要使用默认的话,不定义这些操作就可以。
inculde标签使用
同上面的原理,使用inculde标签时要注意
在分组项目中的模板,例如Admin分组中的模板里如果使用
- <include file=”public:header” />
复制代码
引入的是default/Admin/Public/header.html。
如果要引入系统定义的公用目录下的header.html,可以使用
- <include file=”Public@header” />
复制代码
对应引入的就是default/Public/header.html
好好利用这个特性,就可以做到分组既有共同的Public目录。又有不同于其它分组的独自的Public公共目录,更灵活和更方便了。
模板缓存
模板缓存的区别可以不理会,因为是系统自动定位使用的。当想查看缓存时,直接在cache中找到该项目组目录就是了。
况且现在的Trace信息,会显示具体的模板缓存文件位置及名称。
——————–
远程调用
A函数的使用和D函数一样:
默认项目组的User模块
A(‘User’);
Admin项目组的Abc模块
A(‘Admin.Abc’);
——————–
总结
使用了分组项目部署的区别总的说来仅仅是多了一个项目组目录概念,
不要因为此文概括出这么多而觉得,哎,怎么这样麻烦呀,其实只要谨记这一点区别,其它的使用对于你都已不成问题。
对比多项目方式的部署,它解决了整个项目的公用函数,公用配置,公用模板和公用图片整合,公用语言定义,公用Model,公用数据缓存等等的麻烦。在结构上目录也更清晰。而且相对说来,还少了重复的缓存生成,少了重复的一些目录结构。同时由于唯一的单一入口,在程序运行上的某些逻辑也会容易很多。
在合多而为一的基础上,可扩展的可能性也更多了。相信官方会在以后,针对此部署方式,在TP最大宗旨‘不影响效率和性能’的大前提下,会添加更多可利用的性能。
对于此种模式在使用上的任何不便或有更好建议,大家可以提出来然后一起想办法解决和实现,这样TP的应用就会越来越舒服。
ps:新添了2篇与分组模式相关的使用技巧:
http://bbs.thinkphp.cn/viewthread.php?tid=7293&extra=
http://bbs.thinkphp.cn/viewthread.php?tid=7304&extra=page%3D1
———
示例备注:示例中涉及到的模板调用演示,直接利用了TP的模板调用出错提示,注意看提示的路径就可以,懒得写模板了
另外,示例中的ThinkPHP核心,已是旧的,分组部署功能现在已作了更多的完善,具体可参看svn更新说明。所以示例现在仅只是演示如何使用分组,配置名称及U函数调用方式等已有所改变。具体可查看ThinkPHP2.0完全手册上相关说明。 ThinkPHP2.0将支持项目以’分组模式‘进行部署,这是一项激动人心的新功能特性,让我们在使用TP开发时,又再有了新的目录结构可供选择,而且在使用习惯上,我们并不需要作出多少改变,却会因此带来更多的便利、省心和项目资源可以更方便地共享等等许多好处。
本文将对此模式使用的各方面进行详细介绍,并强烈推荐各位TPer朋友使用 。
分组模式的目录结构
当使用分组模式时,目录结构主要区别在于 项目下的Lib/Action目录和Tpl模板目录。
Action目录下可以根据配置,使用类似下图的方式:
Action目录结构:

相应地,模板目录结构是下图的方式:
default目录结构

而生成的模板缓存,同样会对应模板目录结构。模板目录不限于你的分组设定,例如上图的Public分组公用目录。
上面这些结构示图,不用细说已可以很清晰地看出,我现在把自己的项目按类型细分成了以下几个分组去部署:
Home 前台,
Admin 后台,
Blog 博客模块
User 用户中心模块
——————-
分组模块的概念,并不局限于将项目区分为前台和后台。
你可以按自己所需类型,进行明确细致的区分,这样非常方便于项目管理和开发部署。
同时对于多个分组模块,都可以自由共享项目的基类库进行继承,例如图中的BaseAction.class.php,放置在Action目录下,无须手动引入便可以自动加载。
目前测试通过的是一级项目分组,假如你的项目结构确实非常庞大,你仍可以像以前那样,将整个项目区分为前台后台,然后前台后台再用分组模式部署再次进行细分。在使用上不会有任何冲突,并且对空模块、空操作等等功能没有任何影响和使用上的区别。
—————————
与之产生的目录,还可以有各个分组的
独自的函数目录, (Myapp/Common/Admin/function.php)
独自的配置目录, (Myapp/Conf/Admin/config.php)
Model下的分组目录
而且这些都不是必需存在,但却是允许你使用的。
在项目运行时,系统会自动加载所有共用的函数和配置,
如果检测到Common下有分组目录并且有定义function.php文件,
或者检测到Cofn目录下有分组对应的目录和config.php文件,
都会一一对应进行自动加载,让各个项目拥有自己私有的函数和配置。
对于Model类,如果需要,也可以进行分组处理,并且不必对应项目分组。比如要将视图类模型独立区分出来,可以在Model下建立一个View目录,然后使用D(‘View.UserView’)实例化模型,自动对应Model/View/UserViewModel.class.php类。包括这个连缀的. ,都是可以通过GROUP_DEPR进行配置。多个项目组之间的模型类,统一放在Model目录下,直接使用D(‘ModelName’);实例化就可以。
分组模式配置
分组模式有五个相关配置:
VAR_GROUP
获取项目分组名称的变量 默认是g,
例如:index.php?g=Admin&m=Index&a=edit
DEFAULT_GROUP
默认的项目分组名称,系统默认是’Home’,该设置的作用请看URL访问方式。
APP_GROUP_LIST
项目分组所有名称列表,默认为‘ ‘(空字符串),若不设置则表示不启用分组模式。
需要注意的是,即使你在这设置上定义成默认的‘Home’,也会自动开启分组功能。
如果是多个组,之间请用逗号分隔 例如 ‘Admin,Home,Blog,User’,其中默认模式可以不用配置(建议也写上)。
项目分组名称配置不限大小写,会最终统一为首字母大写其余字母小写的形式。
APP_GROUP_DEPR
项目分组之间的分割符,默认是 . (点),用于A函数 D函数 和 路由配置中的分隔,往下阅读会有示例
TMPL_FILE_DEPR
模板文件MODULE_NAME与ACTION_NAME之间的分割符,默认是’/',只对项目分组部署有效
该设置同时也是语言文件中分组语言定义与语言文件之间的分隔符。
例如,当配置此参数为 _ 时,以Admin分组Index模块add操作说明:
1 对应的模板文件不再是下面所指的 Tpl/default/Admin/Index/add.html,
而是 Tpl/default/Admin/Index_add.html,通过这个配置,使模板目录结构减少了一层目录。
2 对应的分组语言定义文件也一样,默认的 AppName/Lang/Admin/lang.php会成为 Lang/Admin_lang.php
————————————————————————
要为分组项目添加独自的配置,可以在Conf目录下,建立与项目组名称相同的目录,注意目录命名格式是分组名称的首字母大写+其余字母小写的形式。
当分组名称的目录下有定义config.php文件时,每次访问该分组,会自动添加上分组的独立配置,并且会覆盖公共配置的设定。
(ps:HTML_URL_SUFFIX配置在系统开始处理URL调度时不会覆盖默认值,在项目应用中在会生效)
————————————————————————-
URL访问方式
如果启用了分组部署,多个分组全都会采用同一个入口文件进行访问的形式,因此在URL访问上会有一点区别,除了默认指定的项目名称外,其它的分组模块访问要在入口位置后加上一个项目组名称。
访问格式是:
域名/入口文件所在位置/项目组名称/模块名称/操作名称/变量名1/变量值1/更多参数
如果分组名称是所设定的默认项目分组名,分组名称可以省略不写。
如果开启了URL_CASE_INSENSITIVE,在URL中分组名称可以不区分大小写。
示例模拟:
假设域名是:tp.com,入口文件在根目录,配置上开启了rewrite功能和PATHINFO模式其它默认,分组如上列图,默认分组设置是Home,各种访问形式如下。
访问Home分组Index模块index操作。Home作为默认名称可以省略,当然,写上去也没关系。
http://tp.com/
http://tp.com/Index/
http://tp.com/Index/index
http://tp.com/index.php/
http://tp.com/index.php/Index/
http://tp.com/index.php/Index/index
http://tp.com/index.php/Home/
http://tp.com/Home/
可用形式可参考手册,默认分组是没有区别的。理解原理就行。或者看附件示例源码。
访问Admin分组/Index模块index操作
http://tp.com/Admin/
访问Admin分组/Other模块edit操作
http://tp.com/Admin/Other/edit
分组模式同样支持PATH_DEPR设置和静态配置等,例如设置PATH_DEPR为 _ 时,上面的访问URL可以变成
http://tp.com/Admin_Other_edit
跳转
跳转时,使用U函数或在Action中调用$this->redirect()方法时,分组名称与模块名称之间使用 – 作为分隔。
假设当前是默认分组的Index模块index操作
跳转到当前模块的edit操作
$this->redirect(‘edit’);
跳转到Admin分组默认模块默认操作
$this->redirect(‘Admin/’);
跳转到Admin分组默认模块其它操作
$this->redirect(‘Admin-Index/other’);
跳转到多项目部署+分组形式的 Newapp项目User分组A模块b操作
$this->redirect(‘Newapp://User-A/b’);
a标签href链接:
- <a href=”__APP__/Admin/Other/abc” title=”xxx”>Admin分组Other模块abc操作</a>
复制代码
从上面所有示例可以看出,唯一区别是多了一个分组项目名称的概念。
——————-
路由使用
路由的使用对于默认分组来说和原来的没有什么不同。(路由知识请参看手册)
非默认分组,只需要在格式中的模块项前加上一个项目组名称标识。
例如常规路由:
‘system’=>array(‘Admin.Index’,'routes1′,’id’),
这样就将Admin分组的Index模块routes1操作以system作为路由名称,使用这样的URL地址访问
http://tp.com/system/2
就会传入一个$_GET['id']变量到Admin分组Index模块routes1操作。
同样,下面的泛路由配置:
- ‘abc@’=>array(
- array(‘/^\/(\d+)(\/p\/\d)?$/’,'Admin.Index’,'routes2′,’id’),
- array(‘/^\/(\d+)\/(\d+)/’,'Admin.Index’,'routes2′,’year,month’),
- ),
复制代码
当使用http://tp.com/abc/123这样的url去访问,就会传入一个$_GET['id']变量到Admin分组Index模块routes2操作。
如果使用http://tp.com/abc/2009/06的url去访问,则是传入了两个变量year和month。
具体可以参看附件示例。
同样建议如果使用路由定义,即使是对于默认分组,也在模块参数中进行显式指定(不指定也没关系)
模板调用
模板调用方面由于使用了分组模式,需要注意调用路径的区别。
默认调用模板
当使用$this->display();对应的格式是
default/分组名/模块名/操作名.html
例如在Home分组中Index模块index操作像上面那样不传入任何参数调用。默认对应的是
default/Home/Index/index.html
虽然Home是默认的分组名称,可以不在URL中书写,但是Home分组中所有操作的模板仍然会对应Home目录。这点必须引起注意。
指定模板
调用当前项目组Other模块abc操作的abc.html
display(‘Other/abc’);
跨项目组调用
在Home项目中调用Admin项目组的Index模块add操作的模板文件add.html
display(‘Admin:Index/add’);
模板目录定制
如果不喜欢将模板目录分得太深,或有需要,可以指定模板分隔符参数,参看上面的参数说明,
项目公用目录Public相关
至于Public目录,__PUBLIC__常量,..Public/路径,无论是否启用分组部署模式,对应位置还是和原来一样的(包括__TMPL__)。
需要注意的是,如果你习惯定义PublicAction.class.php,在这个Action中定义了login登录这些操作。务必注意模板对应位置。
例如在Home分组中定义了PublicAction类,相应的默认位置是在default/Home/Public下,而不是系统定义的公用目录default/Public。
另外,对于默认的$this->success();和$this->error();的模板文件,需要放在default/Public下。
我们大可以利用这个机制,另各个项目组对以上操作提示使用不同的样式,拥有风格不同的提示模板。
要使用默认的话,不定义这些操作就可以。
inculde标签使用
同上面的原理,使用inculde标签时要注意
在分组项目中的模板,例如Admin分组中的模板里如果使用
- <include file=”public:header” />
复制代码
引入的是default/Admin/Public/header.html。
如果要引入系统定义的公用目录下的header.html,可以使用
- <include file=”Public@header” />
复制代码
对应引入的就是default/Public/header.html
好好利用这个特性,就可以做到分组既有共同的Public目录。又有不同于其它分组的独自的Public公共目录,更灵活和更方便了。
模板缓存
模板缓存的区别可以不理会,因为是系统自动定位使用的。当想查看缓存时,直接在cache中找到该项目组目录就是了。
况且现在的Trace信息,会显示具体的模板缓存文件位置及名称。
——————–
远程调用
A函数的使用和D函数一样:
默认项目组的User模块
A(‘User’);
Admin项目组的Abc模块
A(‘Admin.Abc’);
——————–
总结
使用了分组项目部署的区别总的说来仅仅是多了一个项目组目录概念,
不要因为此文概括出这么多而觉得,哎,怎么这样麻烦呀,其实只要谨记这一点区别,其它的使用对于你都已不成问题。
对比多项目方式的部署,它解决了整个项目的公用函数,公用配置,公用模板和公用图片整合,公用语言定义,公用Model,公用数据缓存等等的麻烦。在结构上目录也更清晰。而且相对说来,还少了重复的缓存生成,少了重复的一些目录结构。同时由于唯一的单一入口,在程序运行上的某些逻辑也会容易很多。
在合多而为一的基础上,可扩展的可能性也更多了。相信官方会在以后,针对此部署方式,在TP最大宗旨‘不影响效率和性能’的大前提下,会添加更多可利用的性能。
对于此种模式在使用上的任何不便或有更好建议,大家可以提出来然后一起想办法解决和实现,这样TP的应用就会越来越舒服。
ps:新添了2篇与分组模式相关的使用技巧:
http://bbs.thinkphp.cn/viewthread.php?tid=7293&extra=
http://bbs.thinkphp.cn/viewthread.php?tid=7304&extra=page%3D1
———
示例备注:示例中涉及到的模板调用演示,直接利用了TP的模板调用出错提示,注意看提示的路径就可以,懒得写模板了
另外,示例中的ThinkPHP核心,已是旧的,分组部署功能现在已作了更多的完善,具体可参看svn更新说明。所以示例现在仅只是演示如何使用分组,配置名称及U函数调用方式等已有所改变。具体可查看ThinkPHP2.0完全手册上相关说明。

[...] http://www.cotrun.net/blog/1377.html TP2.0 之分组模式项目部署 [...]