ThinkPHP3.1.3原始碼分析(五) App.class.php
Think.class.php 的 start()方法 最後 呼叫了App::run();
App類最重要的是兩個部分
1、init()函式
a.過濾了$_GET,$_POST的資料
b.
// URL排程
Dispatcher::dispatch();
2、exec()函式
a.建立對應的Action
if(!preg_match('/^[A-Za-z](\w)*$/',MODULE_NAME)){ // 安全檢測
$module = false;
}else{
//建立Action控制器例項
$group = defined('GROUP_NAME') && C('APP_GROUP_MODE')==0 ? GROUP_NAME.'/' : '';
$module = A($group.MODULE_NAME);
}
b.呼叫對應的方法
try{
if(!preg_match('/^[A-Za-z](\w)*$/',$action)){
// 非法操作
throw new ReflectionException();
}
//執行當前操作
$method = new ReflectionMethod($module, $action);
if($method->isPublic()) {
$class = new ReflectionClass($module);
// 前置操作
if($class->hasMethod('_before_'.$action)) {
$before = $class->getMethod('_before_'.$action);
if($before->isPublic()) {
$before->invoke($module);
}
}
// URL引數繫結檢測
if(C('URL_PARAMS_BIND') && $method->getNumberOfParameters()>0){
switch($_SERVER['REQUEST_METHOD']) {
case 'POST':
$vars = array_merge($_GET,$_POST);
break;
case 'PUT':
parse_str(file_get_contents('php://input'), $vars);
break;
default:
$vars = $_GET;
}
$params = $method->getParameters();
foreach ($params as $param){
$name = $param->getName();
if(isset($vars[$name])) {
$args[] = $vars[$name];
}elseif($param->isDefaultValueAvailable()){
$args[] = $param->getDefaultValue();
}else{
throw_exception(L('_PARAM_ERROR_').':'.$name);
}
}
$method->invokeArgs($module,$args);
}else{
$method->invoke($module);
}
// 後置操作
if($class->hasMethod('_after_'.$action)) {
$after = $class->getMethod('_after_'.$action);
if($after->isPublic()) {
$after->invoke($module);
}
}
}else{
// 操作方法不是Public 丟擲異常
throw new ReflectionException();
}
} catch (ReflectionException $e) {
// 方法呼叫發生異常後 引導到__call方法處理
$method = new ReflectionMethod($module,'__call');
$method->invokeArgs($module,array($action,''));
}
二、值得說的程式設計小細節:
在呼叫 Action對應方法的時候,使用了php中的反射機制
相關文章
- ThinkPHP3.1.3原始碼分析(一) 入口檔案分析PHP原始碼
- ThinkPHP3.1.3原始碼分析(三) common.phpPHP原始碼
- ThinkPHP3.1.3原始碼分析(四) Think.class.phpPHP原始碼
- ThinkPHP3.1.3原始碼分析(二) runtime.phpPHP原始碼
- preact原始碼分析(五)React原始碼
- Netty原始碼分析(五):EventLoopNetty原始碼OOP
- redis原始碼分析(五):資料持久化Redis原始碼持久化
- mybaits原始碼分析--binding模組(五)AI原始碼
- redux原始碼分析之五:applyMiddlewareRedux原始碼APP
- OkHttpClient原始碼分析(五)—— ConnectInterceptor和CallServerInterceptorHTTPclient原始碼Server
- SpringMVC之原始碼分析--ViewResolver(五)SpringMVC原始碼View
- OkHttp 3.7原始碼分析(五)——連線池HTTP原始碼
- keystone系列五:keystone原始碼分析原始碼
- Android 8.0 原始碼分析 (五) Service 啟動Android原始碼
- Netty原始碼分析--Channel註冊(上)(五)Netty原始碼
- 【JUC】JDK1.8原始碼分析之CountDownLatch(五)JDK原始碼CountDownLatch
- MPTCP 原始碼分析(五) 接收端視窗值TCP原始碼
- Dubbo原始碼分析(五)Dubbo呼叫鏈-服務端原始碼服務端
- 五種I/O模型和Java NIO原始碼分析模型Java原始碼
- 【Zookeeper】原始碼分析之伺服器(五)之ObserverZooKeeperServer原始碼伺服器Server
- 【集合框架】JDK1.8原始碼分析之TreeMap(五)框架JDK原始碼
- Android主流三方庫原始碼分析(五、深入理解RxJava原始碼)Android原始碼RxJava
- Retrofit原始碼分析三 原始碼分析原始碼
- Giraph 原始碼分析(五)—— 載入資料+同步總結原始碼
- vscode原始碼分析【五】事件分發機制VSCode原始碼事件
- 集合原始碼分析[2]-AbstractList 原始碼分析原始碼
- 集合原始碼分析[1]-Collection 原始碼分析原始碼
- 集合原始碼分析[3]-ArrayList 原始碼分析原始碼
- Guava 原始碼分析之 EventBus 原始碼分析Guava原始碼
- Dubbo原始碼分析(五)服務暴露的具體流程(下)原始碼
- Android 原始碼分析之 AsyncTask 原始碼分析Android原始碼
- 【JDK原始碼分析系列】ArrayBlockingQueue原始碼分析JDK原始碼BloC
- 以太坊原始碼分析(36)ethdb原始碼分析原始碼
- 以太坊原始碼分析(38)event原始碼分析原始碼
- 以太坊原始碼分析(41)hashimoto原始碼分析原始碼
- 以太坊原始碼分析(43)node原始碼分析原始碼
- 以太坊原始碼分析(52)trie原始碼分析原始碼
- 深度 Mybatis 3 原始碼分析(一)SqlSessionFactoryBuilder原始碼分析MyBatis原始碼SQLSessionUI