事件和行为的个人理解
首先,事件和行为是yii2框架下,组件类才拥有的功能。而组件类,即是yii\base\Component 类或其子类的实例。所以,yii2框架下,大部分的类都可以使用事件和行为。
事件是给指定实例或类绑定一个回调函数,在需要的时候,使用trigger调用即可。在YII2中,yii\base\Controller有内置的beforeAction、afterAction预定义事件函数;yii\base\Model有beforeValidate、afterValidate等预定义事件函数。这些函数中都使用trigger调用了预定义的事件。
行为是给类或实例绑定一个行为类,绑定后实例就可以调用行为类中的方法和属性。行为绑定内部原理和事件绑定相同,都是用了component基类的on方法。我们可以在行为类中,重写event方法,指定事件调用的方法。当组件调用该行为类后,组件中内置的如before~等事件会自动执行重写后指定的方法;而组件内没有的预定义事件,我们可以使用trigger调用事件,或者直接调用自定义的事件对应的方法名。
//建立一个行为类
class BaseBehavior extends Behavior{
public $owner;
public function events()
{
return [
‘beforeValidate’ => 'beforeValidate',
‘mine’ =>'formatResult',
];
}
public function beforeValidate(){
//验证前执行的事件
}
public function formatResult(){
//我的自定义事件
}
}
//建立一个model类
class UserModel extends Model{
public function behaviors()
{
return ['MyBehavior'=>BaseBehavior ::className];
}
//如果只想修改beforeValidate事件,可以不使用行为,重写beforeValidate即可
//也可以在类实例化后,直接使用on方法,设置beforeValidate事件
public function beforeValidate($action)
{
if (!parent::beforeValidate($action)) {
return false;
}
return true;
}
}
//运行model类
$model = new UserModel ();
//使用on方设置事件
$model->on('beforeValidate',function(){
//验证前可进行其他操作,比如检测参数的数量等
});
$model->validate();//运行该方法之前会调用beforeValidate事件
$model->trigger('mine');//使用trigger调用mine事件
$model->formatResult();//直接调用行为中的方
Yii2预定义的一些行为
我们只要在控制器中设施好这些行为,不需要在代码中自己去执行,框架在运行时,会自动在预定义这些行为的位置执行相关的方法。
控制器行为
public function behaviors(){
$behaviors = parent::behaviors();
//设置跨域请求相关,一般用在接口类控制器接口的基类中
$behaviors['cors'] = [
'class' => \tesoon\filters\Cors::className(),
'cors' => [
//设置允许跨域请求的域名,*表示不限
'Origin' => ['*'],
//设置允许的请求方式,*表示不限
'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
/*
浏览器的同源策略,就是出于安全考虑,浏览器会限制从脚本发起的跨域HTTP请求(比如异步请求GET, POST, PUT, DELETE, OPTIONS等等),
所以浏览器会向所请求的服务器发起两次请求,第一次是浏览器使用OPTIONS方法发起一个预检请求,第二次才是真正的异步请求,
第一次的预检请求获知服务器是否允许该跨域请求:如果允许,才发起第二次真实的请求;如果不允许,则拦截第二次请求。
Access-Control-Max-Age用来指定本次预检请求的有效期,单位为秒,在此期间不用发出另一条预检请求。
等于0时,表示每次异步请求都发起预检请求
*/
'Access-Control-Max-Age' => 86400,
'Access-Control-Request-Headers' => ['*'],
'Access-Control-Allow-Credentials' => true,
'Access-Control-Expose-Headers' => ['*'],
'Access-Control-Allow-Headers' => ['*']
],
];
//身份验证
$behaviors['authenticator'] = [
'class'=>QueryParamAuth::class,
];
//接口速率限制
$behaviors['rateLimiter'] = [
'class' => RateLimiter::className(),
];
//设置控制器返回数据格式,也可以在config中设置
$behaviors['contentNegotiator'] = [
'class' => ContentNegotiator::className(),
'formats' => [
'application/json' => Response::FORMAT_JSON,
],
];
//设置控制器下,方法的执行权限
//目前很少用到,对于需登录进行的操作,一般在身份认证时,即可阻断,不需要在这里设置
$behaviors['access'] = [
'class' => AccessControl::className(),
'only' => ['index', 'create', 'update'],
'rules' => [
// 允许认证用户
[
'allow' => true,
'roles' => ['@'],
],
// 禁止游客用户执行
[
'allow' => true,
'actions' => ['logout'],
'roles' => ['@'],
],
],
];
//过滤当前控制器下,方法允许的请求方式
$behaviors['verbFilter'] = [
'class' => VerbFilter::className(),
'actions' => [
'index' => [ 'get'], //只允许get方式访问
'create' => [ 'post'], //只允许用post方式访问
'update' => [ 'post']
],
];
return $behaviors;
}
模型行为
public function behaviors() {
return [
//匿名行为,自动添加更新时间戳字段
[
'class' => \yii\behaviors\TimestampBehavior::className(),
'attributes' => [
self::EVENT_BEFORE_INSERT => ['create_time','update_time'],
self::EVENT_BEFORE_UPDATE => ['update_time'],
],
],
];
}
yii\behaviors\AttributeBehavior: 当某些事件发生时, 将指定的值自动分配给 AR 对象的一个或多个属性.
yii\behaviors\TimestampBehavior: 使用当前时间戳自动填充指定的属性.
yii\behaviors\BlameableBehavior: 使用当前用户ID自动填写指定的属性.
yii\behaviors\SluggableBehavior: 自动使用一个可以在 URL 中使用的值来填充指定的属性.
yii\behaviors\AttributeTypecastBehavior: 提供模型属性类型的自动转换功能