首頁 php教程 php手册 YII框架源码分析(百度PHP大牛创作-原版-无广告无水印)

YII框架源码分析(百度PHP大牛创作-原版-无广告无水印)

Jun 13, 2016 am 09:33 AM
php學習筆記 yii

 

 

 

 

 

 

 

 

 

 

 

 

YII 框架源码分析

 

 

 

 

 

 

百度联盟事业部——黄银锋

 

目 录

1、 引言 3

1.1、Yii 简介 3

1.2、本文内容与结构 3

2、组件化与模块化 4

2.1、框架加载和运行流程 4

2.2、YiiBase 静态类 5

2.3、组件 6

2.4、模块 9

2.5 、App 应用   10

2.6 、WebApp 应用   11

3、系统组件 13

3.1、日志路由组件  13

3.2、Url 管理组件  15

3.3、异常处理组件  17

3.4、Cache 组件   17

3.5、角访问控制组件  19

3.6、全局状态组件  21

4、控制器层 23

4.1 、Action  23

4.2 、Filter   24

4.3 、Action 与 Filter 的执行流程   26

4.4、访问控制过滤器  27

5、模型层 30

5.1 、DAO 层   30

5.1.1、数据库连接组件   30

5.1.2、事务对象   31

5.1.3 、Command 对象   31

5.2 、元数据与 Command 构造器   32

5.2.1、表结构查询   32

5.2.2、查询条件对象   33

5.2.1 、Command 构造器   33

5.3 、ORM(ActiveRecord)   34

5.3.1、表的元数据信息   34

5.3.2 、单表 ORM   34

5.3.3 、多表 ORM   36

5.3.4 、CModel 与 CValidator   37

6、视图层 38

6.1、视图渲染流程  38

6.2、Widget   39

6.3、客户端脚本组件  40

 

1、引言

 

1.1、Yii 简介

 

Yii 的作者是美籍华人“薛强”,他原是 Prado 核心开发成员之一。2008 年薛强另起炉灶, 开发了 Yii 框架,于 2008 年 12 月 3 日发布了 Yii1.0 版本。

Yii 是目前比较优秀的 PHP 框架之一,它的支持的特性包括:MVC、DAO/ActiveRecord、 I18N/L10N、caching、AJAX 支持、用户认证和基于角色的访问控制、脚手架、输入验证、部 件、事件、主题化以及 Web 服务等。

Yii 的很多思想参考了其它一些比较优秀的 Web 框架(我们写东西时是不是也喜欢参考别人的? 有木有?嘿嘿,都喜欢站在别人的肩膀上干活!),下面是一个简短的列表:

框架名称

参考思想

Prado

基于组件和事件驱动编程模式、数据库抽象

层、模块化的应用架构、国际化和本地化等

Ruby on Rails

配置思想、基于 Active Record 的 ORM

jQuery

集成了 jQuery

Symfony

过滤设计和插件架构

Joomla

模块化设计和信息翻译方案

 

 

 

1.2、本文内容与结构

 

本文对 Yii1.1.8 版本的源代码进行了深入的分析,本文的内容与结构为: 组件化与模块化:对 Yii 的基于组件和事件驱动编程模式的基础类(CComponent)进行分

析;对组件化和模块化的工作原理进行分析;对 WebApp 应用创建 Controller 流程等进行分 析。

系统组件:对 Yii 框架自带的重要组件进行分析,主要包括:日志路由组件、Url 管理组 件、异常处理组件、Cache 组件、基于角色的访问控制组件等。

控制器层:控制器主要包含 Action 和 Filter,对 Action 与 Filter 的工作原理进行分析。 模型层:对 DAO 层、元数据和 Command 构造器、ORM 的原理进行分析

视图层:对视图层的渲染过程、Widget 和客户端脚本组件等进行分析

 

本文档中的错误或不妥之处在所难免,殷切希望本文档的读者给予批评指正!

 

2、组件化与模块化

 

2.1、框架加载和运行流程

 

 

 

start

 

 

加载YiiBase.php 1、安装autoload方法, 为类的实例化做准备 2、获得框架所有类的路 径(Yii1.1.8共208类)

 

 

 

 

