本文實例講述了Yii2創建控制器(createController)方法。分享給大家供大家參考,具體如下:
yii中創建控制器的是在application中的request通過UrlManager解析得出路由信息的,然后再由yii\base\Module中的
1
|
public function runAction( $route , $params = []) |
方法來創建控制器,最后由控制器再執行相應的動作。
首先得明確,Yii中的路由分三種情況:
第一種是帶有模塊的(module id/controller id/action id),
第二種是帶有命名空間(子目錄)的(sub dir)/controller id/action id)
第三種是只有控制器和動作的(controller id/action id)
這三個有優先順序,所以在創建控制器的時候,也是先查看是否是模塊類型的路由,如果是,則獲取這個模塊,再由這個模塊來創建控制器
接著再判斷是否是第二種帶有命名空間的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
public function createController( $route ) { //如果路由為空,則使用默認的路由 if ( $route === '' ) { $route = $this ->defaultRoute; } // double slashes or leading/ending slashes may cause substr problem //去掉首尾的反斜杠(“/”),如果路由中包含有“//”,則返回false創建失敗。 $route = trim( $route , '/' ); if ( strpos ( $route , '//' ) !== false) { return false; } /* * 路由分三種情況, * 一種是帶模塊id的(module id/controller id/action id), * 一種是有命名空間(子目錄)的(sub dir)/controller id/action id) * 一種是只有控制器和動作的(controller id/action id) * 所以在這里要根據第一個“/”分隔成兩部分,$id和$route信息, */ if ( strpos ( $route , '/' ) !== false) { list ( $id , $route ) = explode ( '/' , $route , 2); } else { $id = $route ; $route = '' ; } // module and controller map take precedence /* * 查看這個id是否是模塊,如果是模塊,則再用這個模塊來創建控制器。 * 所以,在如果一個控制器的名稱和模塊名稱重復的話會優先創建模塊里面的控制器。 * * 如果有url: http://www.yii2.com/index.php?r=test/index * 本來是打算訪問application中的控制器里面的test控制器,執行index動作的。 * * 然而如果有個模塊的名字為test,里面有個IndexController * * 根據上面會生成$id=test,$route=index * * 由于在下面查找存在這個模塊,所以會執行這個test模塊下面的index控制器, * 而不會執行application里面的test控制器的index動作 */ $module = $this ->getModule( $id ); if ( $module !== null) { return $module ->createController( $route ); } //如果在controllerMap數組中指定了控制器映射,會優先根據這個里面的映射來創建控制器 if (isset( $this ->controllerMap[ $id ])) { $controller = Yii::createObject( $this ->controllerMap[ $id ], [ $id , $this ]); return [ $controller , $route ]; } /* * 如果這個時候$route中還有“/”,也就是說原來的路由為home/index/aa * $id:home(不是模塊) * $route:index/aa * 由于經過上面得知home不為模塊,所以這個為命名空間(子目錄), * * 再經過下面處理后為 * $id:home/index 命名空間(子目錄)home下面的index控制器 * $route:aaa * */ if (( $pos = strrpos ( $route , '/' )) !== false) { $id .= '/' . substr ( $route , 0, $pos ); $route = substr ( $route , $pos + 1); } /* * $id:home/index * $route:aaa */ $controller = $this ->createControllerByID( $id ); if ( $controller === null && $route !== '' ) { //如果創建失敗,再加上route作為id再次創建 $controller = $this ->createControllerByID( $id . '/' . $route ); $route = '' ; } return $controller === null ? false : [ $controller , $route ]; } |
在這個函數中$id就有兩種情況,一種是前面帶有命名空間的,一種是直接就一個控制器ID的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
public function createControllerByID( $id ) { if (!preg_match( '%^[a-z0-9\\-_/]+$%' , $id )) { return null; } /* * 如果$id中有“/”,則前面的為目錄,后面的為類 * */ $pos = strrpos ( $id , '/' ); if ( $pos === false) { $prefix = '' ; $className = $id ; } else { $prefix = substr ( $id , 0, $pos + 1); $className = substr ( $id , $pos + 1); } //生成控制器的類IndexController $className = str_replace ( ' ' , '' , ucwords( str_replace ( '-' , ' ' , $className ))) . 'Controller' ; //如果有前綴(也就是有目錄、命名空間),則在類前面加上命名空間 $className = ltrim( $this ->controllerNamespace . '\\' . str_replace ( '/' , '\\' , $prefix ) . $className , '\\' ); //如果類不存在,或者類名稱包含“-”,則出錯, if ( strpos ( $className , '-' ) !== false || ! class_exists ( $className )) { return null; } //下面就是創建類了 if ( is_subclass_of ( $className , 'yii\base\Controller' )) { return new $className ( $id , $this ); } elseif (YII_DEBUG) { throw new InvalidConfigException( "Controller class must extend from \\yii\\base\\Controller." ); } else { return null; } } |
這個過程就結束了,然后再由創建出來的控制器執行它里面的動作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public function runAction( $route , $params = []) { $parts = $this ->createController( $route ); if ( is_array ( $parts )) { /** @var Controller $controller */ list( $controller , $actionID ) = $parts ; $oldController = Yii:: $app ->controller; Yii:: $app ->controller = $controller ; //控制器執行相應的動作 $result = $controller ->runAction( $actionID , $params ); Yii:: $app ->controller = $oldController ; return $result ; } else { $id = $this ->getUniqueId(); throw new InvalidRouteException( 'Unable to resolve the request "' . ( $id === '' ? $route : $id . '/' . $route ) . '".' ); } } |
希望本文所述對大家基于Yii框架的PHP程序設計有所幫助。