热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ThinkPHP中的跨控制器调用与框架执行流程

一、跨控制器调用UserController.class.php

一、跨控制器调用


  • UserController.class.php

phpnamespace Home/Controlleruse Think/Controllerclass UserController extends Controller{public function show(){//TODO
}}

  • IndexController.class.php(方法一)

phpnamespace Home/Controlleruse Think/Controllerclass IndexController extends Controller{public function count(){//通过快捷函数来实例化一个控制器//User为控制器名$user = A('User');$user-> show();}}

  • IndexController.class.php(方法二)

phpnamespace Home/Controlleruse Think/Controllerclass IndexController extends Controller{public function count(){//User为控制器名,show为其方法R('User/show');}}

二、ThinkPHP执行流程


当一个客户端发起一个请求的时候先去访问应用入口文件

php
// 应用入口文件// 检测PHP环境
if(version_compare(PHP_VERSION,&#39;5.3.0&#39;,&#39;<&#39;)) die(&#39;require PHP > 5.3.0 !&#39;);// 开启调试模式 建议开发阶段开启 部署阶段注释或者设为false
define(&#39;APP_DEBUG&#39;,True);// 引入ThinkPHP入口文件
require &#39;../../ThinkPHP/ThinkPHP.php&#39;;

在应用入口文件中引入TinkPHP框架的入口文件&#xff0c;然后执行该文件中的代码。

在TinkPHP.php中做了一些初始化操作&#xff0c;比如定义了大量的全局常量&#xff0c;运行环境检测等

  • ThinkPHP.php

php
// 记录开始运行时间
$GLOBALS[&#39;_beginTime&#39;] &#61; microtime(TRUE);
// 记录内存初始使用
define(&#39;MEMORY_LIMIT_ON&#39;,function_exists(&#39;memory_get_usage&#39;));
if(MEMORY_LIMIT_ON) $GLOBALS[&#39;_startUseMems&#39;] &#61; memory_get_usage();// 版本信息
const THINK_VERSION &#61; &#39;3.2.3&#39;;// URL 模式定义
const URL_COMMON &#61; 0; //普通模式
const URL_PATHINFO &#61; 1; //PATHINFO模式
const URL_REWRITE &#61; 2; //REWRITE模式
const URL_COMPAT &#61; 3; // 兼容模式// 类文件后缀
const EXT &#61; &#39;.class.php&#39;; // 系统常量定义
defined(&#39;THINK_PATH&#39;) or define(&#39;THINK_PATH&#39;, __DIR__.&#39;/&#39;);
defined(&#39;APP_PATH&#39;) or define(&#39;APP_PATH&#39;, dirname($_SERVER[&#39;SCRIPT_FILENAME&#39;]).&#39;/&#39;);
defined(&#39;APP_STATUS&#39;) or define(&#39;APP_STATUS&#39;, &#39;&#39;); // 应用状态 加载对应的配置文件
defined(&#39;APP_DEBUG&#39;) or define(&#39;APP_DEBUG&#39;, false); // 是否调试模式if(function_exists(&#39;saeAutoLoader&#39;)){// 自动识别SAE环境defined(&#39;APP_MODE&#39;) or define(&#39;APP_MODE&#39;, &#39;sae&#39;);defined(&#39;STORAGE_TYPE&#39;) or define(&#39;STORAGE_TYPE&#39;, &#39;Sae&#39;);
}
else{defined(&#39;APP_MODE&#39;) or define(&#39;APP_MODE&#39;, &#39;common&#39;); // 应用模式 默认为普通模式 defined(&#39;STORAGE_TYPE&#39;) or define(&#39;STORAGE_TYPE&#39;, &#39;File&#39;); // 存储类型 默认为File
}defined(&#39;RUNTIME_PATH&#39;) or define(&#39;RUNTIME_PATH&#39;, APP_PATH.&#39;Runtime/&#39;); // 系统运行时目录
defined(&#39;LIB_PATH&#39;) or define(&#39;LIB_PATH&#39;, realpath(THINK_PATH.&#39;Library&#39;).&#39;/&#39;); // 系统核心类库目录
defined(&#39;CORE_PATH&#39;) or define(&#39;CORE_PATH&#39;, LIB_PATH.&#39;Think/&#39;); // Think类库目录
defined(&#39;BEHAVIOR_PATH&#39;)or define(&#39;BEHAVIOR_PATH&#39;, LIB_PATH.&#39;Behavior/&#39;); // 行为类库目录
defined(&#39;MODE_PATH&#39;) or define(&#39;MODE_PATH&#39;, THINK_PATH.&#39;Mode/&#39;); // 系统应用模式目录
defined(&#39;VENDOR_PATH&#39;) or define(&#39;VENDOR_PATH&#39;, LIB_PATH.&#39;Vendor/&#39;); // 第三方类库目录
defined(&#39;COMMON_PATH&#39;) or define(&#39;COMMON_PATH&#39;, APP_PATH.&#39;Common/&#39;); // 应用公共目录
defined(&#39;CONF_PATH&#39;) or define(&#39;CONF_PATH&#39;, COMMON_PATH.&#39;Conf/&#39;); // 应用配置目录
defined(&#39;LANG_PATH&#39;) or define(&#39;LANG_PATH&#39;, COMMON_PATH.&#39;Lang/&#39;); // 应用语言目录
defined(&#39;HTML_PATH&#39;) or define(&#39;HTML_PATH&#39;, APP_PATH.&#39;Html/&#39;); // 应用静态目录
defined(&#39;LOG_PATH&#39;) or define(&#39;LOG_PATH&#39;, RUNTIME_PATH.&#39;Logs/&#39;); // 应用日志目录
defined(&#39;TEMP_PATH&#39;) or define(&#39;TEMP_PATH&#39;, RUNTIME_PATH.&#39;Temp/&#39;); // 应用缓存目录
defined(&#39;DATA_PATH&#39;) or define(&#39;DATA_PATH&#39;, RUNTIME_PATH.&#39;Data/&#39;); // 应用数据目录
defined(&#39;CACHE_PATH&#39;) or define(&#39;CACHE_PATH&#39;, RUNTIME_PATH.&#39;Cache/&#39;); // 应用模板缓存目录
defined(&#39;CONF_EXT&#39;) or define(&#39;CONF_EXT&#39;, &#39;.php&#39;); // 配置文件后缀
defined(&#39;CONF_PARSE&#39;) or define(&#39;CONF_PARSE&#39;, &#39;&#39;); // 配置文件解析方法
defined(&#39;ADDON_PATH&#39;) or define(&#39;ADDON_PATH&#39;, APP_PATH.&#39;Addon&#39;);// 系统信息
if(version_compare(PHP_VERSION,&#39;5.4.0&#39;,&#39;<&#39;)) {ini_set(&#39;magic_quotes_runtime&#39;,0);define(&#39;MAGIC_QUOTES_GPC&#39;,get_magic_quotes_gpc()? true : false);
}
else{define(&#39;MAGIC_QUOTES_GPC&#39;,false);
}
define(&#39;IS_CGI&#39;,(0 &#61;&#61;&#61; strpos(PHP_SAPI,&#39;cgi&#39;) || false !&#61;&#61; strpos(PHP_SAPI,&#39;fcgi&#39;)) ? 1 : 0 );
define(&#39;IS_WIN&#39;,strstr(PHP_OS, &#39;WIN&#39;) ? 1 : 0 );
define(&#39;IS_CLI&#39;,PHP_SAPI&#61;&#61;&#39;cli&#39;? 1 : 0);if(!IS_CLI) {// 当前文件名if(!defined(&#39;_PHP_FILE_&#39;)) {if(IS_CGI) {//CGI/FASTCGI模式下$_temp &#61; explode(&#39;.php&#39;,$_SERVER[&#39;PHP_SELF&#39;]);define(&#39;_PHP_FILE_&#39;, rtrim(str_replace($_SERVER[&#39;HTTP_HOST&#39;],&#39;&#39;,$_temp[0].&#39;.php&#39;),&#39;/&#39;));}else {define(&#39;_PHP_FILE_&#39;, rtrim($_SERVER[&#39;SCRIPT_NAME&#39;],&#39;/&#39;));}}if(!defined(&#39;__ROOT__&#39;)) {$_root &#61; rtrim(dirname(_PHP_FILE_),&#39;/&#39;);define(&#39;__ROOT__&#39;, (($_root&#61;&#61;&#39;/&#39; || $_root&#61;&#61;&#39;\\&#39;)?&#39;&#39;:$_root));}
}
// 加载核心Think类 ThinkPHP/Library/Think/Think.class.php
require CORE_PATH.&#39;Think&#39;.EXT;
// 应用初始化,调用Think类的静态方法start()
Think\Think::start();

  • Think.class.php

1 php
2
3 namespace Think;
4 /**
5 * ThinkPHP 控制器基类 抽象类
6 */
7 abstract class Controller {
8
9 /**
10 * 视图实例对象
11 * &#64;var view
12 * &#64;access protected
13 */
14 protected $view &#61; null;
15
16 /**
17 * 控制器参数
18 * &#64;var config
19 * &#64;access protected
20 */
21 protected $config &#61; array();
22
23 /**
24 * 架构函数 取得模板对象实例
25 * &#64;access public
26 */
27 public function __construct() {
28 Hook::listen(&#39;action_begin&#39;,$this->config);
29 //实例化视图类
30 $this->view &#61; Think::instance(&#39;Think\View&#39;);
31 //控制器初始化
32 if(method_exists($this,&#39;_initialize&#39;))
33 $this->_initialize();
34 }
35
36 /**
37 * 模板显示 调用内置的模板引擎显示方法&#xff0c;
38 * &#64;access protected
39 * &#64;param string $templateFile 指定要调用的模板文件
40 * 默认为空 由系统自动定位模板文件
41 * &#64;param string $charset 输出编码
42 * &#64;param string $contentType 输出类型
43 * &#64;param string $content 输出内容
44 * &#64;param string $prefix 模板缓存前缀
45 * &#64;return void
46 */
47 protected function display($templateFile&#61;&#39;&#39;,$charset&#61;&#39;&#39;,$contentType&#61;&#39;&#39;,$content&#61;&#39;&#39;,$prefix&#61;&#39;&#39;) {
48 $this->view->display($templateFile,$charset,$contentType,$content,$prefix);
49 }
50
51 /**
52 * 输出内容文本可以包括Html 并支持内容解析
53 * &#64;access protected
54 * &#64;param string $content 输出内容
55 * &#64;param string $charset 模板输出字符集
56 * &#64;param string $contentType 输出类型
57 * &#64;param string $prefix 模板缓存前缀
58 * &#64;return mixed
59 */
60 protected function show($content,$charset&#61;&#39;&#39;,$contentType&#61;&#39;&#39;,$prefix&#61;&#39;&#39;) {
61 $this->view->display(&#39;&#39;,$charset,$contentType,$content,$prefix);
62 }
63
64 /**
65 * 获取输出页面内容
66 * 调用内置的模板引擎fetch方法&#xff0c;
67 * &#64;access protected
68 * &#64;param string $templateFile 指定要调用的模板文件
69 * 默认为空 由系统自动定位模板文件
70 * &#64;param string $content 模板输出内容
71 * &#64;param string $prefix 模板缓存前缀*
72 * &#64;return string
73 */
74 protected function fetch($templateFile&#61;&#39;&#39;,$content&#61;&#39;&#39;,$prefix&#61;&#39;&#39;) {
75 return $this->view->fetch($templateFile,$content,$prefix);
76 }
77
78 /**
79 * 创建静态页面
80 * &#64;access protected
81 * &#64;htmlfile 生成的静态文件名称
82 * &#64;htmlpath 生成的静态文件路径
83 * &#64;param string $templateFile 指定要调用的模板文件
84 * 默认为空 由系统自动定位模板文件
85 * &#64;return string
86 */
87 protected function buildHtml($htmlfile&#61;&#39;&#39;,$htmlpath&#61;&#39;&#39;,$templateFile&#61;&#39;&#39;) {
88 $content &#61; $this->fetch($templateFile);
89 $htmlpath &#61; !empty($htmlpath)?$htmlpath:HTML_PATH;
90 $htmlfile &#61; $htmlpath.$htmlfile.C(&#39;HTML_FILE_SUFFIX&#39;);
91 Storage::put($htmlfile,$content,&#39;html&#39;);
92 return $content;
93 }
94
95 /**
96 * 模板主题设置
97 * &#64;access protected
98 * &#64;param string $theme 模版主题
99 * &#64;return Action
100 */
101 protected function theme($theme){
102 $this->view->theme($theme);
103 return $this;
104 }
105
106 /**
107 * 模板变量赋值
108 * &#64;access protected
109 * &#64;param mixed $name 要显示的模板变量
110 * &#64;param mixed $value 变量的值
111 * &#64;return Action
112 */
113 protected function assign($name,$value&#61;&#39;&#39;) {
114 $this->view->assign($name,$value);
115 return $this;
116 }
117
118 public function __set($name,$value) {
119 $this->assign($name,$value);
120 }
121
122 /**
123 * 取得模板显示变量的值
124 * &#64;access protected
125 * &#64;param string $name 模板显示变量
126 * &#64;return mixed
127 */
128 public function get($name&#61;&#39;&#39;) {
129 return $this->view->get($name);
130 }
131
132 public function __get($name) {
133 return $this->get($name);
134 }
135
136 /**
137 * 检测模板变量的值
138 * &#64;access public
139 * &#64;param string $name 名称
140 * &#64;return boolean
141 */
142 public function __isset($name) {
143 return $this->get($name);
144 }
145
146 /**
147 * 魔术方法 有不存在的操作的时候执行
148 * &#64;access public
149 * &#64;param string $method 方法名
150 * &#64;param array $args 参数
151 * &#64;return mixed
152 */
153 public function __call($method,$args) {
154 if( 0 &#61;&#61;&#61; strcasecmp($method,ACTION_NAME.C(&#39;ACTION_SUFFIX&#39;))) {
155 if(method_exists($this,&#39;_empty&#39;)) {
156 // 如果定义了_empty操作 则调用
157 $this->_empty($method,$args);
158 }elseif(file_exists_case($this->view->parseTemplate())){
159 // 检查是否存在默认模版 如果有直接输出模版
160 $this->display();
161 }else{
162 E(L(&#39;_ERROR_ACTION_&#39;).&#39;:&#39;.ACTION_NAME);
163 }
164 }else{
165 E(__CLASS__.&#39;:&#39;.$method.L(&#39;_METHOD_NOT_EXIST_&#39;));
166 return;
167 }
168 }
169
170 /**
171 * 操作错误跳转的快捷方法
172 * &#64;access protected
173 * &#64;param string $message 错误信息
174 * &#64;param string $jumpUrl 页面跳转地址
175 * &#64;param mixed $ajax 是否为Ajax方式 当数字时指定跳转时间
176 * &#64;return void
177 */
178 protected function error($message&#61;&#39;&#39;,$jumpUrl&#61;&#39;&#39;,$ajax&#61;false) {
179 $this->dispatchJump($message,0,$jumpUrl,$ajax);
180 }
181
182 /**
183 * 操作成功跳转的快捷方法
184 * &#64;access protected
185 * &#64;param string $message 提示信息
186 * &#64;param string $jumpUrl 页面跳转地址
187 * &#64;param mixed $ajax 是否为Ajax方式 当数字时指定跳转时间
188 * &#64;return void
189 */
190 protected function success($message&#61;&#39;&#39;,$jumpUrl&#61;&#39;&#39;,$ajax&#61;false) {
191 $this->dispatchJump($message,1,$jumpUrl,$ajax);
192 }
193
194 /**
195 * Ajax方式返回数据到客户端
196 * &#64;access protected
197 * &#64;param mixed $data 要返回的数据
198 * &#64;param String $type AJAX返回数据格式
199 * &#64;param int $json_option 传递给json_encode的option参数
200 * &#64;return void
201 */
202 protected function ajaxReturn($data,$type&#61;&#39;&#39;,$json_option&#61;0) {
203 if(empty($type)) $type &#61; C(&#39;DEFAULT_AJAX_RETURN&#39;);
204 switch (strtoupper($type)){
205 case &#39;JSON&#39; :
206 // 返回JSON数据格式到客户端 包含状态信息
207 header(&#39;Content-Type:application/json; charset&#61;utf-8&#39;);
208 exit(json_encode($data,$json_option));
209 case &#39;XML&#39; :
210 // 返回xml格式数据
211 header(&#39;Content-Type:text/xml; charset&#61;utf-8&#39;);
212 exit(xml_encode($data));
213 case &#39;JSONP&#39;:
214 // 返回JSON数据格式到客户端 包含状态信息
215 header(&#39;Content-Type:application/json; charset&#61;utf-8&#39;);
216 $handler &#61; isset($_GET[C(&#39;VAR_JSONP_HANDLER&#39;)]) ? $_GET[C(&#39;VAR_JSONP_HANDLER&#39;)] : C(&#39;DEFAULT_JSONP_HANDLER&#39;);
217 exit($handler.&#39;(&#39;.json_encode($data,$json_option).&#39;);&#39;);
218 case &#39;EVAL&#39; :
219 // 返回可执行的js脚本
220 header(&#39;Content-Type:text/html; charset&#61;utf-8&#39;);
221 exit($data);
222 default :
223 // 用于扩展其他返回格式数据
224 Hook::listen(&#39;ajax_return&#39;,$data);
225 }
226 }
227
228 /**
229 * Action跳转(URL重定向&#xff09; 支持指定模块和延时跳转
230 * &#64;access protected
231 * &#64;param string $url 跳转的URL表达式
232 * &#64;param array $params 其它URL参数
233 * &#64;param integer $delay 延时跳转的时间 单位为秒
234 * &#64;param string $msg 跳转提示信息
235 * &#64;return void
236 */
237 protected function redirect($url,$params&#61;array(),$delay&#61;0,$msg&#61;&#39;&#39;) {
238 $url &#61; U($url,$params);
239 redirect($url,$delay,$msg);
240 }
241
242 /**
243 * 默认跳转操作 支持错误导向和正确跳转
244 * 调用模板显示 默认为public目录下面的success页面
245 * 提示页面为可配置 支持模板标签
246 * &#64;param string $message 提示信息
247 * &#64;param Boolean $status 状态
248 * &#64;param string $jumpUrl 页面跳转地址
249 * &#64;param mixed $ajax 是否为Ajax方式 当数字时指定跳转时间
250 * &#64;access private
251 * &#64;return void
252 */
253 private function dispatchJump($message,$status&#61;1,$jumpUrl&#61;&#39;&#39;,$ajax&#61;false) {
254 if(true &#61;&#61;&#61; $ajax || IS_AJAX) {// AJAX提交
255 $data &#61; is_array($ajax)?$ajax:array();
256 $data[&#39;info&#39;] &#61; $message;
257 $data[&#39;status&#39;] &#61; $status;
258 $data[&#39;url&#39;] &#61; $jumpUrl;
259 $this->ajaxReturn($data);
260 }
261 if(is_int($ajax)) $this->assign(&#39;waitSecond&#39;,$ajax);
262 if(!empty($jumpUrl)) $this->assign(&#39;jumpUrl&#39;,$jumpUrl);
263 // 提示标题
264 $this->assign(&#39;msgTitle&#39;,$status? L(&#39;_OPERATION_SUCCESS_&#39;) : L(&#39;_OPERATION_FAIL_&#39;));
265 //如果设置了关闭窗口&#xff0c;则提示完毕后自动关闭窗口
266 if($this->get(&#39;closeWin&#39;)) $this->assign(&#39;jumpUrl&#39;,&#39;Javascript:window.close();&#39;);
267 $this->assign(&#39;status&#39;,$status); // 状态
268 //保证输出不受静态缓存影响
269 C(&#39;HTML_CACHE_ON&#39;,false);
270 if($status) { //发送成功信息
271 $this->assign(&#39;message&#39;,$message);// 提示信息
272 // 成功操作后默认停留1秒
273 if(!isset($this->waitSecond)) $this->assign(&#39;waitSecond&#39;,&#39;1&#39;);
274 // 默认操作成功自动返回操作前页面
275 if(!isset($this->jumpUrl)) $this->assign("jumpUrl",$_SERVER["HTTP_REFERER"]);
276 $this->display(C(&#39;TMPL_ACTION_SUCCESS&#39;));
277 }else{
278 $this->assign(&#39;error&#39;,$message);// 提示信息
279 //发生错误时候默认停留3秒
280 if(!isset($this->waitSecond)) $this->assign(&#39;waitSecond&#39;,&#39;3&#39;);
281 // 默认发生错误的话自动返回上页
282 if(!isset($this->jumpUrl)) $this->assign(&#39;jumpUrl&#39;,"Javascript:history.back(-1);");
283 $this->display(C(&#39;TMPL_ACTION_ERROR&#39;));
284 // 中止执行 避免出错后继续执行
285 exit ;
286 }
287 }
288
289 /**
290 * 析构方法
291 * &#64;access public
292 */
293 public function __destruct() {
294 // 执行后续操作
295 Hook::listen(&#39;action_end&#39;);
296 }
297 }
298 // 设置控制器别名 便于升级
299 class_alias(&#39;Think\Controller&#39;,&#39;Think\Action&#39;);

View Code

  在start方法中主要的工作就是读取配置文件信息(Tinkphp/Mode/common.php, Thinkphp/Conf/convention.php),引入核心文件(Thinkphp/Library/Think)&#xff0c;如果是应用模式则会生成runntime.php文件,如果框架被第一次调用还会为了我们生成应用目录。在start最后调用了App:run()静态方法。

  • App.class.php

1 php
2 // &#43;----------------------------------------------------------------------
3 // | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
4 // &#43;----------------------------------------------------------------------
5 // | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
6 // &#43;----------------------------------------------------------------------
7 // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8 // &#43;----------------------------------------------------------------------
9 // | Author: liu21st
10 // &#43;----------------------------------------------------------------------
11 namespace Think;
12 /**
13 * ThinkPHP 应用程序类 执行应用过程管理
14 */
15 class App {
16
17 /**
18 * 应用程序初始化
19 * &#64;access public
20 * &#64;return void
21 */
22 static public function init() {
23 // 加载动态应用公共文件和配置
24 load_ext_file(COMMON_PATH);
25
26 // 日志目录转换为绝对路径 默认情况下存储到公共模块下面
27 C(&#39;LOG_PATH&#39;, realpath(LOG_PATH).&#39;/Common/&#39;);
28
29 // 定义当前请求的系统常量
30 define(&#39;NOW_TIME&#39;, $_SERVER[&#39;REQUEST_TIME&#39;]);
31 define(&#39;REQUEST_METHOD&#39;,$_SERVER[&#39;REQUEST_METHOD&#39;]);
32 define(&#39;IS_GET&#39;, REQUEST_METHOD &#61;&#61;&#39;GET&#39; ? true : false);
33 define(&#39;IS_POST&#39;, REQUEST_METHOD &#61;&#61;&#39;POST&#39; ? true : false);
34 define(&#39;IS_PUT&#39;, REQUEST_METHOD &#61;&#61;&#39;PUT&#39; ? true : false);
35 define(&#39;IS_DELETE&#39;, REQUEST_METHOD &#61;&#61;&#39;DELETE&#39; ? true : false);
36
37 // URL调度, 把模块、控制器、方法赋予常量
38 // MOUDLE_NAME &#61; 模块名
39 // CONTROLLER_NAME
40 // ACTION_NAME
41 Dispatcher::dispatch();
42
43 if(C(&#39;REQUEST_VARS_FILTER&#39;)){
44 // 全局安全过滤
45 array_walk_recursive($_GET, &#39;think_filter&#39;);
46 array_walk_recursive($_POST, &#39;think_filter&#39;);
47 array_walk_recursive($_REQUEST, &#39;think_filter&#39;);
48 }
49
50 // URL调度结束标签
51 Hook::listen(&#39;url_dispatch&#39;);
52
53 define(&#39;IS_AJAX&#39;, ((isset($_SERVER[&#39;HTTP_X_REQUESTED_WITH&#39;]) && strtolower($_SERVER[&#39;HTTP_X_REQUESTED_WITH&#39;]) &#61;&#61; &#39;xmlhttprequest&#39;) || !empty($_POST[C(&#39;VAR_AJAX_SUBMIT&#39;)]) || !empty($_GET[C(&#39;VAR_AJAX_SUBMIT&#39;)])) ? true : false);
54
55 // TMPL_EXCEPTION_FILE 改为绝对地址
56 C(&#39;TMPL_EXCEPTION_FILE&#39;,realpath(C(&#39;TMPL_EXCEPTION_FILE&#39;)));
57 return ;
58 }
59
60 /**
61 * 执行应用程序
62 * &#64;access public
63 * &#64;return void
64 */
65 static public function exec() {
66
67 if(!preg_match(&#39;/^[A-Za-z](\/|\w)*$/&#39;,CONTROLLER_NAME)){ // 安全检测
68 $module &#61; false;
69 }elseif(C(&#39;ACTION_BIND_CLASS&#39;)){
70 // 操作绑定到类&#xff1a;模块\Controller\控制器\操作
71 $layer &#61; C(&#39;DEFAULT_C_LAYER&#39;);
72 if(is_dir(MODULE_PATH.$layer.&#39;/&#39;.CONTROLLER_NAME)){
73 $namespace &#61; MODULE_NAME.&#39;\\&#39;.$layer.&#39;\\&#39;.CONTROLLER_NAME.&#39;\\&#39;;
74 }else{
75 // 空控制器
76 $namespace &#61; MODULE_NAME.&#39;\\&#39;.$layer.&#39;\\_empty\\&#39;;
77 }
78 $actionName &#61; strtolower(ACTION_NAME);
79 if(class_exists($namespace.$actionName)){
80 $class &#61; $namespace.$actionName;
81 }elseif(class_exists($namespace.&#39;_empty&#39;)){
82 // 空操作
83 $class &#61; $namespace.&#39;_empty&#39;;
84 }else{
85 E(L(&#39;_ERROR_ACTION_&#39;).&#39;:&#39;.ACTION_NAME);
86 }
87 $module &#61; new $class;
88 // 操作绑定到类后 固定执行run入口
89 $action &#61; &#39;run&#39;;
90 }else{
91 //创建控制器实例
92 $module &#61; controller(CONTROLLER_NAME,CONTROLLER_PATH);
93 }
94
95 if(!$module) {
96 if(&#39;4e5e5d7364f443e28fbf0d3ae744a59a&#39; &#61;&#61; CONTROLLER_NAME) {
97 header("Content-type:image/png");
98 exit(base64_decode(App::logo()));
99 }
100
101 // 是否定义Empty控制器
102 $module &#61; A(&#39;Empty&#39;);
103 if(!$module){
104 E(L(&#39;_CONTROLLER_NOT_EXIST_&#39;).&#39;:&#39;.CONTROLLER_NAME);
105 }
106 }
107
108 // 获取当前操作名 支持动态路由
109 if(!isset($action)){
110 $action &#61; ACTION_NAME.C(&#39;ACTION_SUFFIX&#39;);
111 }
112 try{
113 self::invokeAction($module,$action);
114 } catch (\ReflectionException $e) {
115 // 方法调用发生异常后 引导到__call方法处理
116 $method &#61; new \ReflectionMethod($module,&#39;__call&#39;);
117 $method->invokeArgs($module,array($action,&#39;&#39;));
118 }
119 return ;
120 }
121 public static function invokeAction($module,$action){
122 if(!preg_match(&#39;/^[A-Za-z](\w)*$/&#39;,$action)){
123 // 非法操作
124 throw new \ReflectionException();
125 }
126 //执行当前操作
127 $method &#61; new \ReflectionMethod($module, $action);
128 if($method->isPublic() && !$method->isStatic()) {
129 $class &#61; new \ReflectionClass($module);
130 // 前置操作
131 if($class->hasMethod(&#39;_before_&#39;.$action)) {
132 $before &#61; $class->getMethod(&#39;_before_&#39;.$action);
133 if($before->isPublic()) {
134 $before->invoke($module);
135 }
136 }
137 // URL参数绑定检测
138 if($method->getNumberOfParameters()>0 && C(&#39;URL_PARAMS_BIND&#39;)){
139 switch($_SERVER[&#39;REQUEST_METHOD&#39;]) {
140 case &#39;POST&#39;:
141 $vars &#61; array_merge($_GET,$_POST);
142 break;
143 case &#39;PUT&#39;:
144 parse_str(file_get_contents(&#39;php://input&#39;), $vars);
145 break;
146 default:
147 $vars &#61; $_GET;
148 }
149 $params &#61; $method->getParameters();
150 $paramsBindType &#61; C(&#39;URL_PARAMS_BIND_TYPE&#39;);
151 foreach ($params as $param){
152 $name &#61; $param->getName();
153 if( 1 &#61;&#61; $paramsBindType && !empty($vars) ){
154 $args[] &#61; array_shift($vars);
155 }elseif( 0 &#61;&#61; $paramsBindType && isset($vars[$name])){
156 $args[] &#61; $vars[$name];
157 }elseif($param->isDefaultValueAvailable()){
158 $args[] &#61; $param->getDefaultValue();
159 }else{
160 E(L(&#39;_PARAM_ERROR_&#39;).&#39;:&#39;.$name);
161 }
162 }
163 // 开启绑定参数过滤机制
164 if(C(&#39;URL_PARAMS_SAFE&#39;)){
165 $filters &#61; C(&#39;URL_PARAMS_FILTER&#39;)?:C(&#39;DEFAULT_FILTER&#39;);
166 if($filters) {
167 $filters &#61; explode(&#39;,&#39;,$filters);
168 foreach($filters as $filter){
169 $args &#61; array_map_recursive($filter,$args); // 参数过滤
170 }
171 }
172 }
173 array_walk_recursive($args,&#39;think_filter&#39;);
174 $method->invokeArgs($module,$args);
175 }else{
176 $method->invoke($module);
177 }
178 // 后置操作
179 if($class->hasMethod(&#39;_after_&#39;.$action)) {
180 $after &#61; $class->getMethod(&#39;_after_&#39;.$action);
181 if($after->isPublic()) {
182 $after->invoke($module);
183 }
184 }
185 }else{
186 // 操作方法不是Public 抛出异常
187 throw new \ReflectionException();
188 }
189 }
190 /**
191 * 运行应用实例 入口文件使用的快捷方法
192 * &#64;access public
193 * &#64;return void
194 */
195 static public function run() {
196 // 应用初始化标签
197 Hook::listen(&#39;app_init&#39;);
198 App::init();
199 // 应用开始标签
200 Hook::listen(&#39;app_begin&#39;);
201 // Session初始化
202 if(!IS_CLI){
203 session(C(&#39;SESSION_OPTIONS&#39;));
204 }
205 // 记录应用初始化时间
206 G(&#39;initTime&#39;);
207 App::exec();
208 // 应用结束标签
209 Hook::listen(&#39;app_end&#39;);
210 return ;
211 }
212 }

View Code

  在该类中有两个重要的方法&#xff0c;init()和exec()方法。init()主要进行路由解析&#xff0c;看用户是请求那个模块下的哪个控制器的方法。而exec()则是根据init()解析的结果通过反射机制来实例化一个Controller并并调用相应的方法。

总结


 

  通过流程分析来看&#xff0c;这个框架主要由三个文件构成ThinkPHP.php&#xff0c;Think.class.php, App.class.php&#xff0c;当然还有其它的一些辅助类或方法来帮助完成整个响应。

 

 


转:https://www.cnblogs.com/xidongyu/p/5593107.html



推荐阅读
author-avatar
手机用户2502857101
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有