根据ActionId创建Action对象 1、从成员函数中寻找Action 2、从ActionMap中寻找Action

 

 

加载request组件

(Get,Post,Cookie)

创建Action 否 异 是否成功? 常

 

 

创建WebApp实例 1、初始化别名:application、 webroot、ext 2、安装异常处理句柄,抛异常时 交给异常处理组件来处理 3、配置核心组件:urlManager、 errorHandler、session、db等 4、根据配置信息来配置组件、子 模块、WebApp成员属性等 5、加载preload组件:log组件、 request组件等

 

 

 

运行WebApp

1、触发onBeginRequest事件

 

 

加载Url管理组件 根据配置信息分析url,解析出路 由:route=ControllerId/ActionId

 

 

根据ControllerId创建控制器 1、从ControllerMap中寻找 2、从子模块中寻找 3、从ControllerPath中寻找

 

 

创建控制器 抛 是否成功?  否 异

 

 

根据filters()配置,创建出当 前Action的所有Filter对象

 

 

运行Filter1的preFilter方法 运行Filter2的preFilter方法

 

检查Get参 抛 数与Action 否 异 的参数是否      常

一致

 

 

运行Action

 

 

 

 

Partial render

渲染出核心部分的html

 

 

 

Layout render

渲染出整体的html

 

 

Client Script render 嵌入javascript、css生 成最终的html

 

 

 

echo html

 

 

 

2、处理请求

 

 

运行控制器

 

运行Filter2的postFilter方法 运行Filter1的postFilter方法

 

3、触发onEndRequest事件

 

 

 

注册的句柄:

 

异常处理 组件

 

 

XX处抛异常

throw Exception。。。

 

end

比如记录日志

 

 

Yii 框架加载和运行流程共分 4 个阶段(也许看着有点吓人,木有关系,我们先知道一个大概):

Step1:WebApp 初始化与运行

1.1、 加载 YiiBase.php,安装 autoload 方法;加载用户的配置文件;

1.2、 创建 WebApp 应用,并对 App 进行初始化,加载部分组件,最后执行 WebApp

Step2:控制器初始化与运行

2.1、 加载 request 组件,加载 Url 管理组件,获得路由信息 route=ControllerId/ActionId 2.2、 创建出控制器实例,并运行控制器

Step3:控制器初始化与运行

3.1、 根据路由创建出 Action

3.2、 根据配置,创建出该 Action 的 Filter; 3.3、 执行 Filter 和 Action

Step4:渲染阶段

4.1、 渲染部分视图和渲染布局视图

4.2、 渲染注册的 javascript 和 css

 

 

 

2.2、YiiBase 静态类

 

YiiBase 为 YII 框架的运行提供了公共的基础功能:别名管理与对象创建管理。 在创建一个 php 的对象时,需要先 include 这个类的定义文件,然后再 new 这个对象。

在不同环境下(开发环境/测试环境/线上环境),apache 的 webroot 路径的配置可能不一样, 所以这个类的定义文件的全路径就会不同,Yii 框架通过 YiiBase 的别名管理来解决了这个问 题。

在 创 建 对象时 , 需 要导入 对应 类的定义 , 经常需 要 使 用这 5 个 函数 : include()、 include_once()、require()、require_once()、set_include_path()。Yii 通过使用 YiiBase::import() 来统一解决这个问题。下图描述了 YiiBase 提供“别名管理与对象创建管理”的工作原理:

 

通过createComponent创建对象

 

 

1、如果类不存在,则通过import导入

通过new创建对象

 

2、new这个对象

 

3、根据输入对这个对象的属性初始化

 

 

 

 

 

import

导入一个类的定义

 

导入一个路径到

include_path

 

 

 

autoload

 

 

如果类是别名打头的,通过别管管理接口获得全路径

 

 

 

 

 

别名管理

 

getPathOfAlias setPathOfAlias

添加一个别名的全路径

 

首先看别名管理,它是通过为某个文件夹(一个文件夹往往对应一个模块)起一个别名, 在 YII 框架中可以使用这个别名来替代这个文件夹的全路径,比如:system 别名代表的是框 架 /home/work/yii/framework   的 路 径 , 所 以 可 以 使 用 system.base.CApplication   代表 

