목차
YII 的源码分析(-),yii源码分析
백엔드 개발 PHP 튜토리얼 YII 的源码分析(-),yii源码分析_PHP教程

YII 的源码分析(-),yii源码分析_PHP教程

Jul 13, 2016 am 10:12 AM
yii

YII 的源码分析(-),yii源码分析

做为源码分析的首秀,我就挑了yii(读作歪依依而不是歪爱爱);它的赞美之词我就不多说了,直接入正题。先准备材料,建议直从官网下载yii的源码包(1.1.15)最新版本。

在demos里边有一个最简单的应用—helloworld.就是用yii框架输出一句话:”hello world”;

我就从它下手,分析框架执行一个最小流程要经过哪些组件,浅析它的运行过程。

首先从单一入口文件开始阅读。(源码一般都是从调用处开始分析)

Index.php->

// include Yii bootstrap file

//引入启动文件

require_once(dirname(__FILE__).'/../../framework/yii.php');

 

yii.php ->

//YiiBase is a helper class serving common framework functionalities.

//YiiBase是一个助手类,它服务于整个框架。 这里定义了许多重要的常量

require(dirname(__FILE__).'/YiiBase.php');

//注册自动加载类

spl_autoload_register(array('YiiBase','autoload'));

//导入接口类

require(YII_PATH.'/base/interfaces.php');

//启动应用

Yii::createWebApplication()->run();

代码到这里似乎就终结了,页面的内容也程现出来,可是框架到底做了些什么,我们却一无所知。所以我们需要把这一步进行分解,把里边的细节暴露出来。

Yii::createWebApplication()->run() 一共可以分成三部分

Yii 这个东西是什么?

从yii.php 可以找到这样一行代码class Yii extends YiiBase

说明它就是YiiBase的继承类,而且作者的扩展是留空的,所以Yii就是YiiBase的一个引用而已。所以createWebApplication这个静态方法也得去YiiBase中查找了。

在YiiBase.php中,很容易就发现了这个方法:

public static function createWebApplication($config=null)

         {

                   return self::createApplication('CWebApplication',$config);

         }

它又把任务传递给了createApplication:

         public static function createApplication($class,$config=null)

         {

                   return new $class($config);

         }

结合起来看,createWebApplication () 就是return new CWebApplication($config);

这个CWebApplication类又在哪呢?它又是怎么引入的呢?

带着一系列的问题,我又回到了YiiBase.php

那里边定义了一个很长的数组,你可以找到:

'CWebApplication' => '/web/CWebApplication.php',这就是自动加载类中的一员

关于它是如何实现自动加载的,可以查看spl_autoload_register的相关文档,此处就节外生枝了.

 

我们继续往CWebApplication这个里边深挖。打开/web/CWebApplication.php这个文件。

前面提到return new CWebApplication($config);根据我的经验,用了new ,通常会有一个构造函数的,但我却没有找到它的构造函数,肯定是在它的父类中,于是我往上找,class CWebApplication extends CApplication 果然被我发现了,这就跟挖泥鳅一样的,得顺着线索一点点的找,要有耐心。

 

CApplication 中果然有构造函数,代码如下:

<span><span>public</span> <span>function</span> __construct(<span>$config</span>=<span>null</span><span>)

         {

                   Yii</span>::setApplication(<span>$this</span><span>);

 

                   </span><span>//</span><span> set basePath at early as possible to avoid trouble</span>

                   <span>if</span>(<span>is_string</span>(<span>$config</span><span>))

                            </span><span>$config</span>=<span>require</span>(<span>$config</span><span>);

                   </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>);

                   Yii</span>::setPathOfAlias('application',<span>$this</span>-><span>getBasePath());

                   Yii</span>::setPathOfAlias('webroot',<span>dirname</span>(<span>$_SERVER</span>['SCRIPT_FILENAME'<span>]));

                   </span><span>if</span>(<span>isset</span>(<span>$config</span>['extensionPath'<span>]))

                   {

                            </span><span>$this</span>->setExtensionPath(<span>$config</span>['extensionPath'<span>]);

                            </span><span>unset</span>(<span>$config</span>['extensionPath'<span>]);

                   }

                   </span><span>else</span><span>

                            Yii</span>::setPathOfAlias('ext',<span>$this</span>->getBasePath().DIRECTORY_SEPARATOR.'extensions'<span>);

                   </span><span>if</span>(<span>isset</span>(<span>$config</span>['aliases'<span>]))

                   {

                            </span><span>$this</span>->setAliases(<span>$config</span>['aliases'<span>]);

                            </span><span>unset</span>(<span>$config</span>['aliases'<span>]);

                   }</span></span>
