Yii Framework框架中事件和行为的区别及应用实例分析

本文实例讲述了Yii Framework框架中事件和行为的区别及应用。分享给大家供大家参考,具体如下:

个人觉得,在 Yii 里面,最难以明白的就是事件(Event)和行为(behavior)了。这不仅仅是因为它们的概念

比较难明,关键是它们的应用场景比较难明,不知道什么时候应该使用事件和行为来开发。

关于 Yii 的事件和行为的描述,可参考 http://www.yiiframework.com/doc/api/1.1/CComponent

本文参考的文章:

http://www.larryullman.com/2010/07/20/forcing-login-for-all-pages-in-yii/
http://www.yiiframework.com/wiki/44/behaviors-events/

事件

事件模型就是设计模式中的“观察者模式”:当对象的状态发生了变化,那么这个对象可以将该事件通知其它对象。
为了使用事件模型,需要实现这三个步骤:1、定义事件;2、注册事件句柄;3、触发事件。

为什么要做这三个步骤呢?因为对于 PHP 本身,它的执行过程不是以进程化来运行的,
所以 Yii 的事件触发机制不会像 ActionScript 3+ 那样,直接将触发事件。
有人说,Yii 的事件概念跟 js 中的事件概念差不多,因为 Yii 是将事件绑定到 Yii::app() 的执行过程中。
由于本人对于 js 的事件没有做过深入的了解,这里不敢贸然否定,或者肯定。

费话少说,先看这样的应用场景:

我想在请求过来的时候,先将请求的 IP 的记录到数据库,然后才进行对应的相应的请求处理。

1. 通过编辑 components/Controller.php 的构造方法来处理。

如代码:

class Controller extends CController
{
  public function __construct()
  {
    parent::__construct();
    //将请求的 IP 记录到数据库
  }
}

2. 通过使用事件来处理。

我们来分析一个 framework/base/CApplication.php 的 run() 方法

public function run()
{
  if($this->hasEventHandler('onBeginRequest'))
    $this->onBeginRequest(new CEvent($this));
  $this->processRequest();
  if($this->hasEventHandler('onEndRequest'))
    $this->onEndRequest(new CEvent($this));
}

从代码可以看出来,在处理请求之前,Yii 首先会判断一下当前有没有处理 onBeginRequest 的函数或者类的方法绑定了,

如果有这样的函数或者类的方法存在,则先执行了它们,然后再处理请求。

那么,怎样写 onBeginRequest,或者怎样去调用呢?

方法一:修改 index.php

一般来说,我们的 index.php 最后一句是:

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

我们在这里将它改造一下,改成:

$app = Yii::createWebApplication($config);
Yii::app()->onBeginRequest=function($event) {
  //将请求的 IP 记录到数据库
};
Yii::app()->onBeginRequest=function($event) {
  //其它的你想要处理的内容,比如说,生成一个文件
  //file_put_contents('onBeginRequest.txt', '阿妈,我得左啦!');
};
$app->run();

方法二:在配置文件 main.php 里面注册事件

如:

/***************************************************
在我们想要的内容的前后出现了这些代码
只是为了说明,我们添加的内容是要放在
这个配置数据的一维里面。
'import'=>array(
  'application.models.*',
  'application.components.*',
  'application.helpers.*',
),
'defaultController'=>'post',
***************************************************/

//其它代码
'import'=>array(
  'application.models.*',
  'application.components.*',
  'application.helpers.*',
),

/************** 这才是我们想要添加的代码 **************/
'onBeginRequest' => array('MyEventHandler', 'MyEventHandlerMethod'),

'defaultController'=>'post',
//其它代码

关于 onBeginRequest 的使用,它必须是一个有效的 PHP 回调。

即,一个指匿名函数,全局函数名的字符串或一个数组。如果是数组,那么该数组包含两个元素,第一个元素是一个对象,第二个元素是这个对象的方法。
由此可见,方法一和方法二还是有点区别的。使用方法二的时候,只能注册一个 PHP 回调,而使用方法一,可以是不同的 PHP 回调。当然,这里说的方法二
只能注册一个 PHP 回调是指,对整个请求处理过程中肯定会执行的 PHP 回调,在其它地方需要的时候,也可以加上你想实现的功能。