/home/work/yii/framework/base/CApplication.php 文件的路径。当然在应用层(我们)的代码中 也可以通过 Yii::setPathOfAlias 来注册别名。

一般情况下我们使用绝对路径或者相对路径来进行文件引用,当然这 2 种情况都有弊端。 绝对路径:当我们的代码部署到测试环境或者线上环境的时候需要大量修改被 include 文件 的路径;相对路径:当某些模块的文件夹的位置发生调整(改名)的时候,所有的相对路径都 需要修改。而使用别名的方式只需要改一处:注册别名的时候,即 Yii::setPathOfAlias()。从 而将文件夹的变动而导致的代码改动集中到一处完成。

再看 import 功能:a、导入一个类的定义,从而可以创建该类的对象;b、将某个文件夹 加入到 include_path,从而可以直接 include 这个文件下的所有文件。Yii::import 相当于如下

5  个函数的统一:include()、include_once()、require()、require_once()、set_include_path()。 而且一般情况下速度会比这些函数更快。当然 Yii::import 支持别名的功能,从而可以解决路 径变动带来的麻烦。

最后看一下对象的创建,在 YII 框架中有 2 中方法创建对象:1、使用 new 关键字;2、

 

使用 Yii::createComponent 方法。

当使用 new 关键字创建对象时,autoload 会分 3 步来寻找对应类的定义:a、判断是否 为 framework 中的类(framework 的所有类和这个类的全路径都保存在 YiiBase 的一个成员变 量中,就相当于整个框架都 import 了);2、判断是否使用 Yii::import 导入了这个类,对于非 框架的类,我们在创建这个类的对象时需要先 import 这个类的定义;3、从 include_path 目 录下查找以这个类名字命名的 php 脚本,所以在开发的时候类名尽量与文件名保存一致, 这样我们导入(import)包含这个文件的文件夹就行了,从而无需把这个文件夹中的每个文件 都导入一遍。

当使用 Yii::createComponent 方法创建对象时,它提供了比 new 关键字更多的功能:a、 通过这个类的全路径别名来指定类的位置和类名(类名必须与文件名一致),当这个类还没有 导入的时候,会根据全路径来自动导入这个类的定义;2、对创建出来的对象的成员变量进 行赋值。即如下图描述,原来要写 3 行以上的代码,现在一行代码就可以搞定(write less, do more)。

 

 

 

Yii::import('application.models.Student');

$obj = new Student();

$obj->age = 16;

$obj->name = 'jerry';

 

$obj = Yii::createComponent(array( 'class'=>'application.models.Student', 'age'=>16,

'name'=>'jerry'

));

 

 

 

 

 

2.3、组件

 

CComponent 类就是组件,它为整个框架的组件编程和事件驱动编程提供了基础,YII 框架中的大部分类都将 CComponent 类作为基类。CComponent 类为它的子类提供 3 个特性: 1、成员变量扩展

通过定义两个成员函数(getXXX/setXXX)来定义一个成员变量,比如:

public function getText() {…} public function setText {…}

这样就相当于定义了一个 text 成员变量,可以这样调用

$a=new CComponent;

$a=$component->text; // 等价于$a=$component->getText();

$component->text='abc'; // 等价于$component->setText('abc');

CComponent 是通过魔术方法 get 和 set 来实现“成员变量扩展”特性的,如果对类 本身不存在的成员变量进行操作时,php 会调用这个类的 get 和 set 方法来进行处理。 CComponent 利用这两个魔术方法实现了“成员变量扩展”特性。下图描述了一个 CComponent 的子类,它增加了 active 和 sessionName 两个成员变量,该图描述了对于这两个成员变量的 调用流程。

 

getActive

 

setActive

 

 

 

 

是否存在这个 成员变量

否 set()

get()

getSessionName

 

setSessionName

 

是 使用本对象的成员变量

 

 

getXXX setXXX

 

面向对象编程中直接定义一个成员变量就可以了,为什么 CComponent 要通过定义 2 个 函数来实现一个成员变量呢?一个主要得原因是需要对成员变量进行“延时加载”,一般情 况下类的成员变量是在构造函数或者初始化函数进行统一赋值,但是在一次 web 请求的处 理过程中不是每个成员变量都会被使用,比如 App 类中定义了两个成员变量:$cache 和$db

