菜鸟常忽略的基础 - init方法

  • 作者:KK

  • 发表日期:2016.9.8


要点速读

  1. 不要随便重写__construct方法

    如果你写了一个类继承了Yii自带的类,那当你要重写构造方法时,请不要重写__construct,不然的话经常会出问题的

  2. 要做初始化工作就重写init方法,前提是这个类的父类中有yii\base\Componentyii\base\Object(放心大部分都有)

  3. 官方都说过,所有继承那2个类的子类都有init方法,建议重写这个方法来初始化


为毛要用init?

因为Yii之所以能实现定义这样的功能:

Yii::createObject('A', [
	'a' => 1,
	'b' => 2,
]);

是因为它的construct大概做了这样的事情:

class Component{
	public function __construct($attributes){
		foreach($attributes as $name => $attribute){
			$this->{$name} = $attribute;
		}
		
		$this->init();
	}
	
	public function init(){}
}

你重写了__construct的话,这些属性注入就实现不了啦


另外,重写Controller的__construct时会踩到个深坑

一般其实你重写了__construct不一定会马上发现问题,因为不一定刚好有底层或者你的代码调用了属性注入的代码嘛(除非是用在组件上)

但是如果你继承了yii\web\Controller或其他Controller后重写__construct,那保准你跑不起来

因为Yii对Controller的构建方法是另外定制了,属性注入要特殊处理的

且看yii\base\Controller::__construct方法,参数表是这样的:__construct($id, $module, $config = [])

(相关底层处理代码参考:yii\base\Module::createController的Yii::createObject($this->controllerMap[$id], [$id, $this])这个代码位置)

前面两个参数是底层创建控制器所必须的,如果你重写了__construct又不做好父类的处理,又不同步参数表,那肯定要吃Yii一棒了