例如THINKPHP
class xxController{ public function index($id,$age) { //這些參數是通過$_GET['id'],$_GET['age']來的 }}//按PHP的實現方法大致應該是以下$ctr = new xxController();return $ctr->index(); //他這裡怎麼有知道應該傳哪些參數呢?!//本人愚鈍,我想不是這樣做的,那應該是怎麼實現呢?!!請各位大神講解一下其中的實現原理!
回複內容:
例如THINKPHP
class xxController{ public function index($id,$age) { //這些參數是通過$_GET['id'],$_GET['age']來的 }}//按PHP的實現方法大致應該是以下$ctr = new xxController();return $ctr->index(); //他這裡怎麼有知道應該傳哪些參數呢?!//本人愚鈍,我想不是這樣做的,那應該是怎麼實現呢?!!請各位大神講解一下其中的實現原理!
反射,通過反射得的類的方法的參數列表。然後對應起來就可以。
isInstantiable()) { throw new RuntimeException("{$controllerReflection->getName()}不能被執行個體化");}# 擷取對應方法的反射if (!$controllerReflection->hasMethod($action)) { throw new RuntimeException("{$controllerReflection->getName()}沒有指定的方法:{$action}");}$actionReflection = $controllerReflection->getMethod($action);# 擷取方法的參數的反射列表(多個參數反射組成的數組)$paramReflectionList = $actionReflection->getParameters();# 參數,用於action$params = [];# 迴圈參數反射# 如果存在路由參數的名稱和參數的名稱一致,就壓進params裡面# 如果存在預設值,就將預設值壓進params裡面# 如果。。。沒有如果了,異常foreach ($paramReflectionList as $paramReflection) { # 是否存在同名字的路由參數 if (isset($paramsInput[$paramReflection->getName()])) { $params[] = $paramsInput[$paramReflection->getName()]; continue; } # 是否存在預設值 if ($paramReflection->isDefaultValueAvailable()) { $params[] = $paramReflection->getDefaultValue(); continue; } # 異常 throw new RuntimeException( "{$controllerReflection->getName()}::{$actionReflection->getName()}的參數{$paramReflection->getName()}必須傳值" );}# 調起$actionReflection->invokeArgs($controllerReflection->newInstance(), $params);
儲存為:reflection.php
root@work:/media/sf_project/php-hello-world# php refrection.php hello toozy!
這種情況的架構都有一個“路由定義”,用戶端只能匹配到定義好的路由,包含了路徑、Method、以及請求參數。
拿 Laravel 舉例:
Route::get('api/article/{articleId}', 'ArticleController@articleDetail');//...ArticleController extends Controller{ public function articleDetail($articleId) { //... }}
在匹配路由過程,因為定義的這個路由包含了{articleId} 這個約定好形式的預留位置,路由模組會匹配包含 articleId 的 URL,並擷取到參數值傳給對應 Controller 的 action。