($cache 是一个缓存对象,$db 是一个数据库链接对象),这两个对象在 App 类初始化的时

候创建,但是一个 web 网站的有些页面,它内容可以通过缓存获取,那么数据库链接对象 其实就不需要创建。如果将 App 定义为 CComponent 的子类,在 App 类中定义两个方法: getCache/getDb,这样就可以做到第一次使用 db 成员变量的时候,才调用 getDb 函数来进行 数据库链接的初始化,从而实现延时加载——即在第一次使用时进行初始化。虽然延时加载 会增加一次函数调用,但是可以减少不必要的成员变量的初始化(总体上其实是提升了网站 的访问速度),而且可以使得我们的代码更加易维护、易扩展。

延时加载应该是“成员变量扩展”特性的最重要的用途,当然这个特性还会有其它用途, 想一想,当你操作一个成员变量的时候,你其实是在调用 getXXX 和 setXXX 成员函数,你是 在调用一段代码!

2、事件模型

事件模型就是设计模式中的“观察者模式”:当对象的状态发生了变化,那么这个对象 可以将该事件通知其它对象。

为了使用事件模型,需要实现这三个步骤:1、定义事件;2、注册事件句柄;3、触发 事件。

CComponent 的子类通过定义一个以 on 打头的成员函数来定义一个事件,比如:public function onClick(){…},接着通过调用 attachEventHandler 成员函数来注册事件句柄(可以注册 多个事件句柄),最后通过调用 raiseEvent 来触发事件。

 

attachEventHandler detachEventHandler raiseEvent

 

 

 

 

事件句柄容器

 

 

onclick

fun_11 fun_12

„ fun_1n

 

 

 

beforeinsert

fun_2n

 

 

 

afterinsert

fun_3n

 

 

 

„„

 

Key

 

fun_m1

 

 

Value

fun_mn

 

CComponent 类使用一个私有的成员变量来保存事件以及处理该事件的所有句柄,该成 员变量可以看作一个 hash 表,hash 表的 key 是事件的名称,hash 表的 value 是事件处理函 数链表。

3、行为类绑定

有两种办法可以对类添加特性:1、直接修改这个类的代码:添加一些成员函数和成员 变量;2、派生:通过子类来扩展。很明显第二种方法更加易维护、易扩展。如果需要对一 个类添加多个特性(多人在不同时期),那么需要进行多级派生,这显然加大了维护成本。 CComponent  使用一种特殊的方式对类信息扩展——行为类绑定。行为类是 CBehavior 类的一个子类,CComponent 可以将一个或者多个 CBehavior 类的成员函数和成员变量添加

到自己身上,并且在不需要的时候卸载掉某些 CBehavior 类。下面是一个简单的例子:

//计算器类

class Calculator extends CBehavior

{

public function add($x, $y) { return $x + $y; } public function sub($x, $y) { return $x - $y; }

...

}

$comp = new CComponent();

//为我的类添加计算器功能

$comp->attachbehavior('calculator', new Calculator());

$comp->add(2, 5);

$comp->sub(2, 5);

CComponent 通过 get、 set 和 call 这 3 个魔术方法来实现“行为类绑定”这个特性, 当调用 CComponent 类不存在的成员变量和成员方法的时候,CComponent 类会通过这三个 魔法方法在“动态绑定的行为对象”上进行查找。即将不存在的成员变量和成员方法路由到 “动态绑定对象”上。

 

attachBehavior detachBehavior

 

绑定一个对象   解除绑定

 

 

obj1

 

 

 

 set()

obj2

 

是否不存在

否 get()

查询各个对象

 

 call()

obj3

 

 

 

使用本对象的成员 变量和成员函数

 

 

 

绑定的对象

 

 

使用绑定对象流程 绑定的维护流程

 

可以用 3 句话来总结 CComponent 类的特性:

1、 更好的配置一个对象,当设置对象的成员变量的时候,其实是运行一段代码;

2、 更好的监听一个对象,当对象的内部状态发生变化的时候,其它对象可以得到通知;

