ThinkPHP的應用模式使得開發人員對核心框架進行改造較以往更為得心應手,並且可以讓你的應用適應更多的環境和不同的需求。每個應用模式都有自己的模式定義文件,相對於ThinkPHP3.1版本,ThinkPHP3.2版本對應用模式的擴展更加明確和清晰,在ThinkPHP3.1版本中定義了Cli、Lite、Thin、AMF、PHPRPC、REST模式,其定義方式和ThinkPHP3.2版本的方式大同小異,如有需要可以參考修改,其中Cli模式被ThinkPHP框架內置,不用單獨定義Cli模式即可正常使用,如需要更細化調整可以參考3.1版編寫的Cli運行模式擴展。ThinkPHP同樣提供了便捷的開發環境和正式環境的模式切換方式。讓我們隨著ThinkPHP的運行流程解析其應用模式擴展之謎。
一、應用模式的使用
在研究應用模式擴展之前,看看如何使用應用模式的吧。一般通過在入口文件定義常量APP_MODE為應用模式名稱,但是在分析ThinkPHP框架入口文件時,了解到框架默認采用模式為普通模式(common),而且可以自動識別sae環境,當然前提是沒有定義APP_MODE常量時,當然ThinkPHP可以自動識別CLI和CGI模式,並且在CLI和CGI環境下運行ThinkPHP框架在默認模式中自動對這兩種環境做了細微調整,當然也可以自己擴展這兩種應用模式。
if(function_exists('saeAutoLoader')){// 自動識別SAE環境
defined('APP_MODE') or define('APP_MODE', 'sae');
defined('STORAGE_TYPE') or define('STORAGE_TYPE', 'Sae');
}else{
defined('APP_MODE') or define('APP_MODE', 'common'); // 應用模式 默認為普通模式
defined('STORAGE_TYPE') or define('STORAGE_TYPE', 'File'); // 存儲類型 默認為File
}
二、應用模式定義
在ThinkPHP框架當中除了ThinkPHP框架入口和框架引導類以外,基本所有其他功能都可以通過應用模式進行更改和擴展,如果我們要增加一個應用模式,只需要在ThinkPHP\Mode目錄下面定義一個模式定義文件即可,我們可以通過分析common模式進行學習。該文件的代碼如下:
//文件路徑:ThinkPHP/Mode/common.php
/**
* ThinkPHP 普通模式定義
* 定義一個模式文件,只需要返回一個模式包含文件的數組即可
* 在數組中主要包含4種擴展文件列表:
* config 為默認加載配置文件列表
* alias 為核心類庫別名配置列表
* core 需要加載的核心函數和類文件列表
* tags 行為配置列表
*
* 如果在應用模式定義中加載一個自定類,那個自定義類的命名空間必須是Think
*/
return array(
// 配置文件
'config' => array(
THINK_PATH.'Conf/convention.php', // 系統慣例配置
CONF_PATH.'config.php', // 應用公共配置
),
// 別名定義
'alias' => array(
'Think\Log' => CORE_PATH . 'Log'.EXT,
'Think\Log\Driver\File' => CORE_PATH . 'Log/Driver/File'.EXT,
'Think\Exception' => CORE_PATH . 'Exception'.EXT,
'Think\Model' => CORE_PATH . 'Model'.EXT,
'Think\Db' => CORE_PATH . 'Db'.EXT,
'Think\Template' => CORE_PATH . 'Template'.EXT,
'Think\Cache' => CORE_PATH . 'Cache'.EXT,
'Think\Cache\Driver\File' => CORE_PATH . 'Cache/Driver/File'.EXT,
'Think\Storage' => CORE_PATH . 'Storage'.EXT,
),
// 函數和類文件
'core' => array(
THINK_PATH.'Common/functions.php',
COMMON_PATH.'Common/function.php',
CORE_PATH . 'Hook'.EXT,
CORE_PATH . 'App'.EXT,
CORE_PATH . 'Dispatcher'.EXT,
//CORE_PATH . 'Log'.EXT,
CORE_PATH . 'Route'.EXT,
CORE_PATH . 'Controller'.EXT,
CORE_PATH . 'View'.EXT,
BEHAVIOR_PATH . 'BuildLiteBehavior'.EXT,
BEHAVIOR_PATH . 'ParseTemplateBehavior'.EXT,
BEHAVIOR_PATH . 'ContentReplaceBehavior'.EXT,
),
// 行為擴展定義
'tags' => array(
'app_init' => array(
'Behavior\BuildLiteBehavior', // 生成運行Lite文件
),
'app_begin' => array(
'Behavior\ReadHtmlCacheBehavior', // 讀取靜態緩存
),
'app_end' => array(
'Behavior\ShowPageTraceBehavior', // 頁面Trace顯示
),
'view_parse' => array(
'Behavior\ParseTemplateBehavior', // 模板解析 支持PHP、內置模板引擎和第三方模板引擎
),
'template_filter'=> array(
'Behavior\ContentReplaceBehavior', // 模板輸出替換
),
'view_filter' => array(
'Behavior\WriteHtmlCacheBehavior', // 寫入靜態緩存
),
),
);
我們看到這個普通應用模式代碼之後,有點明了ThinkPHP的應用模式擴展是怎麼回事了,但是還是知其然而不知其所以然,定義一個加載文件列表和配置是如何改變框架核心的呢?秘密就在ThinkPHP引導類中,讓我們再回顧以下吧!
//判斷是否存在core.php配置文件(這是開發環境臨時定義的運行模式,我是這麼理解的)
//否者加載APP_MODE定義的模式文件
$mode = include is_file(CONF_PATH.'core.php')?CONF_PATH.'core.php':MODE_PATH.APP_MODE.'.php';
//加載模式中core定義的核心文件列表
foreach ($mode['core'] as $file){
if(is_file($file)) {
include $file;
if(!APP_DEBUG) $content .= compile($file);
}
}
//加載模式中定義的config配置文件列表
foreach ($mode['config'] as $key=>$file){
is_numeric($key)?C(include $file):C($key,include $file);
}
// 讀取當前應用模式對應的配置文件
if('common' != APP_MODE && is_file(CONF_PATH.'config_'.APP_MODE.'.php'))
C(include CONF_PATH.'config_'.APP_MODE.'.php');
// 加載模式中alias別名列表定義
if(isset($mode['alias'])){
self::addMap(is_array($mode['alias'])?$mode['alias']:include $mode['alias']);
}
// 加載應用別名定義文件
if(is_file(CONF_PATH.'alias.php'))
self::addMap(include CONF_PATH.'alias.php');
// 加載模式中tags行為定義
if(isset($mode['tags'])) {
Hook::import(is_array($mode['tags'])?$mode['tags']:include $mode['tags']);
}
// 加載應用行為定義
if(is_file(CONF_PATH.'tags.php'))
// 允許應用增加開發模式配置定義
Hook::import(include CONF_PATH.'tags.php');
// 加載框架底層語言包
L(include THINK_PATH.'Lang/'.strtolower(C('DEFAULT_LANG')).'.php');
通過ThinkPHP::start()中的這段代碼,完美無縫關聯的模式定義文件的意義與實現方法。
三、定義簡單的運行模式
手冊中有一個模式擴展到的實例,可以拿到這裡來分析一下,定義一個lite簡潔運行模式,首先在ThinkPHP/Mode目錄下新建一個lite.php文件內容定義如下:
return array(
// 配置文件
'config' => array(
THINK_PATH.'Conf/convention.php', // 系統慣例配置
CONF_PATH.'config.php', // 應用公共配置
),
// 別名定義
'alias' => array(
'Think\Exception' => CORE_PATH . 'Exception'.EXT,
'Think\Model' => CORE_PATH . 'Model'.EXT,
'Think\Db' => CORE_PATH . 'Db'.EXT,
'Think\Cache' => CORE_PATH . 'Cache'.EXT,
'Think\Cache\Driver\File' => CORE_PATH . 'Cache/Driver/File'.EXT,
'Think\Storage' => CORE_PATH . 'Storage'.EXT,
),
// 函數和類文件
'core' => array(
MODE_PATH.'Lite/functions.php',
COMMON_PATH.'Common/function.php',
MODE_PATH . 'Lite/App'.EXT,
MODE_PATH . 'Lite/Dispatcher'.EXT,
MODE_PATH . 'Lite/Controller'.EXT,
MODE_PATH . 'Lite/View'.EXT,
CORE_PATH . 'Behavior'.EXT,
),
// 行為擴展定義
'tags' => array(
'view_parse' => array(
'Behavior\ParseTemplate', // 模板解析 支持PHP、內置模板引擎和第三方模板引擎
),
'template_filter'=> array(
'Behavior\ContentReplace', // 模板輸出替換
),
),
);
從上面的配置當中我們發現core中的核心文件大多數都被替換了,當然這些需要被替換的程序功能需要我們自己去實現,不過建議大家直接拷貝普通模式中定義的核心文件過來修改。接下來我們來實現以下ThinkPHP應用開發中的核心類庫擴展文件App.class.php
在ThinkPHP/Mode目錄下建立一個Lite目錄並在lite目錄下建立App.class.php文件,以下是程序文件的實現:
//模式擴展類庫必須是Think命名空間
namespace Think;
/**
* ThinkPHP 應用程序類 執行應用過程管理 Lite模式擴展類
* 實現ThinkPHP核心類庫擴展時,盡可能仿造原有類庫實現(除非對ThinkPHP框架源碼特別了解)
* 因為在其他沒有擴展的核心文件中可能會調用擴展的核心類文件中的某個方法,除非你打算全部擴展
*/
class App{
/**
* 應用程序初始化
* @access public
* @return void
*/
static public function init() {
//具體現實
}
/**
* 執行應用程序
* @access public
* @return void
*/
static public function exec() {
//具體實現
}
/**
* 運行應用實例 入口文件使用的快捷方法
* @access public
* @return void
*/
static public function run() {
//具體實現
}
static public function logo(){
//具體實現
}
}
當文件所有擴展文件的實現後,可以在框架入口文件定義APP_MODE常量為lite。
另外需要注意一點,手冊當中要求定義的MODE_NAME常量來改變運行模式是之前3.1版本中定義運行模式的方法,使用新版本的用戶對此需要注意。