로그인 후 복사

//以上都可以看成是初始化,设置类的引用,别名,路径什么的。

$this->preinit();//暂时未发现有什么用,估计是留给后面扩展用的

$this->initSystemHandlers();//设置错误处理

$this->registerCoreComponents();//注册核心组件

$this->configure($config); //通过配置文件扩展类的属性,为空的时候什么也不做

$this->attachBehaviors($this->behaviors);

$this->preloadComponents();

$this->init();

}

$this下面的某些方法,在当前类是找不到的,因为它们可能是来自父类,最简单的方法就是ctrl+f搜索一下,没有就去类的声明处查看:

abstract class CApplication extends CModule

显然要进入CModule,如果此时还找不到想要方法,那么继续上一过程:

abstract class CModule extends CComponent

直到class CComponent

说明这就是当前这些家伙的老巢了。从代码的中注释中也可以看到:

CComponent is the base class for all components

说明我的想法是正确的,没错,它就是基类。

透过代码,我们可以发现,我们当前的应用,因为很多参数是空,所以很多逻辑都是直接跳过的。

看到这,$this的内容也大致明了啦。我们再回头看看

return new CWebApplication($config)->run();

通过前面的层层分析,此时的run方法也很好找了。就在CApplication 里边:

<span><span>public</span> <span>function</span><span> run()

         {

                   </span><span>if</span>(<span>$this</span>->hasEventHandler('onBeginRequest'<span>)){

                            </span><span>$this</span>->onBeginRequest(<span>new</span> CEvent(<span>$this</span><span>));

                   }

 

                   </span><span>register_shutdown_function</span>(<span>array</span>(<span>$this</span>,'end'),0,<span>false</span><span>);

                   </span><span>$this</span>-><span>processRequest();  

                   </span><span>if</span>(<span>$this</span>->hasEventHandler('onEndRequest'<span>)){

                            </span><span>$this</span>->onEndRequest(<span>new</span> CEvent(<span>$this</span><span>));

                   }

 

         }</span></span>
로그인 후 복사

重点放在:$this->processRequest(); 因为前面和后面部分都是注册事件相关的,当前条件下执行不到。

<span><span>abstract</span> <span>public</span> <span>function</span> processRequest(); 这个方法在当前类中是抽象的,所以肯定在它的子类中实现了。回去找CWebApplication:

         <span>public</span> <span>function</span><span> processRequest()

         {

                   </span><span>if</span>(<span>is_array</span>(<span>$this</span>->catchAllRequest) && <span>isset</span>(<span>$this</span>->catchAllRequest[0<span>]))

                   {

                            </span><span>$route</span>=<span>$this</span>->catchAllRequest[0<span>];

                            </span><span>foreach</span>(<span>array_splice</span>(<span>$this</span>->catchAllRequest,1) <span>as</span> <span>$name</span>=><span>$value</span><span>)

                                     </span><span>$_GET</span>[<span>$name</span>]=<span>$value</span><span>;

                   }

                   </span><span>else</span>

                            <span>$route</span>=<span>$this</span>->getUrlManager()->parseUrl(<span>$this</span>-><span>getRequest());

 

                   </span><span>$this</span>->runController(<span>$route</span><span>);

         }</span></span>
로그인 후 복사

注意重点在$this->runController($route);

<span><span>public</span> <span>function</span> runController(<span>$route</span><span>)

         {

                   </span><span>if</span>((<span>$ca</span>=<span>$this</span>->createController(<span>$route</span>))!==<span>null</span><span>)

                   {

                            </span><span>list</span>(<span>$controller</span>,<span>$actionID</span>)=<span>$ca</span><span>;

 

                            </span><span>$oldController</span>=<span>$this</span>-><span>_controller;

                            </span><span>$this</span>->_controller=<span>$controller</span><span>;

                            </span><span>$controller</span>-><span>init();

                            </span><span>$controller</span>->run(<span>$actionID</span><span>);

                            </span><span>$this</span>->_controller=<span>$oldController</span><span>;

                   }

                   </span><span>else</span>

                            <span>throw</span> <span>new</span> CHttpException(404,Yii::t('yii','Unable to resolve the request "{route}".',

                                     <span>array</span>('{route}'=><span>$route</span>===''?<span>$this</span>->defaultController:<span>$route</span><span>)));

         }</span></span>
로그인 후 복사

我们要注意的代码只有两行:

$controller->init();

$controller->run($actionID);