3、 更好的扩展一个对象,可以给一个对象增加成员变量和成员函数,还能监听这个对 象的状态。

 

2.4、模块

 

模块是整个系统中一些相对独立的程序单元,完成一个相对独立的软件功能。比如 Yii 自带的 gii 模块,它实现了在线代码生成的功能。CModule 是所有模块类的基类,它有 3 部 分组成:

a、基本属性(模块 id,模块路径等); b、组件,这是模块的核心组成部分,模块可以看成这些组件的容器; c、子模块,这为模块提供了扩展性,比如一个模块做大了,可以拆成多个子模块(每个

子模块也是有这 3 部分组成,是一个递归结构)。 下图是模块与它的成员之间的包含关系图:

 

 

模板基

本属性 组件 子模块

 

下表列出了 CModule 各个组成部分:

3 部分

详细成员

说明

基本属性

(用户对整个模块的全局性 的东西进行配置)

id

模块的 id

parentModule

父模块

basePath

当前模块的路径

modulePath

子模块的路径

params

模块的参数

preload

需要预先加载的组件 id

behaviors

绑定的行为类

aliases

新增加的别名,添加到 YiiBase 的别名管理中

import

需要包含的文件或者路径

组件

(这是模块的核心组成部分)

components

数组类型,数组的每个成员描述了一个组件

子模块

(这为模块提供了扩展性)

modules

数组类型,数组的每个成员描述了一个模块,

每个模块也是有这 3 部分组成,是递归结构

可以非常方便的对模块的这 3 个组成部分进行初始化:使用一个数组进行配置,数组的 key 是需要配置的属性,value 就是需要配置的值,下图是一个例子,为什么会如此方面的进 行配置呢?因为 CModule 继承自 CComponent 类,所以在对成员属性进行配置的时候,其实 是在运行一段代码,即一个成员函数。

array(

'basePath'=>dirname( FILE ).DIRECTORY_SEPARATOR.'..',//模块的路径 'preload'=>array('log'),//需要预先加载日志组件

'import'=>array('application.models.*', 'application.components.*',),//需要include的路径

//组件的配置

'components'=>array( 'user'=>array(//用户组件的配置

'allowAutoLogin'=>true

),

 

'log'=>array(//日志组件的配置 'class'=>'CLogRouter',

'routes'=>array(array('class'=>'CWebLogRoute','levels'=>'trace, profile'))

)

),

//模块的配置

'modules'=>array(

'gii'=>array(//自动生成代码模块的配置 'class'=>'system.gii.GiiModule', 'password'=>'123456'

),

),

);

 

 

 

 

 

2.5 、App 应用

 

应用是指请求处理中的执行上下文。它的主要任务是分析用户请求并将其分派到合适的 控制器中以作进一步处理。它同时作为服务中心,维护应用级别的配置。鉴于此,应用也叫 做“前端控制器”。

Yii 使用 CApplication 类用来表示 App 应用,CApplication 继承自 CModule,它在父类基 础上做了 3 方面的扩展:1、增加一个 run 方法;2、添加了若干成员属性;3、添加了若干 组件。

run 方法的作用相当于 C 语言的 main 函数,是整个程序开始运行的入口,内部调用虚 函数 processRequest 来处理每个请求,CApplication 有 2 个子类:CWebApplication 和 CConsoleApplication,它们都实现了该方法。在处理每个请求的开始和结束分别发起了 onBeginRequest 和 onEndRequest 事件,用于通知监听的观察者。复习一下“Yii 框架加载和 运行流程”图,从中可以找到该方法在整个流程中所起的作用。

添加的成员变量、成员函数和组件见下表:

类别

名称

说明

成员变量

name

应用的名称

charset

应用的编码集,默认为 UTF-8

sourceLanguage

编码所使用的语言和区域 id 号,这在开发多语言时需要,

默认为 UTF-8

language

app 要求的语言和区域 id 号,默认为 sourceLanguage

runtimePath

运行时的路径,比如全局的状态会保存到这个路径下,默

认为 application.runtime

extensionPath

放第三方扩展的路径,默认为 application.ext

timezone

获取或者设置时区

locale

本地化对象,用于对时间、数字等的本地化

globalsate