3. 另一个例子,来说明自己是怎样定义一个事件的。

打开 models/ContactForm.php,输入

/**
 * 自己定义发送邮件事件
 * @param unknown_type $event
 */
public function onSendMail($event)
{
  $this->raiseEvent('onSendMail',$event);
}

/**
 * 验证成功,执行
 * @see CModel::afterValidate()
 */
public function afterValidate()
{
  if($this->hasEventHandler('onSendMail'))
    $this->onSendMail(new CEvent($this));
}

这里我们定义了一个 onSendMail 事件,并在 Validate 验证后,触发此事件。

打开 controllers/SiteController.php,将修改actionContact修改为以下内容

public function actionContact()
{
  $model=new ContactForm;

  $model->onSendMail=function($event) {
    $headers="From: {$event->sender->email}\r\nReply-To: {$event->sender->email}";
    mail(Yii::app()->params['adminEmail'],$event->sender->subject,$event->sender->body,$headers);
  };

  if(isset($_POST['ContactForm']))
  {
    $model->attributes=$_POST['ContactForm'];
    if($model->validate())
    {

      Yii::app()->user->setFlash('contact','Thank you for contacting us. We will respond to you as soon as possible.');
      $this->refresh();
    }
  }
  $this->render('contact',array('model'=>$model));
}

上面的 3 点,虽然通过绑定事件来做一些额外的处理,但同时已经暴露了一个问题,就是协同开发的时候,我不一定知道,

其他开发人员写了哪些事件的 PHP 回调,在处理过程中到底会调用哪些事件的 PHP 回调。或者说,这个 PHP 回调在什么时候创建的,

或者说你在为组件添加事件处理函数时,找不到合适的时候,如果添加早了,组件还没创建,如果添加晚了,事件不被执行,有可能组件已经执行完了。

我们需要一个类似于配置文件的东西,将存在的事件处理组织起来,统一管理。这个时候,行为可以用上了。

行为

这里先重新描述一下为什么要使用行为。

有两种办法可以对类添加特性:

1、直接修改这个类的代码,添加一些成员函数和成员变量;
2、派生,通过子类来扩展。

很明显第二种方法更加易维护、易扩展。但是如果需要对一个类添加多个特性(多人在不同时期),那么需要进行多级派生,这显然加大了维护成本。

在 Yii 里面,通过行为类绑定,组件将一个或多个 CBehavior 类的成员方法和成员变量添加到自己身上,并且在不需要的时候载掉某些 CBehavior 类。

同时,可以通过重写 CBehavior::events 的方法,来实现对目标类的多个事件绑定。这些事件将会在当前行为绑定到目标类的时候,一起被绑定上。

下面我们以代码来具体看一下这个行为特性。

在 protected 创建目录 behaviors,并在protected/behaviors目录下创建ApplicationBehavior.php,输入如下代码:

<?php
class ApplicationBehavior extends CBehavior
{

  public function events()
  {
    return array_merge(parent::events(),array(
        'onBeginRequest'=>'beginRequest'
    ));
  }

  public function beginRequest($event)
  {
    echo "我已经将 onBeginRequest 的事件处理通过行为绑定了";
  }
}

此行为文件,是要为 CApplication 服务,仔细查看这个行为文件,我们可以看到,events 方法定义了些行为可以处理的事件,

上面的类,可以处理 onBeginRequest 事件,当然如果你自己定义的组件也有一个叫做 onBeginRequest 方法,你也可以使用此行为

后面的 beginRequest 就是事件的处理函数,这个处理函数必须要有行为类中定义。

跟上面的事件一样,也有两种方法将此行为类附加到 CApplication。

方法一:

打开 index.php,输入下面代码

$app = Yii::createWebApplication($config);
Yii::app()->onBeginRequest=function($event) {
  //将请求的 IP 记录到数据库
};
Yii::app()->onBeginRequest=function($event) {
  //file_put_contents('onBeginRequest.txt', '阿妈,我又得左啦!');
};
/****** 这句才是我们想要的东东 *********/
$app->attachBehavior('app', 'application.behaviors.ApplicationBehavior');
$app->run();

