Heim >php教程 >php手册 >YII 的源码分析(三),yii源码分析

YII 的源码分析(三),yii源码分析

WBOY
WBOYOriginal
2016-06-13 09:18:271024Durchsuche

YII 的源码分析(三),yii源码分析

前面已经看完了启动一个yii程序所要经过的流程,以及渲染一个页面是怎么完成的。今天要分析的是yii是如何处理用户请求的。也就是控制和动作部分。

还是以helloworld为例演示这一过程。我们在地址栏输入http://localhost/study/yii/demos/helloworld/index.php,页面就显示了hello world.

前面的分析都是用的默认值,但是如果url有参数的时候,yii又是怎么处理的呢?带着这个问题,我们具体来分析一下。

在CWebApplication中有这样一行代码:

<span>$route</span>=<span>$this</span>->getUrlManager()->parseUrl(<span>$this</span>->getRequest());

这就是传说中的路由了,是不是有点小鸡冻呢?先看看getUrlManager是个神马。

    <span>public</span> <span>function</span><span> getUrlManager()
    {
        </span><span>return</span> <span>$this</span>->getComponent('urlManager'<span>);
    }</span>

这个又要通过找关系了.

    <span>public</span> <span>function</span> getComponent(<span>$id</span>,<span>$createIfNull</span>=<span>true</span><span>)
    {
        </span><span>if</span>(<span>isset</span>(<span>$this</span>->_components[<span>$id</span><span>]))
            </span><span>return</span> <span>$this</span>->_components[<span>$id</span><span>];
        </span><span>elseif</span>(<span>isset</span>(<span>$this</span>->_componentConfig[<span>$id</span>]) && <span>$createIfNull</span><span>)
        {
            </span><span>$config</span>=<span>$this</span>->_componentConfig[<span>$id</span><span>];
            </span><span>if</span>(!<span>isset</span>(<span>$config</span>['enabled']) || <span>$config</span>['enabled'<span>])
            {
                Yii</span>::trace("Loading \"<span>$id</span>\" application component",'system.CModule'<span>);
                </span><span>unset</span>(<span>$config</span>['enabled'<span>]);
                </span><span>$component</span>=Yii::createComponent(<span>$config</span><span>);
                </span><span>$component</span>-><span>init();
                </span><span>return</span> <span>$this</span>->_components[<span>$id</span>]=<span>$component</span><span>;
            }
        }
    }</span>

执行了return $this->_components[$id]; id就是传进去的urlManager,其实从这里也还看不出什么,直接找到urlManager这个类,看parseUrl:

    <span>public</span> <span>function</span> parseUrl(<span>$request</span><span>)
    {
        </span><span>if</span>(<span>$this</span>->getUrlFormat()===self::<span>PATH_FORMAT)
        {
            </span><span>$rawPathInfo</span>=<span>$request</span>-><span>getPathInfo();
            </span><span>$pathInfo</span>=<span>$this</span>->removeUrlSuffix(<span>$rawPathInfo</span>,<span>$this</span>-><span>urlSuffix);
            </span><span>foreach</span>(<span>$this</span>->_rules <span>as</span> <span>$i</span>=><span>$rule</span><span>)
            {
                </span><span>if</span>(<span>is_array</span>(<span>$rule</span><span>))
                    </span><span>$this</span>->_rules[<span>$i</span>]=<span>$rule</span>=Yii::createComponent(<span>$rule</span><span>);
                </span><span>if</span>((<span>$r</span>=<span>$rule</span>->parseUrl(<span>$this</span>,<span>$request</span>,<span>$pathInfo</span>,<span>$rawPathInfo</span>))!==<span>false</span><span>)
                    </span><span>return</span> <span>isset</span>(<span>$_GET</span>[<span>$this</span>->routeVar]) ? <span>$_GET</span>[<span>$this</span>->routeVar] : <span>$r</span><span>;
            }
            </span><span>if</span>(<span>$this</span>-><span>useStrictParsing)
                </span><span>throw</span> <span>new</span> CHttpException(404,Yii::t('yii','Unable to resolve the request "{route}".',
                    <span>array</span>('{route}'=><span>$pathInfo</span><span>)));
            </span><span>else</span>
                <span>return</span> <span>$pathInfo</span><span>;
        }
        </span><span>elseif</span>(<span>isset</span>(<span>$_GET</span>[<span>$this</span>-><span>routeVar]))
            </span><span>return</span> <span>$_GET</span>[<span>$this</span>-><span>routeVar];
        </span><span>elseif</span>(<span>isset</span>(<span>$_POST</span>[<span>$this</span>-><span>routeVar]))
            </span><span>return</span> <span>$_POST</span>[<span>$this</span>-><span>routeVar];
        </span><span>else</span>
            <span>return</span> ''<span>;
    }</span>