全局状态数组,该数组会被持久化(通过 statePersister 实现)

组件

coreMessages

对框架层内容进行翻译,支持多语言

messages

对应用层内容进行翻译,支持多语言

 

 

 

db

数据库组件

errorHandler

异常处理组件,该组件与 App 配合来处理所有的异常

securityManager

安全管理组件

statePersister

状态持久化组件

urlManager

url 管理组件

request

请求组件

format

格式化组件

 

 

 

2.6 、WebApp 应用

 

每个 web 请求都由 WebApp 应用来处理,即 WebApp 应用为 http 请求的处理提供了运 行的环境。WebApp 应用就是 CWebApplication 类,它的最主要工作是根据 url 中的路由来创 建对于的控制类,下图描述了控制器创建的过程,主要由 3 步组成:

1、在成员变量 controllerMap 中查找,判断是否有对应的 Controller,controllerMap 的 优先级最高

2、在子模块中中查找,判断是否有对应的 Controller 3、在 ControllerPath 及其子文件夹中查找

搜索控制器的过程

输入的路由为:seg1/seg2/seg3

 

调用createController(‘seg1/seg2/seg3’,$app)

 

 

1

在controllerMap中寻 找id为seg1的控制类

 

 

调用createController(‘seg2/seg3’,

$subModule)

 

2 不存在

递归调用

 

在id为seg1的子模块 中寻找

 

 

 

不存在

3

在ControllerPath路 径下逐层寻找

 

 

是否存在ControllerPath/seg1/Seg2Controller.php ControlId为/seg1/seg2

不存在 是否存在ControllerPath/seg1/seg2/Seg3Controller.php

ControlId为/seg1/seg2/seg3

 

 

添加的重要的成员变量、成员函数和组件见下表:

类别

名称

说明

成员变量

defaultController

默认的控制类,如果没有指定控制器,则使用该控制器

 

layout

默认的布局,如果控制器没有指定布局,则使用该布局

 

controllerMap

控制器映射表,给某些特定的路由指定控制器

 

theme

设置主题

 

controller

当前的控制器对象

 

controllerPath

控制器文件的路径

 

 

 

ViewPath

视图层文件的路径,默认为 protected/views/

 

SystemViewPath

系统视图文件的路径,默认为 protected/views/system/

 

LayoutPath

布局文件的路径,默认为 protected/views/layouts/

组件

session

session 组件

 

assetManager

资源管理组件,用于发布私有的 js、css 和 image

 

user

用户组件,用户登录等

 

themeManager

主题组件

 

authManager

权限组件,实现了基于角色的权限控制

 

clientScript

客户端脚本管理组件,管理 js 和 css 代码

 

3、系统组件

 

3.1、日志路由组件

 

每个 Web 系统在运行的过程中都需要记录日志,日志可以记录到文件或数据库中,在 开发阶段可以把日志直接输出到页面得底部,这样可以加快开发速度。Yii 在日志处理上做 了如下 2 点重要工作:

1、每个 Http 请求,可能需要记录多条日志(数据库更新日志/与其它系统交互日志)。比 如某次 Http 请求要记录 18 条日志,我们是每记一条日志都写一次硬盘(即写 18 硬盘)呢,还 是在请求快结束的时候一次性写硬盘?很显然,先把这些日志保存在一个 php 的数组中, 在请求快结束的时候,把数组中的所有日志一次性写硬盘速度要快一些。

2、每条日志可以从 2 个维度来进行分类:日志的严重级别、日志的业务逻辑。用下表

来描述“百度创意专家”产品的日志在这 2 个维度上的情况:

业务逻辑

严重级别

数据库日志

用户中心接口日志

Drmc 接口日志

Memcache 日志

trace

 

 

 

 

info

 

 

 

 

profile

 

 

 

 

warning

 

 

 

 

error

 

 

 

 

按业务逻辑分为:数据库操作日志、用户中心接口日志、Drmc 接口日志、Memcache 更新日志等等。

按照严重级别分为:trace、info、profile、warning、error。 我们可能希望把不同业务逻辑(数据库日志、与其它系统交互的日志)的日志记录到不同

