• YII框架分析笔记5:控制器和动作


    CBaseController是控制器和挂件的基类,主要提供了视图渲染,挂件,剪辑、片段缓存等方法,CController是所有应用中自定义控制器的基类。

    创建动作

    1. public function run($actionID)  
    2. {  
    3.     if(($action=$this->createAction($actionID))!==null)  
    4.     {  
    5.         if(($parent=$this->getModule())===null)  
    6.             $parent=Yii::app();  
    7.         if($parent->beforeControllerAction($this,$action))  
    8.         {  
    9.             $this->runActionWithFilters($action,$this->filters());  
    10.             $parent->afterControllerAction($this,$action);  
    11.         }  
    12.     }  
    13.     else  
    14.         $this->missingAction($actionID);  
    15. }  

    控制器的调用从CWebApplication执行runController()起,通过路由找到控制器和动作id,初始化控制器实例,然后执 行$controller->run($actionID),通过actionId创建动作对象(预留 beforeControllerAction和afterControllerAction钩子)。
    如果动作方法存在于控制器中并且不是actions(),会创建一个CInlineAction对象,否则通过actions()中会返回外部动作的关联 数组射找到外部动作对象,这个好处是可以共用一些同样的动作,比如下面curd动作代码,通过http://www.test.com /index.php?r=post/read就可以通过外部ReadAction对象读取post

    1. class PostController extends Controller  
    2. {  
    3.     function actions(){  
    4.         return array(  
    5.             'create' => array(  
    6.                 'class'      => 'application.actions.CreateAction',  
    7.                 'modelClass' => 'Post',  
    8.             ),  
    9.             'update' => array(  
    10.                 'class'      => 'application.actions.UpdateAction',  
    11.                 'modelClass' => 'Post',  
    12.             ),  
    13.             'read' => array(  
    14.                 'class'      => 'application.actions.ReadAction',  
    15.                 'param'      => 'Postid',   
    16.                 'modelClass' => 'Post',  
    17.             ),            
    18.             'delete' => array(  
    19.                 'class'      => 'application.actions.DeleteAction',  
    20.                 'modelClass' => 'Post',  
    21.             )  
    22.         );  
    23.     }  
    24. }  

    在actions()中还可以指定CViewAction对象,它其实就是YII框架写的一个调用外部动作的一个扩展。如下面代码可以按照用户指定的参数显示一个视图,通过GET参数来定位视图文件,这样对加载静态内容而又不用单独写动作方法很有帮助。

    1. public function actions()  
    2. {  
    3.     return array(  
    4.         'page'=>array(  
    5.             'class'=>'CViewAction',  
    6.             'basePath' => '$path',  
    7.             'defaultView '=> '$view'  
    8.         ),  
    9.     );  
    10. }  

    过滤器
    在创建完Action对象后,现在又返回到CController接着执行过滤动作(预留beforeControllerAction和 afterControllerAction钩子),此时会加载过滤器,控制器通过CController::filters()方法返回过滤器配置关联 数组,和验证器相似,过滤器可以在控制器内部定义(方法名必须以filter开头)也可以自定义过滤器类继承CFilter扩展preFilter()和 postFilter()方法, 如框架中自带的授权验证CAccessControlFilter。

    执行动作
    再返回CController执行动作(预留beforeAction和afterAction钩子),进入CActon子类(以 CInlineAction为例)中执行runWithParams($params)方法通过php反射判断控制器中的动作方法是不是需要参数
    1、如果需要参数执行runWithParamsInternal()方法,通过反射获取动作方法中的参数和值得键值对数组(写API经常用的方法),并执行动作方法
    2、如果不要参数执行run()方法定位到控制器的动作中

    1. /** 
    2.  * Runs the action with the supplied request parameters. 
    3.  * This method is internally called by {@link CController::runAction()}. 
    4.  * @param array $params the request parameters (name=>value) 
    5.  * @return boolean whether the request parameters are valid 
    6.  * @since 1.1.7 
    7.  */  
    8. public function runWithParams($params)  
    9. {  
    10.     $methodName='action'.$this->getId();  
    11.     $controller=$this->getController();  
    12.     $method=new ReflectionMethod($controller, $methodName);  
    13.     if($method->getNumberOfParameters()>0)  
    14.         return $this->runWithParamsInternal($controller, $method, $params);  
    15.     else  
    16.         return $controller->$methodName();  
    17. }  
    18. /** 
    19.  * Executes a method of an object with the supplied named parameters. 
    20.  * This method is internally used. 
    21.  * @param mixed $object the object whose method is to be executed 
    22.  * @param ReflectionMethod $method the method reflection 
    23.  * @param array $params the named parameters 
    24.  * @return boolean whether the named parameters are valid 
    25.  * @since 1.1.7 
    26.  */  
    27. protected function runWithParamsInternal($object, $method, $params)  
    28. {  
    29.     $ps=array();  
    30.     foreach($method->getParameters() as $i=>$param)  
    31.     {  
    32.         $name=$param->getName();  
    33.         if(isset($params[$name]))  
    34.         {  
    35.             if($param->isArray())  
    36.                 $ps[]=is_array($params[$name]) ? $params[$name] : array($params[$name]);  
    37.             else if(!is_array($params[$name]))  
    38.                 $ps[]=$params[$name];  
    39.             else  
    40.                 return false;  
    41.         }  
    42.         else if($param->isDefaultValueAvailable())  
    43.             $ps[]=$param->getDefaultValue();  
    44.         else  
    45.             return false;  
    46.     }  
    47.     $method->invokeArgs($object,$ps);  
    48.     return true;  
    49. }  



  • 相关阅读:
    Comet OJ CCPC-Wannafly Winter Camp Day1 (Div2, online mirror) F.爬爬爬山-最短路(Dijkstra)(两个板子)+思维(mdzz...) zhixincode
    Codeforces 1104 D. Game with modulo-交互题-二分-woshizhizhang(Codeforces Round #534 (Div. 2))
    POJ 1655.Balancing Act-树的重心(DFS) 模板(vector存图)
    Codeforces gym102058 J. Rising Sun-简单的计算几何+二分 (2018-2019 XIX Open Cup, Grand Prix of Korea (Division 2))
    BZOJ 3261: 最大异或和位置-贪心+可持久化01Trie树
    51nod 1295 XOR key-区间异或最大值-可持久化01Trie树(模板)
    BZOJ 2588: Spoj 10628. Count on a tree-可持久化线段树+LCA(点权)(树上的操作) 无语(为什么我的LCA的板子不对)
    Codeforces 1099 D. Sum in the tree-构造最小点权和有根树 贪心+DFS(Codeforces Round #530 (Div. 2))
    Codeforces 586D. Phillip and Trains 搜索
    Codeforces 734E. Anton and Tree 搜索
  • 原文地址:https://www.cnblogs.com/sunscheung/p/4827123.html
Copyright © 2020-2023  润新知