


yii源码分析4——非核心类的导入注册,yii源码
转载请注明: TheViper http://www.cnblogs.com/TheViper
在yii源码分析1中说到spl_autoload_register注册给定的函数作为 __autoload 的实现,在这里是autoload().
<span>public</span> <span>static</span> <span>function</span> autoload(<span>$className</span><span>) { </span><span>include</span> self::<span>$_coreClasses</span> [<span>$className</span><span>]; }</span>
实际上这个autoload()是没有考虑非核心文件的引入的。比如,在app文件夹经常会有自定义的一些重要文件夹,比如'application.utils.*(工具类),'application.filters.*'(过滤类),'application.validators.*'(校验类)等。
在实际用的时候,是不用一个一个include的,直接new就可以了,yii已经帮我们做了include的工作。而这个工作就是在autoload()里面做的。
上面的代码很显然没有考虑非核心文件的引入,这是我的疏忽。
那yii是怎么帮我们引入非核心文件的?
这要从CApplication说起。
<span>abstract</span> <span>class</span> CApplication <span>extends</span><span> CModule { </span><span>public</span> <span>function</span> __construct(<span>$config</span> = <span>null</span><span>) { </span><span>if</span> (<span>is_string</span> ( <span>$config</span><span> )) </span><span>$config</span> = <span>require</span> (<span>$config</span><span>); Yii</span>::setApplication ( <span>$this</span> );<span>//</span><span>保存整个app实例</span> <span>if</span> (<span>isset</span> ( <span>$config</span> ['basePath'<span>] )) { </span><span>$this</span>->setBasePath ( <span>$config</span> ['basePath'<span>] ); </span><span>unset</span> ( <span>$config</span> ['basePath'<span>] ); } </span><span>else</span> <span>$this</span>->setBasePath ( 'protected'<span> ); </span><span>//</span><span>设置别名,后面就可以用application表示basePath了</span> Yii::setPathOfAlias ( 'application', <span>$this</span>-><span>getBasePath () ); </span><span>//</span><span>钩子,模块 预 初始化时执行,子类实现。不过这时,配置还没有写入框架</span> <span>$this</span>-><span>preinit (); </span><span>$this</span>-><span>registerCoreComponents (); </span><span>//</span><span>父类实现</span> <span>$this</span>->configure ( <span>$config</span><span> ); </span><span>//</span><span>加载静态应用组件</span> <span>$this</span>-><span>preloadComponents (); </span><span>//</span><span>这才开始初始化模块</span> <span>$this</span>-><span>init (); }</span>
注意到里面的$this->configure ( $config );,$config是传入的配置文件,是一个数组,非核心文件的定义就是在这里面,比如引入工具类文件夹
<?<span>php </span><span>return</span> <span>array</span><span> ( </span>'basePath' => <span>dirname</span> ( <span>__FILE__</span> ) . DIRECTORY_SEPARATOR . '..', 'import' => <span>array</span><span> ( </span>'application.utils.*'<span> ) ); </span>?>
然后在父类CModule
<span>public</span> <span>function</span> configure(<span>$config</span><span>) { </span><span>if</span> (<span>is_array</span> ( <span>$config</span><span> )) { </span><span>foreach</span> ( <span>$config</span> <span>as</span> <span>$key</span> => <span>$value</span><span> ) </span><span>$this</span>-><span>$key</span> = <span>$value</span><span>; } }</span>
这里yii很"狡猾",它在CModule的父类CComponent中重写了__set()
<span>public</span> <span>function</span> __set(<span>$name</span>,<span>$value</span><span>) { </span><span>$setter</span>='set'.<span>$name</span><span>; </span><span>if</span>(<span>method_exists</span>(<span>$this</span>,<span>$setter</span><span>)) </span><span>return</span> <span>$this</span>-><span>$setter</span>(<span>$value</span><span>); </span><span>else</span>....<span> }</span>
可以看到,如果CModule中如果有设置yii指定参数(比如import)的方法,就会调用它,而我之前裁剪的时候,把CModule中的setImport()删掉了。
另外可以看到basePath, params, modules, import, components 是yii保留的参数名。
<span>public</span> <span>function</span> setImport(<span>$aliases</span><span>) { </span><span>foreach</span>(<span>$aliases</span> <span>as</span> <span>$alias</span><span>) Yii</span>::import(<span>$alias</span><span>); }</span>
然后是YiiBase里面的import()
<span>public</span> <span>static</span> <span>function</span> import(<span>$alias</span>, <span>$forceInclude</span> = <span>false</span><span>) { </span><span>if</span> (<span>isset</span> ( self::<span>$_imports</span> [<span>$alias</span>] )) <span>//</span><span>是否已经存在路径</span> <span>return</span> self::<span>$_imports</span> [<span>$alias</span><span>]; </span><span>if</span> (<span>class_exists</span> ( <span>$alias</span>, <span>false</span> ) || <span>interface_exists</span> ( <span>$alias</span>, <span>false</span> ))<span>//</span><span>类是否已经定义,针对如urlManager这样的已定义于$_coreClasses[]的类</span> <span>return</span> self::<span>$_imports</span> [<span>$alias</span>] = <span>$alias</span><span>; </span><span>if</span> ((<span>$pos</span> = <span>strrpos</span> ( <span>$alias</span>, '.' )) === <span>false</span>) <span>//</span><span>直接是文件名</span> <span> { </span><span>//</span><span> try to autoload the class with an autoloader if $forceInclude is true</span> <span>if</span> (<span>$forceInclude</span> && (Yii::autoload ( <span>$alias</span>, <span>true</span> ) || <span>class_exists</span> ( <span>$alias</span>, <span>true</span><span> ))) self</span>::<span>$_imports</span> [<span>$alias</span>] = <span>$alias</span><span>; </span><span>return</span> <span>$alias</span><span>; } </span><span>$className</span> = ( <span>string</span> ) <span>substr</span> ( <span>$alias</span>, <span>$pos</span> + 1<span> ); </span><span>$isClass</span> = <span>$className</span> !== '*'<span>; </span><span>//</span><span>是否为路径+类名</span> <span>if</span> (<span>$isClass</span> && (<span>class_exists</span> ( <span>$className</span>, <span>false</span> ) || <span>interface_exists</span> ( <span>$className</span>, <span>false</span><span> ))) </span><span>return</span> self::<span>$_imports</span> [<span>$alias</span>] = <span>$className</span><span>; </span><span>//</span><span>获取真实路径</span> <span>if</span> ((<span>$path</span> = self::getPathOfAlias ( <span>$alias</span> )) !== <span>false</span><span>) { </span><span>//</span><span>是否以*结尾,如application.utils.*</span> <span>if</span> (<span>$isClass</span><span>) { </span><span>if</span> (<span>$forceInclude</span><span>) { </span><span>if</span> (<span>is_file</span> ( <span>$path</span> . '.php'<span> )) </span><span>require</span> (<span>$path</span> . '.php'<span>); </span><span>else</span> <span>throw</span> <span>new</span> CException ( Yii::t ( 'yii', 'Alias "{alias}" is invalid. Make sure it points to an existing PHP file and the file is readable.', <span>array</span><span> ( </span>'{alias}' => <span>$alias</span><span> ) ) ); self</span>::<span>$_imports</span> [<span>$alias</span>] = <span>$className</span><span>; } </span><span>else</span><span> self</span>::<span>$classMap</span> [<span>$className</span>] = <span>$path</span> . '.php'<span>; </span><span>return</span> <span>$className</span><span>; } </span><span>else</span> <span>//</span><span> a directory</span> <span> { </span><span>if</span> (self::<span>$_includePaths</span> === <span>null</span><span>) { self</span>::<span>$_includePaths</span> = <span>array_unique</span> ( <span>explode</span> ( PATH_SEPARATOR, <span>get_include_path</span><span> () ) ); </span><span>if</span> ((<span>$pos</span> = <span>array_search</span> ( '.', self::<span>$_includePaths</span>, <span>true</span> )) !== <span>false</span><span>) </span><span>unset</span> ( self::<span>$_includePaths</span> [<span>$pos</span><span>] ); } </span><span>array_unshift</span> ( self::<span>$_includePaths</span>, <span>$path</span><span> ); </span><span>if</span> (self::<span>$enableIncludePath</span> && <span>set_include_path</span> ( '.' . PATH_SEPARATOR . <span>implode</span> ( PATH_SEPARATOR, self::<span>$_includePaths</span> ) ) === <span>false</span><span>) self</span>::<span>$enableIncludePath</span> = <span>false</span><span>; </span><span>return</span> self::<span>$_imports</span> [<span>$alias</span>] = <span>$path</span><span>; } } }</span>
一系列的判断,最后走到最后的else,将path写入到$_imports,这时仍然没有include.
include在autoload()
<span>public</span> <span>static</span> <span>function</span> autoload(<span>$className</span><span>) { </span><span>//</span><span> use include so that the error PHP file may appear</span> <span>if</span>(<span>isset</span>(self::<span>$classMap</span>[<span>$className</span><span>])) </span><span>include</span>(self::<span>$classMap</span>[<span>$className</span><span>]); </span><span>elseif</span>(<span>isset</span>(self::<span>$_coreClasses</span>[<span>$className</span><span>])) </span><span>include</span>(self::<span>$_coreClasses</span>[<span>$className</span><span>]); </span><span>else</span><span> { </span><span>//</span><span> include class file relying on include_path</span> <span>if</span>(<span>strpos</span>(<span>$className</span>,'\\')===<span>false</span>) <span>//</span><span> class without namespace</span> <span> { </span><span>if</span>(self::<span>$enableIncludePath</span>===<span>false</span><span>) { </span><span>foreach</span>(self::<span>$_includePaths</span> <span>as</span> <span>$path</span><span>) { </span><span>$classFile</span>=<span>$path</span>.DIRECTORY_SEPARATOR.<span>$className</span>.'.php'<span>; </span><span>if</span>(<span>is_file</span>(<span>$classFile</span><span>)) { </span><span>include</span>(<span>$classFile</span><span>); </span><span>break</span><span>; } } } </span><span>else</span> <span>include</span>(<span>$className</span>.'.php'<span>); } </span><span>return</span> <span>class_exists</span>(<span>$className</span>,<span>false</span>) || <span>interface_exists</span>(<span>$className</span>,<span>false</span><span>); } </span><span>return</span> <span>true</span><span>; }</span>
如果需要include的是非核心文件,那这里的$className只是一个alias,即文件名的前缀。
裁剪的yii http://files.cnblogs.com/TheViper/framework.zip
如果您觉得本文的内容对您有所帮助,您可以打赏我:

Python语言作为一种高级编程语言,具有简单易学、易读易写等特点,在软件开发领域中得到了广泛的应用。然而,由于Python的开源特性,源代码很容易被他人轻易获取,这就给软件源码保护带来了一些挑战。因此,在实际应用中,我们常常需要采取一些方法来保护Python源代码,确保其安全性。在软件源码保护中,有多种针对Python的应用实践可供选择。下面将介绍几种常见

vue能显示源码,vue查看看源码的方法是:1、通过“git clone https://github.com/vuejs/vue.git”获取vue;2、通过“npm i”安装依赖;3、通过“npm i -g rollup”安装rollup;4、修改dev脚本;5、调试源码即可。

随着互联网的不断发展,Web应用程序开发的需求也越来越高。对于开发人员而言,开发应用程序需要一个稳定、高效、强大的框架,这样可以提高开发效率。Yii是一款领先的高性能PHP框架,它提供了丰富的特性和良好的性能。Yii3是Yii框架的下一代版本,它在Yii2的基础上进一步优化了性能和代码质量。在这篇文章中,我们将介绍如何使用Yii3框架来开发PHP应用程序。

随着云计算技术的不断发展,数据的备份已经成为了每个企业必须要做的事情。在这样的背景下,开发一款高可用的云备份系统尤为重要。而PHP框架Yii是一款功能强大的框架,可以帮助开发者快速构建高性能的Web应用程序。下面将介绍如何使用Yii框架开发一款高可用的云备份系统。设计数据库模型在Yii框架中,数据库模型是非常重要的一部分。因为数据备份系统需要用到很多的表和关

在当前信息时代,大数据、人工智能、云计算等技术已经成为了各大企业关注的热点。在这些技术中,显卡渲染技术作为一种高性能图形处理技术,受到了越来越多的关注。显卡渲染技术被广泛应用于游戏开发、影视特效、工程建模等领域。而对于开发者来说,选择一个适合自己项目的框架,是一个非常重要的决策。在当前的语言中,PHP是一种颇具活力的语言,一些优秀的PHP框架如Yii2、Ph

Yii框架是一个开源的PHPWeb应用程序框架,提供了众多的工具和组件,简化了Web应用程序开发的流程,其中数据查询是其中一个重要的组件之一。在Yii框架中,我们可以使用类似SQL的语法来访问数据库,从而高效地查询和操作数据。Yii框架的查询构建器主要包括以下几种类型:ActiveRecord查询、QueryBuilder查询、命令查询和原始SQL查询

随着Web应用需求的不断增长,开发者们在选择开发框架方面也越来越有选择的余地。Symfony和Yii2是两个备受欢迎的PHP框架,它们都具有强大的功能和性能,但在面对需要开发大型Web应用时,哪个框架更适合呢?接下来我们将对Symphony和Yii2进行比较分析,以帮助你更好地进行选择。基本概述Symphony是一个由PHP编写的开源Web应用框架,它是建立

yii框架:本文为大家介绍了yii将对象转化为数组或直接输出为json格式的方法,具有一定的参考价值,希望能够帮助到大家。


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

SAP NetWeaver Server Adapter for Eclipse
Integrate Eclipse with SAP NetWeaver application server.

EditPlus Chinese cracked version
Small size, syntax highlighting, does not support code prompt function

Dreamweaver Mac version
Visual web development tools

Notepad++7.3.1
Easy-to-use and free code editor

VSCode Windows 64-bit Download
A free and powerful IDE editor launched by Microsoft