这里的$controller可以能过查看createController得知,就是默认的控制器Sitecontroller.php

而Action则是index,你问我是怎么看出来的?哈哈,我在猜不出来的地方echo或var_dump一下不就可以了吗?这么简单的逻辑,还轮不到xdebug 这样的神器出场。

显然,init什么也没有做,看看run做了什么

Sitecontroller中没有run方法,又要去它的父类中查找。

class SiteController extends CController

在CController中有这个方法:

<span><span>public</span> <span>function</span> run(<span>$actionID</span><span>)

         {

                   </span><span>if</span>((<span>$action</span>=<span>$this</span>->createAction(<span>$actionID</span>))!==<span>null</span><span>)

                   {

                            </span><span>if</span>((<span>$parent</span>=<span>$this</span>->getModule())===<span>null</span><span>){

                                     </span><span>$parent</span>=Yii::<span>app();

                            }

 

                            </span><span>if</span>(<span>$parent</span>->beforeControllerAction(<span>$this</span>,<span>$action</span><span>))

                            {

                                     </span><span>$this</span>->runActionWithFilters(<span>$action</span>,<span>$this</span>-><span>filters());

                                     </span><span>$parent</span>->afterControllerAction(<span>$this</span>,<span>$action</span><span>);

                            }

                   }

                   </span><span>else</span>

                            <span>$this</span>->missingAction(<span>$actionID</span><span>);

         }

 </span></span>
로그인 후 복사

能过查看$this->createAction($actionID),得到return new CInlineAction($this,$actionID);

我们呆会再看这个CInlineAction,先看$this->runActionWithFilters($action,$this->filters());

<span><span>public</span> <span>function</span> runActionWithFilters(<span>$action</span>,<span>$filters</span><span>)

         {

                   </span><span>if</span>(<span>empty</span>(<span>$filters</span><span>)){

                            </span><span>$this</span>->runAction(<span>$action</span><span>);

                   }

                   </span><span>else</span><span>

                   {

                            </span><span>$priorAction</span>=<span>$this</span>-><span>_action;

                            </span><span>$this</span>->_action=<span>$action</span><span>;

                            CFilterChain</span>::create(<span>$this</span>,<span>$action</span>,<span>$filters</span>)-><span>run();

                            </span><span>$this</span>->_action=<span>$priorAction</span><span>;

                   }

         }</span></span>
로그인 후 복사

显然$filters是空的,所以执行第一个表达式$this->runAction($action);

<span><span>public</span> <span>function</span> runAction(<span>$action</span><span>)

         {

 

                   </span><span>$priorAction</span>=<span>$this</span>-><span>_action;

                   </span><span>$this</span>->_action=<span>$action</span><span>;

                   </span><span>if</span>(<span>$this</span>->beforeAction(<span>$action</span><span>))

                   {

 

                            </span><span>if</span>(<span>$action</span>->runWithParams(<span>$this</span>->getActionParams())===<span>false</span><span>){

                                     </span><span>$this</span>->invalidActionParams(<span>$action</span><span>);

                            }

 

                            </span><span>else</span><span>{

                                     </span><span>$this</span>->afterAction(<span>$action</span><span>);

 

                            }

 

                   }

                   </span><span>$this</span>->_action=<span>$priorAction</span><span>;

         }</span></span>
로그인 후 복사

这段代码的重点是 $action->runWithParams($this->getActionParams())这一句;

这里的$action就是$this->createAction($actionID)返回的结果,而它的结果就是

return new CInlineAction($this,$actionID);

CInlineAction.php

是时候查看CInlineAction了;

<span> <span>public</span> <span>function</span> runWithParams(<span>$params</span><span>)

         {

                   </span><span>$methodName</span>='action'.<span>$this</span>-><span>getId();

                   </span><span>$controller</span>=<span>$this</span>-><span>getController();

                   </span><span>$method</span>=<span>new</span> ReflectionMethod(<span>$controller</span>, <span>$methodName</span><span>);

                   </span><span>if</span>(<span>$method</span>->getNumberOfParameters()>0<span>)

                            </span><span>return</span> <span>$this</span>->runWithParamsInternal(<span>$controller</span>, <span>$method</span>, <span>$params</span><span>);

                   </span><span>else</span>

                            <span>return</span> <span>$controller</span>-><span>$methodName</span><span>();

         }</span></span>
로그인 후 복사

哇哦,好高级,居然还用了反射,不过我喜欢!

不过呢,打印$method发现:

object(ReflectionMethod)#6 (2) {

["name"]=>

