yii框架源码分析之创建contr…

原文地址:yii框架源码分析之创建controller分析 作者:silentime
使用yii框架的url路径一般形如hostname/?r=xxxx/xxxx/xxxx&sdfs=dsfdsf

我们可以看到有时会使用protected目录下的controller,有时会使用module中controller,具体是如何处理的呢,请看如下的分析:

以下代码摘自yii框架核心代码%Yiiroot%/framework/web/CWebApplication.php

=================================================================================================
//1.runController是执行一个controller的方法,$route是$_GET['r']
    public function runController($route)
    {
        //在这里调用createController先去创建一个controller实例,由此可见createController是选择controller的关键
        if(($ca=$this->createController($route))!==null)
        {
            list($controller,$actionID)=$ca;
            $oldController=$this->_controller;
            $this->_controller=$controller;
            $controller->init();
            $controller->run($actionID);
            $this->_controller=$oldController;
        }
        else
            throw new CHttpException(404,Yii::t('yii','Unable to resolve the request "{route}".',
                array('{route}'=>$route===''?$this->defaultController:$route)));
    }
==================================================================================================
//2.接下来我们分析createController,假设我们访问的route是site/contact
public function createController($route,$owner=null)
    {
        //首次进入这个函数,$owner参数为空
        if($owner===null)
            $owner=$this;
        //如果$route参数中不含/,那么使用默认的controller
        if(($route=trim($route,'/'))==='')
            $route=$owner->defaultController;
        $caseSensitive=$this->getUrlManager()->caseSensitive;
        //为了能够完整运行下面的循环,给$route后面加一个/
        $route.='/';
        //将/的位置保存在$pos中
        while(($pos=strpos($route,'/'))!==false)
        {
            //$id是前半部分,即site
            $id=substr($route,0,$pos);
            if(!preg_match('/^w+$/',$id))
                return null;
            if(!$caseSensitive)
                $id=strtolower($id);
            //$route变成后半部分,即contact
            $route=(string)substr($route,$pos+1);
            //controller根目录或子目录前缀
            if(!isset($basePath))  // first segment
            {
                //首次进入,$owner为空,没有这个成员变量
                //非首次进入或$owner有值,有可能设置了这个成员变量,参见CWebModule类
                if(isset($owner->controllerMap[$id]))
                {
                    return array(
                        Yii::createComponent($owner->controllerMap[$id],$id,$owner===$this?null:$owner),
                        $this->parseActionParams($route),
                    );
                }
                //如果能通过getModule方法获取到一个独立模块,则再次调用createController,适用于site是module名的情况,参考protected/config/main.php配置文件,例如你的controller在%webroot%/protected/module/site/controller/ContactController.php
                if(($module=$owner->getModule($id))!==null)
                    return $this->createController($route,$module);
                //controller的目录:
                //对于CWebApplication,对应config['basePath'](参见配置文件)./controller/,例如你的controller在%webroot%/protected/controller/SiteController.php
                //对于CModule的子类,对应改子类所在文件夹./contoller/ ,例如你的controller在%webroot%/protected/module/site/controller/ContactController.php
                $basePath=$owner->getControllerPath();
                $controllerID='';
            }
            else
                $controllerID.='/';
            $className=ucfirst($id).'Controller';
            $classFile=$basePath.DIRECTORY_SEPARATOR.$className.'.php';
            //如果$classFile存在,根据上面所得到的controller类文件路径,创建类实例
            //如果不存在,则是子目录下的controller,继续循环寻找最终的controller,例如你的controller在%webroot%/protected/controller/somedir/SiteController
            if(is_file($classFile))
            {
                if(!class_exists($className,false))
                    require($classFile);
                if(class_exists($className,false) && is_subclass_of($className,'CController'))
                {
                    $id[0]=strtolower($id[0]);
                    return array(
                        new $className($controllerID.$id,$owner===$this?null:$owner),
                        $this->parseActionParams($route),
                    );
                }
                return null;
            }
            $controllerID.=$id;
            $basePath.=DIRECTORY_SEPARATOR.$id;
        }
    }

你可能感兴趣的:(yii框架源码分析之创建contr…)