当前位置: 首页 > 后端技术 > PHP

Codeigniter4.0-dev版源码学习笔记7——View视图

时间:2023-03-29 21:18:33 PHP

前言CI的View不像Laravel等一些流行的框架那么笨重,有自己的一套模板机制。CI一直使用纯天然的PHP模板Form,天然的好处就是不需要学习一套模板语言。缺点是不能使用一些方便的设计模式,比如继承布局等。当然你也可以添加第三方视图组件。接下来我们看源码,看源码,我们先从视图的调用说起。视图调用CI4开始使用新的视图调用逻辑,不再以加载的形式出现。调用方法如下:echoview('name');可以看到直接调用了一个视图函数。我们不需要提前加载这个函数。我在构造方法中没有看到任何包含文件。同时,这个方法似乎也不属于controller对象,那么它是从哪里来的呢?回到之前写的“二-入口及初始化操作”一节,提到在bootstrap.php第74行(原文件行号),需要一点BASEPATH.'Common.php',定义在这个文件许多辅助方法。view就是其中之一,这个方法位于system/common.php中的第88行(原文件行号)。贴出下面的代码:$保存数据=空;如果(array_key_exists('saveData',$options)&&$options['saveData']===true){$saveData=(bool)$options['saveData'];取消设置($options['saveData']']);}返回$renderer->setData($data,'raw')->render($name,$options,$saveData);}}可以看到,这里调用了Services类的renderer静态方法。后面的saveData逻辑主要处理多次调用view方法时是否共享视图变量,最后通过$renderer->setData方法将要传递的数据变量传递给视图渲染,最后执行render进行渲染风景。下面是Services::renderer()的源码(system/config/services.php:362):publicstaticfunctionrenderer($viewPath=APPPATH.'Views/',$config=null,$getShared=true){如果($getShared){returnself::getSharedInstance('renderer',$viewPath,$config);}if(is_null($config)){$config=new\Config\View();}returnnew\CodeIgniter\View\View($config,$viewPath,self::locator(true),CI_DEBUG,self::logger(true));}可以看出view方法主要是新建了一个CodeIgniterViewView类,它位于/system/ViewView.php下。总结一下,给个分析流程图,方便理解:接下来就是我们的主角View了。View源码分析根据上图的流程,我们需要看一下View类的三个关键方法,分别是__construct、setData、render。__construct方法publicfunction__construct($config,string$viewPath=null,$loader=null,bool$debug=null,Logger$logger=null){$this->config=$config;$this->viewPath=rtrim($viewPath,'/').'/';$this->loader=is_null($loader)?服务::定位器():$loader;$this->logger=is_null($logger)?服务::记录器():$记录器;$this->debug=is_null($debug)?CI_DEBUG:$调试;$this->saveData=$config->saveData??null;}可以看到,当services是new的时候,除了配置信息和视图路径外,只传递了视图数据,视图数据并没有包含在初始化中。setData方法publicfunctionsetData(array$data=[],string$context=null):RendererInterface{if(!empty($context)){$data=\esc($data,$context);}$this->data=array_merge($this->data,$data);return$this;}该方法的主要目的是将数据压入视图中,实际上就是将新压入的数据与对象中原有的数据(data)合并。render方法是view的逻辑,渲染view绝对是最重要的一个过程。下面是去掉注释和空行后的源码截图(源码分析中涉及的行号为截图中的行号):第142行:从参数中可以看出具体的视图文件名在调用render方法时传入。因为视图数据是通过setData方法放入当前对象的data属性中的,所以不需要再传一遍。第145-147、170-172行,处理是否将本次推送的视图数据共享给下一个渲染进程。这个$saveData可以在application/config/view.php中配置,默认为false。第149行:处理视图文件名后缀。第150-158行,如果判断开始缓存设置,处理视图缓存。第159-168行尝试通过自动加载机制找到视图文件。如果未找到,则抛出异常。168行很重要(重点加了),这个方法是把数组形式的数据展开成$key=$value的形式,因为view是一个普通的php包含在里面,所以$key也可以在视图中使用窗体读取变量的内容。第174-177行,开启outputcontrolbuffer机制,并include到view中,相当于同时执行了这个文件。这个文件中的普通html或者执行php后的输出都会被outputbuffer接收并赋值给$output。第179-182行,前端缓存是读进程,这里是写进程。第183行,最终返回渲染结果。结论从源码来看,CI使用了原有的PHP作为模板机制,使得视图逻辑非常简单。无非是包含视图,使用输出缓冲区获取执行结果。本文可转载,但转载前需发邮件至imustgxd*sina.cn进行交流,未交流的视为侵权。转载时必须同时注明链接,并保留该段文字。