string(11) "actionIndex"

["class"]=>

string(14) "SiteController"

}

没有参数,所以此处代码相当于是执行了SiteController->actionIndex();

在class SiteController extends CController中可以看到actionIndex 的定义

<span> <span>public</span> <span>function</span><span> actionIndex()

         {

                   </span><span>echo</span> 'Hello World'<span>;

         }</span></span>
로그인 후 복사

 

于是就看到屏幕上那一句Hello World ,整个程序也就跑完了。也许有人要问了,为什么输出一句话还这么复杂,不是脱了裤子打屁吗? (请允许我的粗俗);

如果是这么简单的需求,当然不可能这么干。举这个例子,只是说明yii的基础流程,为下面的复杂应用做一个过渡。

Yii作为一个优秀的oop框架,这个例子只是介绍了它的继承,接口,mvc中的vc特性,关于数据模型,我将在后面的分析中陆续给出。最终的目标,是利用yii框架简化我们的开发过程。

好了,今天的分析就在到了,如果有什么不妥的,请留言,如果觉得有帮助,请顺手点个推荐!

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/924356.htmlTechArticleYII 的源码分析(-),yii源码分析 做为源码分析的首秀,我就挑了yii(读作歪依依而不是歪爱爱);它的赞美之词我就不多说了,直接入正题。先...
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

PHP에서 Yii3 프레임워크를 사용하는 방법은 무엇입니까? PHP에서 Yii3 프레임워크를 사용하는 방법은 무엇입니까? May 31, 2023 pm 10:42 PM

인터넷이 계속 발전함에 따라 웹 애플리케이션 개발에 대한 수요도 점점 높아지고 있습니다. 개발자의 경우 애플리케이션 개발에는 개발 효율성을 향상시킬 수 있는 안정적이고 효율적이며 강력한 프레임워크가 필요합니다. Yii는 풍부한 기능과 우수한 성능을 제공하는 선도적인 고성능 PHP 프레임워크입니다. Yii3은 Yii2를 기반으로 성능과 코드 품질을 더욱 최적화하는 Yii 프레임워크의 차세대 버전입니다. 이번 글에서는 Yii3 프레임워크를 사용하여 PHP 애플리케이션을 개발하는 방법을 소개하겠습니다.

PHP 프레임워크 Yii를 사용하여 고가용성 클라우드 백업 시스템을 개발하는 방법 PHP 프레임워크 Yii를 사용하여 고가용성 클라우드 백업 시스템을 개발하는 방법 Jun 27, 2023 am 09:04 AM

클라우드 컴퓨팅 기술이 지속적으로 발전하면서 데이터 백업은 모든 기업이 반드시 해야 할 일이 되었습니다. 이러한 맥락에서 가용성이 높은 클라우드 백업 시스템을 개발하는 것이 특히 중요합니다. PHP 프레임워크 Yii는 개발자가 고성능 웹 애플리케이션을 빠르게 구축하는 데 도움이 되는 강력한 프레임워크입니다. 다음은 Yii 프레임워크를 사용하여 고가용성 클라우드 백업 시스템을 개발하는 방법을 소개합니다. 데이터베이스 모델 설계 Yii 프레임워크에서 데이터베이스 모델은 매우 중요한 부분입니다. 데이터 백업 시스템에는 많은 테이블과 관계가 필요하기 때문에

Yii2 vs Phalcon: 그래픽 렌더링 애플리케이션 개발에 어떤 프레임워크가 더 좋나요? Yii2 vs Phalcon: 그래픽 렌더링 애플리케이션 개발에 어떤 프레임워크가 더 좋나요? Jun 19, 2023 am 08:09 AM

현재 정보화 시대에는 빅데이터, 인공지능, 클라우드 컴퓨팅 등의 기술이 주요 기업의 화두가 되었습니다. 이러한 기술들 중에서 고성능 그래픽 처리 기술로서 그래픽 카드 렌더링 기술이 점점 주목을 받고 있다. 그래픽 카드 렌더링 기술은 게임 개발, 영화 및 TV 특수 효과, 엔지니어링 모델링 및 기타 분야에서 널리 사용됩니다. 개발자에게 자신의 프로젝트에 적합한 프레임워크를 선택하는 것은 매우 중요한 결정입니다. 현재 언어 중에서 PHP는 Yii2, Ph와 같은 뛰어난 PHP 프레임워크 중 매우 역동적인 언어입니다.

