• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

YII 的源码分析(3)

php 搞代码 4年前 (2022-01-24) 20次浏览 已收录 0个评论

YII 的源码分析(三)

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

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

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

在CWebApplication中有这样一行代码:

<span style="color: #800080">$route</span>=<span style="color: #800080">$this</span>->getUrlManager()->parseUrl(<span style="color: #800080">$this</span>->getRequest());

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

    <span style="color: #0000ff">public</span> <span style="color: #0000ff">function</span><span style="color: #000000"> getUrlManager()    {        </span><span style="color: #0000ff">return</span> <span style="color: #800080">$this</span>->getComponent('urlManager'<span style="color: #000000">);    }</span>

这个又要通过找关系了.

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

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

    <span style="color: #0000ff">public</span> <span style="color: #0000ff">function</span> parseUrl(<span style="color: #800080">$request</span><span style="color: #000000">)    {        </span><span style="color: #0000ff">if</span>(<span style="color: #800080">$this</span>->getUrlFormat()===self::<span style="color: #000000">PATH_FORMAT)        {            </span><span style="color: #800080">$rawPathInfo</span>=<span style="color: #800080">$request</span>-><span style="color: #000000">getPathInfo();            </span><span style="color: #800080">$pathInfo</span>=<span style="color: #800080">$this</span>->removeUrlSuffix(<span style="color: #800080">$rawPathInfo</span>,<span style="color: #800080">$this</span>-><span style="color: #000000">urlSuffix);            </span><span style="color: #0000ff">foreach</span>(<span style="color: #800080">$this</span>->_rules <span style="color: #0000ff">as</span> <span style="color: #800080">$i</span>=><span style="color: #800080">$rule</span><span style="color: #000000">)            {                </span><span style="color: #0000ff">if</span>(<span style="color: #008080">is_array</span>(<span style="color: #800080">$rule</span><span style="color: #000000">))                    </span><span style="color: #800080">$this</span>->_rules[<strong>)本文来(源gaodai#ma#com搞@@代~&码*网2</strong><pre>搞代gaodaima码

$i]=$rule=Yii::createComponent($rule); if(($r=$rule->parseUrl($this,$request,$pathInfo,$rawPathInfo))!==false) return isset($_GET[$this->routeVar]) ? $_GET[$this->routeVar] : $r; } if($this->useStrictParsing) throw new CHttpException(404,Yii::t(‘yii’,’Unable to resolve the request “{route}”.’, array(‘{route}’=>$pathInfo))); else return $pathInfo; } elseif(isset($_GET[$this->routeVar])) return $_GET[$this->routeVar]; elseif(isset($_POST[$this->routeVar])) return $_POST[$this->routeVar]; else return; }

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

isset($_GET[$this-><span>routeVar]) <br /><br /></span>
<span style="color: #0000ff">public</span> <span style="color: #800080">$routeVar</span>='r';

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

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

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

<span style="color: #0000ff">class</span> SiteController <span style="color: #0000ff">extends</span><span style="color: #000000"> CController{    </span><span style="color: #008000">/*</span><span style="color: #008000">*     * Index action is the default action in a controller.     </span><span style="color: #008000">*/</span>    <span style="color: #0000ff">public</span> <span style="color: #0000ff">function</span><span style="color: #000000"> actionIndex()    {        </span><span style="color: #0000ff">echo</span> 'Hello World'<span style="color: #000000">;    }</span><span style="color: #000000">}</span>

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

<span style="color: #0000ff">class</span> SiteController <span style="color: #0000ff">extends</span><span style="color: #000000"> CController{    </span><span style="color: #008000">/*</span><span style="color: #008000">*     * Index action is the default action in a controller.     </span><span style="color: #008000">*/</span>    <span style="color: #0000ff">public</span> <span style="color: #0000ff">function</span><span style="color: #000000"> actionIndex()    {        </span><span style="color: #0000ff">echo</span> 'Hello World'<span style="color: #000000">;    }    </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">function</span><span style="color: #000000"> actionView()    {        </span><span style="color: #0000ff">echo</span> 'Hello View'<span style="color: #000000">;    }}</span>

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

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

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

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

    <span style="color: #008000">/*</span><span style="color: #008000">*     * Declares class-based actions.     </span><span style="color: #008000">*/</span>    <span style="color: #0000ff">public</span> <span style="color: #0000ff">function</span><span style="color: #000000"> actions()    {        </span><span style="color: #0000ff">return</span> <span style="color: #0000ff">array</span><span style="color: #000000">(            </span><span style="color: #008000">//</span><span style="color: #008000"> captcha action renders the CAPTCHA image displayed on the contact page</span>            'captcha'=><span style="color: #0000ff">array</span><span style="color: #000000">(                </span>'class'=>'CCaptchaAction',                'backColor'=>0xFFFFFF,<span style="color: #000000">            )</span>,            <span style="color: #008000">//</span><span style="color: #008000"> 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 style="color: #0000ff">array</span><span style="color: #000000">(                </span>'class'=>'CViewAction',<span style="color: #000000">            )</span>,<span style="color: #000000">        );    }</span>

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

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

        'urlManager'=><span style="color: #0000ff">array</span><span style="color: #000000">(            </span>'urlFormat'=>'path',            'rules'=><span style="color: #0000ff">array</span><span style="color: #000000">(                </span>'post//<title>'=>'post/view',                'posts/'=>'post/index',                '/'=>'/',<span style="color: #000000">            )</span>,<span style="color: #000000">        )</span>,

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

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

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


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:YII 的源码分析(3)

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址