刷新页面,你将会在头部看到一行 “我已经将 onBeginRequest 的事件处理通过行为绑定了”

方法二:

如果对 Yii 的组件定义了解的话,应该知道每一个组件,都有一个behaviors方法,该方法中定义的相关行为,在组件初始化时,会自动附件,

下面我们就为 CApplication 定义 behaviors,由于 CApplication 是系统级类,我们可以扩展此类,并添加behaviors方法。这里补充一下,

CApplication 是会根据 config/main.php 配置进行初始化,那么我们就可以将 behaviors 定义在 main.php。

打开 protected/config/main.php,加入如下代码:

'behaviors' => array(
  'app' => 'application.behaviors.ApplicationBehavior',
),

刷新页面,你也会在头部看到一行 “我已经将 onBeginRequest 的事件处理通过行为绑定了”

通过以上的例子,希望相关读者对 Yii 的事件和行为有一定的了解。

更多关于Yii相关内容感兴趣的读者可查看本站专题:《Yii框架入门及常用技巧总结》、《php优秀开发框架总结》、《smarty模板入门基础教程》、《php面向对象程序设计入门教程》、《php字符串(string)用法总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》

希望本文所述对大家基于Yii框架的PHP程序设计有所帮助。

(0)

相关推荐

  • Yii框架组件的事件机制原理与用法分析

    本文实例讲述了Yii框架组件的事件机制原理与用法.分享给大家供大家参考,具体如下: 在深入分析 Yii 的运行之前,我们先来看一下 Yii 框架中一个很重要的机制 - 事件. Yii 官方参考文档关于组件事件的解释: ======================================================================= 组件事件是一些特殊的属性,它们使用一些称作 事件句柄 ( event handlers )的方法作为其值. 附加 ( 分配 ) 一个方法到

  • yii2行为的方法如何注入到组件类中详解

    前言 当了解了行为属性的注入逻辑后,方法的注入对于我们来说就很简单了.逻辑一样.只不过此刻我们不再调用 __get 方法,而是一个用于方法的 __call 方法.下面话不多说了,来一起看看详细的介绍: 在研究之前先跟我学习两个PHP的知识: __call call_user_func_array __call __call 是 PHP 的一个魔术方法,这个方法和 __get 功能差不多,当发现一个类的方法未定义时会触发此函数,它有两个参数 public mixed __call ( string

  • yii2学习教程之5种内置行为类详解

    前言 众所周知学习所有知识都需要循序渐进,行为也是一样,在我们学会很牛逼的新建行为,然后轻松注入到组件类之前,先看看yii2框架为我们准备的5个内置的行为类,也许你刚要用到~话不多说了,来一起看看详细的介绍: 本节的目的是让各位小伙伴在使用过程中对行为有一个整体上的感觉. 先亮亮相 TimestampBehavior SluggableBehavior BlameableBehavior AttributeTypecastBehavior AttributeBehavior 网上很多文章只是讲解

  • 深入解析PHP的Yii框架中的event事件机制

    事件 事件可以将自定义代码"注入"到现有代码中的特定执行点.附加自定义代码到某个事件,当这个事件被触发时,这些代码就会自动执行.例如,邮件程序对象成功发出消息时可触发 messageSent 事件.如想追踪成功发送的消息,可以附加相应追踪代码到messageSent 事件. Yii 引入了名为 yii\base\Component 的基类以支持事件.如果一个类需要触发事件就应该继承 yii\base\Component 或其子类. Yii的event机制 YII的事件机制,是其比较独特

  • YII框架行为behaviors用法示例

    本文实例讲述了YII框架行为behaviors用法.分享给大家供大家参考,具体如下: 文件 frontend/libs/FilterTest.php <?php /** * Created by PhpStorm. * Date: 2016/5/27 * Time: 14:16 */ namespace frontend\libs; use Yii; use yii\base\Action; use yii\base\ActionFilter; class FilterTest extends

  • YII2.0框架行为(Behavior)深入详解

    本文实例讲述了YII2.0框架行为(Behavior).分享给大家供大家参考,具体如下: 行为(Behavior) 使用行为(behavior)可以在不修改现有类的情况下,对类的功能进行扩充. 通过将行为绑定到一个类,可以使类具有行为本身所定义的属性和方法,就好像类本来就有这些属性和方法一样. 而且不需要写一个新的类去继承或包含现有类. Yii中的行为,其实是 yii\base\Behavior 类的实例, 只要将一个Behavior实例绑定到任意的 yii\base\Component 实例上

  • 详解PHP的Yii框架中组件行为的属性注入和方法注入

    行为的属性和方法注入原理 上面我们了解到了行为的用意在于将自身的属性和方法注入给所依附的类. 那么Yii中是如何将一个行为 yii\base\Behavior 的属性和方法, 注入到一个 yii\base\Component 中的呢? 对于属性而言,是通过 __get() 和 __set() 魔术方法来实现的. 对于方法,是通过 __call() 方法. 属性的注入 以读取为例,如果访问 $Component->property1 ,Yii在幕后干了些什么呢? 这个看看 yii\base\Com

  • PHP的Yii框架中行为的定义与绑定方法讲解

    定义行为 要定义行为,通过继承 yii\base\Behavior 或其子类来建立一个类.如: namespace app\components; use yii\base\Behavior; class MyBehavior extends Behavior { public $prop1; private $_prop2; public function getProp2() { return $this->_prop2; } public function setProp2($value)

  • 详解在PHP的Yii框架中使用行为Behaviors的方法

    一个绑定了行为的类,表现起来是这样的: // Step 1: 定义一个将绑定行为的类 class MyClass extends yii\base\Component { // 空的 } // Step 2: 定义一个行为类,他将绑定到MyClass上 class MyBehavior extends yii\base\Behavior { // 行为的一个属性 public $property1 = 'This is property in MyBehavior.'; // 行为的一个方法 p

  • Yii框架组件和事件行为管理详解

    本文实例讲述了Yii框架组件和事件行为管理.分享给大家供大家参考,具体如下: Yii是一个基于组件.用于开发大型 Web 应用的高性能 PHP 框架.CComponent几乎是所有类的基类,它控制着组件与事件的管理,其方法与属性如下,私有变量$_e数据存放事件(evnet,有些地方叫hook),$_m数组存放行为(behavior). 组件管理 YII是一个纯oop框架,很多类中的成员变量的受保护或者私有的,CComponent中利用php中的魔术方法__get(),__set()来访问和设置属

  • Yii2表单事件之Ajax提交实现方法

    本文实例讲述了Yii2表单事件之Ajax提交实现方法.分享给大家供大家参考,具体如下: 前言 Yii2 现在使用 JS 都必须要注册代码了. 要实现 Ajax 提交,有两种方法.一是直接在 ActiveForm 调用 beforeSubmit 参数,但是个人认为这样没有很好的把 JS 和 HTML 分开,所以我们这篇文章主要介绍第二种方法 - 外部写 JS 方法. 表单部分 <?php $form = ActiveForm::begin([ 'id' => $model->formNam

  • PHP的Yii框架中移除组件所绑定的行为的方法

    要移除行为,可以调用 yii\base\Component::detachBehavior() 方法用行为相关联的名字实现: $component->detachBehavior('myBehavior1'); 也可以移除全部行为: $component->detachBehaviors(); 这上面两种方法,都会调用到 yii\base\Behavior::detach() ,其代码如下: public function detach() { // 这得是个名花有主的行为才有解除一说 if

  • YII2框架中behavior行为的理解与使用方法示例

    本文实例讲述了YII2框架中behavior行为的理解与使用方法.分享给大家供大家参考,具体如下: YII2中的行为说白了就是对组件功能的扩展,在不改变继承关系的条件下. 行为附加到组件后,行为将注入自已的方法和属性到组件,可以像组件访问自定义的方法和属性一样访问行为. 注意行为是对功能的扩展,不要乱用行为,比如有一个动物类和一个人类,他们各自有自已的名称,身高,体重,这些是属性. 他们都会跑,这个时候我们就可以抽象出来做成一个跑的行为,根据不同需求来扩展他们. 这里我们有两个控制器一个Good

随机推荐