Symfony vs Yii2: 대규모 웹 애플리케이션 개발에 어떤 프레임워크가 더 좋나요? Symfony vs Yii2: 대규모 웹 애플리케이션 개발에 어떤 프레임워크가 더 좋나요? Jun 19, 2023 am 10:57 AM

웹 애플리케이션에 대한 수요가 계속 증가함에 따라 개발자는 개발 프레임워크를 선택할 때 점점 더 많은 선택권을 갖게 되었습니다. Symfony와 Yii2는 두 가지 인기 있는 PHP 프레임워크입니다. 둘 다 강력한 기능과 성능을 갖추고 있지만 대규모 웹 애플리케이션을 개발해야 하는 경우 어떤 프레임워크가 더 적합합니까? 다음으로 더 나은 선택을 하실 수 있도록 Symphony와 Yii2의 비교 분석을 진행하겠습니다. 기본 개요 Symphony는 PHP로 작성된 오픈 소스 웹 애플리케이션 프레임워크이며 다음을 기반으로 합니다.

Yii 프레임워크의 데이터 쿼리: 데이터에 효율적으로 액세스 Yii 프레임워크의 데이터 쿼리: 데이터에 효율적으로 액세스 Jun 21, 2023 am 11:22 AM

Yii 프레임워크는 웹 애플리케이션 개발 프로세스를 단순화하기 위한 다양한 도구와 구성 요소를 제공하는 오픈 소스 PHP 웹 애플리케이션 프레임워크입니다. 데이터 쿼리는 중요한 구성 요소 중 하나입니다. Yii 프레임워크에서는 SQL과 유사한 구문을 사용하여 데이터베이스에 액세스하여 데이터를 효율적으로 쿼리하고 조작할 수 있습니다. Yii 프레임워크의 쿼리 빌더에는 주로 ActiveRecord 쿼리, QueryBuilder 쿼리, 명령 쿼리 및 원본 SQL 쿼리 유형이 포함됩니다.

yii 객체를 배열로 변환하거나 json 형식으로 직접 출력하는 방법 yii 객체를 배열로 변환하거나 json 형식으로 직접 출력하는 방법 Jan 08, 2021 am 10:13 AM

Yii 프레임워크: 이 기사에서는 객체를 배열로 변환하거나 json 형식으로 직접 출력하는 Yii의 방법을 소개합니다. 이는 특정 참조 가치가 있으며 모든 사람에게 도움이 되기를 바랍니다.

Yii2 프로그래밍 가이드: Cron 서비스 실행 방법 Yii2 프로그래밍 가이드: Cron 서비스 실행 방법 Sep 01, 2023 pm 11:21 PM

"Yii가 무엇인가요?"라고 묻는다면 Yii의 이점을 검토하고 2014년 10월에 출시된 Yii 2.0의 새로운 기능을 간략하게 설명하는 이전 튜토리얼인 Yii 프레임워크 소개를 확인하세요. 흠> 이번 Yii2 프로그래밍 시리즈에서는 Yii2PHP 프레임워크를 사용하는 방법을 독자들에게 안내하겠습니다. 오늘 튜토리얼에서는 Yii의 콘솔 기능을 활용하여 크론 작업을 실행하는 방법을 공유하겠습니다. 과거에는 cron 작업에서 웹 액세스 가능 URL인 wget을 사용하여 백그라운드 작업을 실행했습니다. 이로 인해 보안 문제가 발생하고 일부 성능 문제가 발생합니다. Security for Startup 시리즈에서 위험을 완화하는 몇 가지 방법을 논의하는 동안 콘솔 기반 명령으로 전환하고 싶었습니다.

Yii 프레임워크의 양식 빌더: 복잡한 양식 작성 Yii 프레임워크의 양식 빌더: 복잡한 양식 작성 Jun 21, 2023 am 10:09 AM

인터넷의 급속한 발전으로 인해 웹 애플리케이션은 점차 사람들의 삶에 없어서는 안 될 부분이 되었습니다. 양식은 웹 애플리케이션에서 없어서는 안 될 요소 중 하나입니다. 양식은 웹 애플리케이션이 사용자에게 더 나은 서비스를 제공할 수 있도록 사용자 데이터를 수집하는 데 사용됩니다. Yii 프레임워크는 개발자가 웹 애플리케이션을 보다 빠르게 개발하는 데 도움이 되는 빠르고 효율적이며 유연한 PHP 프레임워크입니다. Yii 프레임워크의 양식 빌더(FormBuilder)를 사용하면 개발자가 복잡한 양식을 쉽게 구축하여 웹 애플리케이션을 더 효과적으로 만들 수 있습니다.

See all articles