我想在请求过来的时候,先将请求的 IP 的记录到数据库,然后才进行对应的相应的请求处理。
1
2
3
4
5
6
7
8
|
class Controller
extends
CController
{
public
function
__construct()
{
parent::__construct();
//将请求的 IP 记录到数据库
}
}
|
2. 通过使用事件来处理。
我们来分析一个 framework/base/CApplication.php 的 run() 方法
1
2
3
4
5
6
7
8
|
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 的函数或者类的方法绑定了,
1
|
Yii::createWebApplication(
$config
)->run();
|
我们在这里将它改造一下,改成:
1
2
3
4
5
6
7
8
9
|
$app
= Yii::createWebApplication(
$config
);
Yii::app()->onBeginRequest=
function
(
$event
) {
//将请求的 IP 记录到数据库
};
Yii::app()->onBeginRequest=
function
(
$event
) {
//其它的你想要处理的内容,比如说,生成一个文件
//file_put_contents('onBeginRequest.txt', '阿妈,我得左啦!');
};
$app
->run();
|
方法二:在配置文件 main.php 里面注册事件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
/***************************************************
在我们想要的内容的前后出现了这些代码
只是为了说明,我们添加的内容是要放在
这个配置数据的一维里面。
'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,写如下代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
/**
* 自己定义发送邮件事件
* @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 验证后,触发此事件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
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 点,虽然通过绑定事件来做一些额外的处理,但同时已经暴露了一个问题,就是协同开发的时候,我不一定知道,
行为
1
2
3
4
5
6
7
8
9
10
11
12
|
public
function
events()
{
return
array_merge
(parent::events(),
array
(
'onBeginRequest'
=>
'beginRequest'
));
}
public
function
beginRequest(
$event
)
{
echo
"我已经将 onBeginRequest 的事件处理通过行为绑定了"
;
}
}
|
此行为文件,是要为 CApplication 服务,仔细查看这个行为文件,我们可以看到,events 方法定义了些行为可以处理的事件,
跟上面的事件一样,也有两种方法将此行为类附加到 CApplication。
1
2
3
4
5
6
7
8
9
10
|
$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();
|
方法二:
1
2
3
|
'behaviors'
=>
array
(
'app'
=>
'application.behaviors.ApplicationBehavior'
,
),
|
通过以上的例子,希望相关读者对 Yii 的事件和行为有一定的了解。