从上面的代码来看,如果我们不在url上传点东西,直接就return ''了。于是问题来了,参数要怎么传呢?

isset($_GET[$this-><span>routeVar]) <br /><br /></span>
<span>public</span> <span>$routeVar</span>='r';

于是有办法了,让我们一起来使点坏吧。加上这样的一个参数helloworld/index.php?r=abc

发现报错了。说明abc这个控制器是不存在的,事实上也是不存在的,使点小坏坏而已,正所谓男人不坏,女人不爱。

改成helloworld/index.php?r=site就可以显示hello world了,这是什么鬼原理呢?原因很简单,因为定义了site控制器嘛。

<span>class</span> SiteController <span>extends</span><span> CController
{
    </span><span>/*</span><span>*
     * Index action is the default action in a controller.
     </span><span>*/</span>
    <span>public</span> <span>function</span><span> actionIndex()
    {
        </span><span>echo</span> 'Hello World'<span>;
    }</span><span>
}</span>

好吧,这个我没有意见,但是actionIndex又是神么鬼?在yii中,这称为动作。它捕获的是控制器后面的参数,如果我们输?r=site/index就是index,动作是用“/"进行分隔的,为了验正一下我说的不是骗女孩子的鬼话,我在site控制器里加一个动作给你看一下:

<span>class</span> SiteController <span>extends</span><span> CController
{
    </span><span>/*</span><span>*
     * Index action is the default action in a controller.
     </span><span>*/</span>
    <span>public</span> <span>function</span><span> actionIndex()
    {
        </span><span>echo</span> 'Hello World'<span>;
    }

    </span><span>public</span> <span>function</span><span> actionView()
    {
        </span><span>echo</span> 'Hello View'<span>;
    }

}</span>

访问?r=site/view的时候,是不是看到输出'Hello View'了呢?肯定是的,虽然我读的书少,但是你骗不了我的,有图有真相:

我一点儿也不喜欢用site这个名字,test才是我的最爱,于是我又建了一个test控制器来尝试一下。

眼尖的一定看到怎么写了一个actions,这是什么鬼?我也是刚试了才知道,它其实是另一种表示方式。

我记得在blog那个例子中有用过,用来显示验证码:

    <span>/*</span><span>*
     * Declares class-based actions.
     </span><span>*/</span>
    <span>public</span> <span>function</span><span> actions()
    {
        </span><span>return</span> <span>array</span><span>(
            </span><span>//</span><span> captcha action renders the CAPTCHA image displayed on the contact page</span>
            'captcha'=><span>array</span><span>(
                </span>'class'=>'CCaptchaAction',
                'backColor'=>0xFFFFFF,<span>
            )</span>,
            <span>//</span><span> page action renders "static" pages stored under 'protected/views/site/pages'
            // They can be accessed via: index.php?r=site/page&view=FileName</span>
            'page'=><span>array</span><span>(
                </span>'class'=>'CViewAction',<span>
            )</span>,<span>
        );
    }</span>

我把它理解为集中声明第三方业务的动作集合,因为本控制器内的动作,我觉得还是action+ID 的方式直接。

什么鬼?你说我用的是index.php/site/captcha 而不是index.php?r=site/captcha .这又得从配置文件说起。

        'urlManager'=><span>array</span><span>(
            </span>'urlFormat'=>'path',
            'rules'=><span>array</span><span>(
                </span>'post/<id:\d+>/<title:.*?>'=>'post/view',
                'posts/<tag:.*?>'=>'post/index',
                '<controller:\w+>/<action:\w+>'=>'<controller>/<action>',<span>
            )</span>,<span>
        )</span>,

urlFormat 有path 和 get两种,如果在main.php中没有指定,那么就是get方式,也就是index.php?r=site/captcha这种。如果指定了,即index.php/site/captcha这种

从字面上也很好理解,path就是像路径的格式,get就是?这种形式。

关于路由和控制器部分的内容还有很多,但是本节就到这里了。

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn