Table of Contents
yii源码分析4——非核心类的导入注册,yii源码
Home Backend Development PHP Tutorial yii source code analysis 4 - import registration of non-core classes, yii source code_PHP tutorial

yii source code analysis 4 - import registration of non-core classes, yii source code_PHP tutorial

Jul 13, 2016 am 09:57 AM
yii analyze import register Source code of kind

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>
Copy after login

实际上这个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>
Copy after login

注意到里面的$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>?> 
Copy after login

然后在父类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>
Copy after login

这里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>
Copy after login

可以看到,如果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>
Copy after login

然后是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>
Copy after login

一系列的判断,最后走到最后的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>
Copy after login

 

如果需要include的是非核心文件,那这里的$className只是一个alias,即文件名的前缀。

裁剪的yii http://files.cnblogs.com/TheViper/framework.zip

如果您觉得本文的内容对您有所帮助,您可以打赏我:

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/979000.htmlTechArticleyii源码分析4——非核心类的导入注册,yii源码 转载请注明: TheViperhttp://www.cnblogs.com/TheViper 在yii源码分析1中说到spl_autoload_register注册给定...
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How to register multiple accounts on Xiaohongshu? Will I be discovered if I register multiple accounts? How to register multiple accounts on Xiaohongshu? Will I be discovered if I register multiple accounts? Mar 25, 2024 am 09:41 AM

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

How to register a Xiaohongshu account? What is required to register a Xiaohongshu account? How to register a Xiaohongshu account? What is required to register a Xiaohongshu account? Mar 22, 2024 am 10:16 AM

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 &quot;Register&quot; 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

How to register a Xiaohongshu account? How to recover if its account is abnormal? How to register a Xiaohongshu account? How to recover if its account is abnormal? Mar 21, 2024 pm 04:57 PM

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 &quot;Me&quot; button in the lower right corner of the homepage, and then select &quot;Register&quot;. 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

How to register a qooapp account How to register a qooapp account Mar 19, 2024 pm 08:58 PM

qooapp is a software that can download many games, so how to register an account? Users need to click the &quot;Register&quot; 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

How to import local songs from NetEase Cloud Music How to import local songs How to import local songs from NetEase Cloud Music How to import local songs Mar 13, 2024 am 11:19 AM

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,

How to register two B-site numbers with one mobile phone number? How does Station B unbind its mobile phone? How to register two B-site numbers with one mobile phone number? How does Station B unbind its mobile phone? Mar 21, 2024 pm 10:10 PM

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 &quot;Register&quot; 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

How to register a video number matrix account? How to create your own video account? How to register a video number matrix account? How to create your own video account? Mar 22, 2024 am 10:42 AM

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 &quot;Discover&quot; page and click &quot;Video Account&quot; to enter the video account page. 3. Creator Center: At the bottom of the video account page, click the &quot;Creator Center&quot; button to enter the Creator Center. 4. Register a video account: On the Creator Center page, find the &quot;Register Video Account&quot; option.

How to check how long it has been since WeChat registration? How to check how long you have been registered on WeChat How to check how long it has been since WeChat registration? How to check how long you have been registered on WeChat Mar 13, 2024 am 08:52 AM

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

See all articles