YII中行为Behavior运用 AOP介绍,以及例子
原创
©著作权归作者所有:来自51CTO博客作者廖圣平_的原创作品,请联系作者获取转载授权,否则将追究法律责任
之前有写一篇Thinkphp AOP 编程的例子 查看
AOP主要功能
日志记录,性能统计,安全控制,事务处理,异常处理等等wn及扩展
AOP主要意图
将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。
AOP的好处
查看aop 的好处例子
初识 yii 中的行为
点击跳转
项目中封装的BaseBehavior
<?php
namespace service\behavior;
use yii\base\Behavior;
use yii\web\Controller;
class BaseBehavior extends Behavior
{
public function beforeActionBase($event)
{
if (static::matchRoutes($this->only_routes)) {
return $this->beforeAction($event);
}
}
public function afterActionBase($event){
if (static::matchRoutes($this->only_routes)) {
return $this->afterAction($event);
}
}
public function events()
{
return [
Controller::EVENT_BEFORE_ACTION => 'beforeActionBase',
Controller::EVENT_AFTER_ACTION => 'afterActionBase'
];
}
public static function matchRoutes($routes)
{
$route = \Yii::$app->requestedRoute;
if (is_array($routes)) {
foreach ($routes as $r) {
if ($r == $route) {
return true;
}
$r = str_replace('/', '\/', $r);
$r = str_replace('*', '.*', $r);
$r = "/^{$r}$/";
if (preg_match($r, $route, $res)) {
return true;
}
}
}
return false;
}
}
封装的功能实践
比如 订单行为: 继承 BaseBehavior ,$only_routes 只有这些路由才回触发行为
我看到一些程序,是把定时任务的事件,放到这边做一个缓存10秒的执行。相当于一个10秒的定时器吧。
也可以把同步事件,写到这边。
这个根据系统的复杂度,和流量决定怎么来做的。
class OrderBehavior extends BaseBehavior
{
protected $only_routes = [
'mch/order/*',
'mch/share/*',
'mch/miaosha/*',
'api/order/*',
'api/share/*',
'api/miaosha/*',
// 'mch/store/index',
'mch/user/*',
'api/user/*'
];
public $store_id;
public $store;
public $share_setting;
public function beforeAction($e)
{
//订单过期检查之类事件
}
public function afterAction(){
echo "****";
}
行为在验证中的运用
class LoginBehavior extends ActionFilter
{
public function beforeAction($e)
{
$access_token = \Yii::$app->request->get('access_token');
if (!$access_token) {
$access_token = \Yii::$app->request->post('access_token');
}
if (!$access_token) {
\Yii::$app->response->data = new ApiResponse(-1, 'access_token 不能为空');
return false;
}
if (\Yii::$app->user->loginByAccessToken($access_token)) {
return true;
} else {
\Yii::$app->response->data = new ApiResponse(-1, '登录失败,');
return false;
}
}
}
如何在控制层运用行为:
class OrderController extends Controller
{
public function behaviors()
{
return array_merge(parent::behaviors(), [
'login' => [
'class' => LoginBehavior::className(),
],
]);
}
}
可以看处订单控制器,用了上面的login 验证器,同时,还继承了Controller 中的行为,以继承的方式,扩展了行为
那是不是全部控制器都会使用,并执行这么多的行为呢,这就是之前only_rule 的作用了
class Controller extends \yii\web\Controller
{
public function behaviors()
{
return [
'order' => [
'class' => OrderBehavior::className(),
],
'coupon' => [
'class' => CouponBehavior::className(),
],
'pintuan' => [
'class' => PintuanBehavior::className(),
],
'bargain' => [
'class' => BargainBehavior::className(),
],
'lottery' => [
'class' => LotteryBehavior::className(),
],
'step' => [
'class' => StepBehavior::className(),
],
];
}
}
总结
总结一下,Aop 编程,不是很像 extends 继承的关系嘛 ,这样写有啥意义。其实某种程度上是把系统复杂化了,而且增加了看似不必要的操作。
但是做一些saas 系统,或者比较大的系统,aop编程,具有易读性和可扩展性,你啥时候开心了,就插入一个功能,啥时候不开心了,就拔了另外一个功能,而且比较不影响,后面的常规操作。
相对于 继承方式实现‘aop’实际中的例子就很明显,比如在某个接口你想有一些不要继承的类,但是硬生生的运行了,但是对该程序没什么软用。
ok ,think you for your time !
参考代码:
https://github.com/liaoshengping/dingdong_shop.git