Yii2.0 控制器的 behaviors [ 2.0 版本 ]
class CustomController extends ActiveController
{
public $modelClass = 'app\models\Custom';
// public $serializer = [
// 'class' => 'yii\rest\Serializer',
// 'collectionEnvelope' => 'items',
// ];
public function behaviors()
{
return ArrayHelper::merge(parent::behaviors(), [
'authenticator' => [
'class' => QueryParamAuth::className(),
],
'rateLimiter' => [
'class' => RateLimiter::className(),
'enableRateLimitHeaders' => false,
],
]);
}
}
源代码中,控制器的behaviors是在哪里处理的?
比如说:QueryParamAuth对象是在哪里实例化的?并且调用了authenticator()方法。
最佳答案
-
你给的例子,其实不能完全说明
behaviors
的行为,这里是filter
的行为,但filter
在yii2
和yii
中的实现不一样,yii2
中的filter
是特殊的behavior
,被框架多加了一层的处理,这里我只说明下filter
的调用, 普通的behavior
我暂时还没有用到,不清楚一句话,
QueryParamAuth
中authenticator()
方法,是在Controller
调用beforeAction
时触发的,你可以在Controller
复写beforeAction
方法为空操作,看看还会不会调用。在底层的
Controller
中,beforeAction
执行了$this->trigger(self::EVENT_BEFORE_ACTION, $event)
触发了EVENT_BEFORE_ACTION
事件,在yii\base\Component
中trigger
会首先ensureBehaviors()
,把behaviors()
定义的行为附加到Controller
上/** * Makes sure that the behaviors declared in [[behaviors()]] are attached to this component. */ public function ensureBehaviors() { if ($this->_behaviors === null) { $this->_behaviors = []; foreach ($this->behaviors() as $name => $behavior) { $this->attachBehaviorInternal($name, $behavior); } } } /** * Attaches a behavior to this component. * @param string|integer $name the name of the behavior. If this is an integer, it means the behavior * is an anonymous one. Otherwise, the behavior is a named one and any existing behavior with the same name * will be detached first. * @param string|array|Behavior $behavior the behavior to be attached * @return Behavior the attached behavior. */ private function attachBehaviorInternal($name, $behavior) { if (!($behavior instanceof Behavior)) { $behavior = Yii::createObject($behavior); } if (is_int($name)) { $behavior->attach($this); $this->_behaviors[] = $behavior; } else { if (isset($this->_behaviors[$name])) { $this->_behaviors[$name]->detach(); } $behavior->attach($this); $this->_behaviors[$name] = $behavior; } return $behavior; }
}
QueryParamAuth
最终继承自ActionFilter
的,来看看ActionFilter
在attach
时会做什么/** * @inheritdoc */ public function attach($owner) { $this->owner = $owner; $owner->on(Controller::EVENT_BEFORE_ACTION, [$this, 'beforeFilter']); }
会在
Controller
上绑定一个EVENT_BEFORE_ACTION
事件,行为是执行自己的beforeFilter
方法/** * @param ActionEvent $event */ public function beforeFilter($event) { if (!$this->isActive($event->action)) { return; } $event->isValid = $this->beforeAction($event->action); if ($event->isValid) { // call afterFilter only if beforeFilter succeeds // beforeFilter and afterFilter should be properly nested $this->owner->on(Controller::EVENT_AFTER_ACTION, [$this, 'afterFilter'], null, false); } else { $event->handled = true; } }
到这里,你看到了,
ActionFilter
最终会执行自己的beforeAction
方法,当然这可不是Controller
中的beforeAction
方法,还会处理些前置check,如except
和only
检测,这个beforeAction
正是你写 filter 时需要复写的一个方法,至于QueryParamAuth
的authenticator()
方法,自己可以接着走代码入口是
Controller
的beforeAction
方法,可以自己走一遍源代码,就这些
其他 0 个回答
jayce
最后登录:2015-06-09
在线时长:48小时16分
- 粉丝5
- 金钱175
- 威望0
- 积分655