Yii2创建form表单是个常见的情景,今天偶然的机会看到from表单id的两种写法:
第一种写法:
<?php $form = ActiveForm::begin([
'id'=>'myForm',
'method'=>'get',
'options' => ['class'=>'form-horizontal']
]);?>
第二种写法:
<?php $form = ActiveForm::begin([
'method'=>'get',
'options' => ['class'=>'form-horizontal','id'=>'myForm']
]);?>
两种写法经过的源码有一点点区别,简单的来看下源码:
首先,是ActiveForm::begin()
这个方法,他是在yiisoft\yii2\base\Widget.php
里的begin()
方法
public static function begin($config = [])
{
$config['class'] = get_called_class();
$widget = Yii::createObject($config);
static::$stack[] = $widget;
return $widget;
}
这个方法返回的是ActiveForm(yiisoft\yii2\widgets\ActiveForm)对象,而不是Widget对象,我们打印下返回的$widget对象,看看两种情况这个对象哪里不一样var_dump($widget);
第一种id的表单写法结果是:
object(yii\widgets\ActiveForm)
第二种id表单结果:
object(yii\widgets\ActiveForm)
可以看出,结果差不多一样,关键看后面几行["_id":"yii\base\Widget":private]
这个对应的值不一样,第一种的值是自己定义的id(myForm),第二种值为空,这里的_id是Widget.php里的一个属性(定义在110行左右)
begin()运行后,是运行init()方法(在yiisoft\yii2\widgets\ActiveForm):
public function init()
{
if (!isset($this->options['id'])) {
$this->options['id'] = $this->getId();
}
echo Html::beginForm($this->action, $this->method, $this->options);
}
这里的if语句不解,$this->options[‘id’])不是两种情况都有值的吗(var_dump($widget);),为什么第2种没运行进来第1种却运行进来了???
问题解决了,之前理解错了一直以为运行完begin后才会运行init的,原来是运行begin的时候会调用init的
如果你在options中没有指定id,那么框架就使用w0,w1,w2…这样的id.
首先你要理解init();在什么时候调用。
是在object创建的时候调用的魔术方法__construct();里面调用到init();
而静态方法的调用不会触发construct();
所以ActiveForm::begin();先执行begin();方法,在begin();方法中调用$widget = Yii::createObject($config);的时候,才触发construct();调用到init();
而$this->options中options的值是在__construct();中Yii::configure($this, $config);方法设置,所以你会发现你方法1中有init();有值而2中没值。
农民和楼上的解释挺好的