


yii source code analysis 4 - import registration of non-core classes, yii source code_PHP tutorial
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
如果您觉得本文的内容对您有所帮助,您可以打赏我:

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

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

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



As a platform integrating social networking and e-commerce, Xiaohongshu has attracted more and more users to join. Some users hope to register multiple accounts to better experience interacting with Xiaohongshu. So, how to register multiple accounts on Xiaohongshu? 1. How to register multiple accounts on Xiaohongshu? 1. Use different mobile phone numbers to register. Currently, Xiaohongshu mainly uses mobile phone numbers to register accounts. Users sometimes try to purchase multiple mobile phone number cards and use them to register multiple Xiaohongshu accounts. However, this approach has some limitations, because purchasing multiple mobile phone number cards is cumbersome and costly. 2. Use email to register. In addition to your mobile phone number, your email can also be used to register a Xiaohongshu account. Users can prepare multiple email addresses and then use these email addresses to register accounts. but

Xiaohongshu, a social platform integrating life, entertainment, shopping and sharing, has become an indispensable part of the daily life of many young people. So, how to register a Xiaohongshu account? 1. How to register a Xiaohongshu account? 1. Open the Xiaohongshu official website or download the Xiaohongshu APP. Click the "Register" button below and you can choose different registration methods. Currently, Xiaohongshu supports registration with mobile phone numbers, email addresses, and third-party accounts (such as WeChat, QQ, Weibo, etc.). 3. Fill in the relevant information. According to the selected registration method, fill in the corresponding mobile phone number, email address or third-party account information. 4. Set a password. Set a strong password to keep your account secure. 5. Complete the verification. Follow the prompts to complete mobile phone verification or email verification. 6. Perfect the individual

As one of the most popular lifestyle sharing platforms in the world, Xiaohongshu has attracted a large number of users. So, how to register a Xiaohongshu account? This article will introduce you to the Xiaohongshu account registration process in detail, and answer the question of how to recover Xiaohongshu account abnormalities. 1. How to register a Xiaohongshu account? 1. Download the Xiaohongshu APP: Search and download the Xiaohongshu APP in the mobile app store, and open it after the installation is complete. 2. Register an account: After opening the Xiaohongshu APP, click the "Me" button in the lower right corner of the homepage, and then select "Register". 3. Fill in the registration information: Fill in the mobile phone number, set password, verification code and other registration information according to the prompts. 4. Complete personal information: After successful registration, follow the prompts to complete personal information, such as name, gender, birthday, etc. 5. Settings

qooapp is a software that can download many games, so how to register an account? Users need to click the "Register" button if they don't have a pass yet, and then choose a registration method. This account registration method introduction is enough to tell you how to operate it. The following is a detailed introduction, so take a look. How to register a qooapp account? Answer: Click to register, and then choose a registration method. Specific methods: 1. After entering the login interface, click below. Don’t have a pass yet? Apply now. 2. Then choose the login method you need. 3. You can use it directly after that. Official website registration: 1. Open the website https://apps.ppaooq.com/ and click on the upper right corner to register. 2. Select registration

When we use this platform to listen to songs, most of them should have some songs that you want to listen to. Of course, some things may not be listened to because there is no copyright. Of course, we can also directly use some songs imported locally. Go up there so you can listen. We can download some songs and directly convert them into mp3 formats, so that they can be scanned on the mobile phone for import and other situations. However, for most users, they don’t know much about importing local song content, so in order to solve these problems well, today the editor will also explain it to you. The content method allows you to make better choices without asking. If you are interested,

Bilibili (Bilibili), as a video sharing website very popular among Chinese young people, has attracted a large number of users. Some users hope to have two Bilibili accounts so that they can be managed and used separately. So, how to register two B-site numbers with one mobile phone number? This article will focus on this issue and how to unbind the mobile phone. 1. How to register two B-site numbers with one mobile phone number? 1. Register a new account: First, open the Bilibili App on your mobile phone or log in to the official website, click the "Register" button, and select the registration method. You can use your mobile phone number, email or third-party account (such as WeChat, QQ, etc.) to register. 2. When registering an account, please fill in the necessary information according to the system prompts, including mobile phone number, verification code, and set password. Be sure to use different accounts

With the launch of WeChat video accounts, more and more people have seen new traffic opportunities. Therefore, registering a video account matrix account has become the focus of many creators and merchants. So, how to register a video number matrix account? How to create your own video account? This article will answer these two questions in detail. 1. How to register a video number matrix account? 1. WeChat account: First, you need to have a WeChat account. If not, please register one first. 2. Open a video account: In the WeChat APP, find the "Discover" page and click "Video Account" to enter the video account page. 3. Creator Center: At the bottom of the video account page, click the "Creator Center" button to enter the Creator Center. 4. Register a video account: On the Creator Center page, find the "Register Video Account" option.

WeChat is a popular social software with rich functions and many users. If you want to check how long you have been registered on WeChat, although WeChat itself does not directly provide the function of checking the registration time, we can speculate through some indirect methods. However, these methods are not absolutely accurate as various factors may affect the accuracy of the results. If you have precise requirements for the registration time, it is recommended to contact WeChat customer service for consultation. How to check how long it has been since WeChat registration? The first way to see how long you have been registered on WeChat is by checking your QQ mailbox. If you use QQ to log in to WeChat, after successful registration, your QQ mailbox will receive a welcome email from WeChat. You can search for "WeChat" in your QQ mailbox to see if there is such an email, and then determine the registration time. The second way is by looking at
