YII 的源码分析(3)
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[<span style="color: #800080;">$i</span>]=<span style="color: #800080;">$rule</span>=Yii::createComponent(<span style="color: #800080;">$rule</span><span style="color: #000000;">); </span><span style="color: #0000ff;">if</span>((<span style="color: #800080;">$r</span>=<span style="color: #800080;">$rule</span>->parseUrl(<span style="color: #800080;">$this</span>,<span style="color: #800080;">$request</span>,<span style="color: #800080;">$pathInfo</span>,<span style="color: #800080;">$rawPathInfo</span>))!==<span style="color: #0000ff;">false</span><span style="color: #000000;">) </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">isset</span>(<span style="color: #800080;">$_GET</span>[<span style="color: #800080;">$this</span>->routeVar]) ? <span style="color: #800080;">$_GET</span>[<span style="color: #800080;">$this</span>->routeVar] : <span style="color: #800080;">$r</span><span style="color: #000000;">; } </span><span style="color: #0000ff;">if</span>(<span style="color: #800080;">$this</span>-><span style="color: #000000;">useStrictParsing) </span><span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> CHttpException(404,Yii::t('yii','Unable to resolve the request "{route}".', <span style="color: #0000ff;">array</span>('{route}'=><span style="color: #800080;">$pathInfo</span><span style="color: #000000;">))); </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">return</span> <span style="color: #800080;">$pathInfo</span><span style="color: #000000;">; } </span><span style="color: #0000ff;">elseif</span>(<span style="color: #0000ff;">isset</span>(<span style="color: #800080;">$_GET</span>[<span style="color: #800080;">$this</span>-><span style="color: #000000;">routeVar])) </span><span style="color: #0000ff;">return</span> <span style="color: #800080;">$_GET</span>[<span style="color: #800080;">$this</span>-><span style="color: #000000;">routeVar]; </span><span style="color: #0000ff;">elseif</span>(<span style="color: #0000ff;">isset</span>(<span style="color: #800080;">$_POST</span>[<span style="color: #800080;">$this</span>-><span style="color: #000000;">routeVar])) </span><span style="color: #0000ff;">return</span> <span style="color: #800080;">$_POST</span>[<span style="color: #800080;">$this</span>-><span style="color: #000000;">routeVar]; </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">return</span> ''<span style="color: #000000;">; }</span>
从上面的代码来看,如果我们不在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/<id:>/<.><.><controller:><action:><controller><action><span style="color: #000000;"></span><span style="color: #000000;"></span></action></controller></action:></controller:></.></.></id:>

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

index.html代表网页的首页文件,是网站的默认页面。当用户访问一个网站时,通常会首先加载index.html页面。HTML(HypertextMarkupLanguage)是一种用于创建网页的标记语言,index.html也是一种HTML文件。它包含网页的结构和内容,以及用于格式化和布局的标签和元素。下面是一个示例的index.html代码:<

许多用户在选择智能手表的时候都会选择的华为的品牌,其中华为GT3pro和GT4都是非常热门的选择,不少用户都很好奇华为GT3pro和GT4有什么区别,下面就就给大家介绍一下二者。华为GT3pro和GT4有什么区别一、外观GT4:46mm和41mm,材质是玻璃表镜+不锈钢机身+高分纤维后壳。GT3pro:46.6mm和42.9mm,材质是蓝宝石玻璃表镜+钛金属机身/陶瓷机身+陶瓷后壳二、健康GT4:采用最新的华为Truseen5.5+算法,结果会更加的精准。GT3pro:多了ECG心电图和血管及安

C语言return的用法有:1、对于返回值类型为void的函数,可以使用return语句来提前结束函数的执行;2、对于返回值类型不为void的函数,return语句的作用是将函数的执行结果返回给调用者;3、提前结束函数的执行,在函数内部,我们可以使用return语句来提前结束函数的执行,即使函数并没有返回值。

源码:publicclassReturnFinallyDemo{publicstaticvoidmain(String[]args){System.out.println(case1());}publicstaticintcase1(){intx;try{x=1;returnx;}finally{x=3;}}}#输出上述代码的输出可以简单地得出结论:return在finally之前执行,我们来看下字节码层面上发生了什么事情。下面截取case1方法的部分字节码,并且对照源码,将每个指令的含义注释在

为什么截图工具在Windows11上不起作用了解问题的根本原因有助于找到正确的解决方案。以下是截图工具可能无法正常工作的主要原因:对焦助手已打开:这可以防止截图工具打开。应用程序损坏:如果截图工具在启动时崩溃,则可能已损坏。过时的图形驱动程序:不兼容的驱动程序可能会干扰截图工具。来自其他应用程序的干扰:其他正在运行的应用程序可能与截图工具冲突。证书已过期:升级过程中的错误可能会导致此issu简单的解决方案这些适合大多数用户,不需要任何特殊的技术知识。1.更新窗口和Microsoft应用商店应用程

第1部分:初始故障排除步骤检查苹果的系统状态:在深入研究复杂的解决方案之前,让我们从基础知识开始。问题可能不在于您的设备;苹果的服务器可能会关闭。访问Apple的系统状态页面,查看AppStore是否正常工作。如果有问题,您所能做的就是等待Apple修复它。检查您的互联网连接:确保您拥有稳定的互联网连接,因为“无法连接到AppStore”问题有时可归因于连接不良。尝试在Wi-Fi和移动数据之间切换或重置网络设置(“常规”>“重置”>“重置网络设置”>设置)。更新您的iOS版本:

php提交表单通过后,弹出的对话框怎样在当前页弹出php提交表单通过后,弹出的对话框怎样在当前页弹出而不是在空白页弹出?想实现这样的效果:而不是空白页弹出:------解决方案--------------------如果你的验证用PHP在后端,那么就用Ajax;仅供参考:HTML code

Vue3.2setup语法糖是在单文件组件(SFC)中使用组合式API的编译时语法糖解决Vue3.0中setup需要繁琐将声明的变量、函数以及import引入的内容通过return向外暴露,才能在使用的问题1.在使用中无需return声明的变量、函数以及import引入的内容,即可在使用语法糖//import引入的内容import{getToday}from'./utils'//变量constmsg='Hello!'//函数func