的文件中,这样可以分门别类的查看。因为 error 日志一般比较严重,所以我们可能还希望 把所有的 error 记录到一个单独的文件中或者 mongodb 中。Yii 中的日志路由组件可以将不 同类别的日志路由到不同的目的地(文件、数据库、邮箱和页面),利用它可以非常方便维护 和管理日志。

如下是一个日志路由组件的配置,该配置将不同业务逻辑的日志记录到不同的文件中, 把错误日志单独记录到 error.log 文件中,把严重的日志直接发邮件,在开发过程还将日志输 出到页面上,加快了开发速度。具体配置如下:

'log'=>array(

'class'=>'CLogRouter', 'routes'=>array(

array(//数据库日志记录到db.log中 'class'=>'CFileLogRoute', 'categories'=>'db.*', 'logFile'=>'db.log',

),

array(//与用户中心交互的日志记录到uc.log中 'class'=>'CFileLogRoute', 'categories'=>'uc.*',

 

'logFile'=>'uc.log',

),

array(//与Drmc交互的日志记录到uc.log中 'class'=>'CFileLogRoute', 'categories'=>'drmc.*', 'logFile'=>'drmc.log',

),

array(//所有的错误日志记录到error.log中 'class'=>'CFileLogRoute', 'levels'=>'error', 'logFile'=>'error.log',

),

array(//因为用户中心很重要,所有的用户中心错误日志需要离开发邮件

'class'=>'CEmailLogRoute', 'categories'=>'uc.*', 'levels'=>'error', 'emails'=>'admaker@baidu.com',

),

array(//开发过程中,把所有的日志直接打印到页面底部,这样就不需要登录服务器看日志了

'class'=>'CWebLogRoute' 'levels'=>'trace,info,profile,warning,error',

),

)

通过上面的代码可以知道,Yii 的日志记录是通过配置数组驱动的,接下来对 Yii 中日志

处理进行深入的分析,下图描述 Yii 中日志处理的流程和原理:

 

 

 

1、根据日志路由组件的配置, 生成多个日志记录对象

 

 

 

日志路由组件

 

 

日志记录对象1

db.log

 

 

 

 

 

 

 

2、将日志保存 到日志缓冲区

 

 

日志 缓冲区

 

 

 

3、缓冲区满或 请求结束时通知 日志路由组件

日志记录对象2

 

 

 

。。。

uc.log

 

 

 

 

日志记录对象i

 

5、把日志 输出到指定 的目的地

 

 

 

发送邮件日志

 

 

4、每个日志记录 对象从缓冲区中取 出自己需要的日志

 

 

 

日志记录对象N

 

 

 

日志输出到页面

 

 

 

一次 Http 请求的过程中,记录日志的处理流程分如下 5 个阶段:

 

Step1:根据日志路由器的配置信息,生成各个日志记录对象,即 CFileLogRoute、

CEmailLogRoute 和 CWebLogRoute 的对象,日志路由组件统一管理这些对象;

Step2:程序员调用写日志的接口(见下表),来记录日志,所有的日志都是暂时保存在一 个 php 的数组缓冲区中;

Step3:当缓冲区满的时候或请求处理结束的时候,会触发以个 Flush 事件,通知日志路 由组件来取日志,这里使用的就是是观察者模式;

Step4:每个日志记录对象分别取出自己需要的日志,比如数据库的日志、用户中心交 互日志、error 级别的日志

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

如何使用PHP框架Yii開發一個高可用的雲端備份系統 如何使用PHP框架Yii開發一個高可用的雲端備份系統 Jun 27, 2023 am 09:04 AM

隨著雲端運算技術的不斷發展,資料的備份已經成為了每個企業必須要做的事情。在這樣的背景下,開發一款高可用的雲端備份系統尤其重要。而PHP框架Yii是一款功能強大的框架,可以幫助開發者快速建立高效能的Web應用程式。以下將介紹如何使用Yii框架開發一款高可用的雲端備份系統。設計資料庫模型在Yii框架中,資料庫模型是非常重要的一環。因為資料備份系統需要用到很多的表和關

php如何使用Yii3框架? php如何使用Yii3框架? May 31, 2023 pm 10:42 PM

隨著互聯網的不斷發展,Web應用程式開發的需求也越來越高。對於開發人員而言,開發應用程式需要一個穩定、高效、強大的框架,這樣可以提高開發效率。 Yii是一款領先的高效能PHP框架,它提供了豐富的特性和良好的性能。 Yii3是Yii框架的下一代版本,它在Yii2的基礎上進一步優化了效能和程式碼品質。在這篇文章中,我們將介紹如何使用Yii3框架來開發PHP應用程式。

Symfony vs Yii2:哪個框架比較適合開發大型Web應用? Symfony vs Yii2:哪個框架比較適合開發大型Web應用? Jun 19, 2023 am 10:57 AM

隨著Web應用需求的不斷增長,開發者在選擇開發框架方面也越來越有選擇的空間。 Symfony和Yii2是兩個備受歡迎的PHP框架,它們都具有強大的功能和效能,但在面對需要開發大型網路應用程式時,哪個框架更適合呢?接下來我們將對Symphony和Yii2進行比較分析,以幫助你更好地進行選擇。基本概述Symphony是一個由PHP編寫的開源Web應用框架,它是建立

Yii框架中的資料查詢:有效率地存取數據 Yii框架中的資料查詢:有效率地存取數據 Jun 21, 2023 am 11:22 AM

Yii框架是一個開源的PHPWeb應用程式框架,提供了眾多的工具和元件,簡化了Web應用程式開發的流程,其中資料查詢是其中一個重要的元件之一。在Yii框架中,我們可以使用類似SQL的語法來存取資料庫,從而有效率地查詢和操作資料。 Yii框架的查詢建構器主要包括以下幾種類型:ActiveRecord查詢、QueryBuilder查詢、命令查詢和原始SQL查詢

Yii2 vs Phalcon:哪個框架更適合開發顯示卡渲染應用? Yii2 vs Phalcon:哪個框架更適合開發顯示卡渲染應用? Jun 19, 2023 am 08:09 AM

在當前資訊時代,大數據、人工智慧、雲端運算等技術已成為了各大企業關注的熱點。在這些技術中,顯示卡渲染技術作為一種高效能圖形處理技術,受到了越來越多的關注。顯示卡渲染技術廣泛應用於遊戲開發、影視特效、工程建模等領域。而對於開發者來說,選擇一個適合自己專案的框架,是一個非常重要的決策。在目前的語言中,PHP是一種相當有活力的語言,一些優秀的PHP框架如Yii2、Ph

Yii2程式設計指南:執行Cron服務的方法 Yii2程式設計指南:執行Cron服務的方法 Sep 01, 2023 pm 11:21 PM

如果您問「Yii是什麼?」請參閱我之前的教學:Yii框架簡介,其中回顧了Yii的優點,並概述了2014年10月發布的Yii2.0的新增功能。嗯>在這個使用Yii2程式設計系列中,我將指導讀者使用Yii2PHP框架。在今天的教學中,我將與您分享如何利用Yii的控制台功能來執行cron作業。過去,我在cron作業中使用了wget—可透過Web存取的URL來執行我的後台任務。這引發了安全性問題並存在一些效能問題。雖然我在我們的啟動系列安全性專題中討論了一些減輕風險的方法,但我曾希望過渡到控制台驅動的命令

Yii2 vs Symfony:哪個框架比較適合API開發? Yii2 vs Symfony:哪個框架比較適合API開發? Jun 18, 2023 pm 11:00 PM

隨著網路的快速發展,API成為了各種應用間資料交換的重要方式。因此,開發一款易於維護、高效、穩定的API框架變得越來越重要。而在選擇API框架時,Yii2和Symfony是兩個備受開發者歡迎的選擇。那麼,哪一個比較適合API開發呢?本文將對這兩個框架進行比較,並給出一些結論。一、基本介紹Yii2和Symfony都是成熟的PHP框架,都有相應的擴展,可以用來開

yii如何將物件轉換為陣列或直接輸出為json格式 yii如何將物件轉換為陣列或直接輸出為json格式 Jan 08, 2021 am 10:13 AM

yii框架:本文為大家介紹了yii將物件轉換為陣列或直接輸出為json格式的方法,具有一定的參考價值,希望能幫助大家。

See all articles