yii 将动态属性设置为ModelClass

zengzsys  于 2022-11-09  发布在  其他
关注(0)|答案(1)|浏览(209)

我有一个模型,有许多属性(属性)。其中一个form_fields storeJSON用验证来填充动态表单字段。例如:

// ./protected/models/FormBuilder.php

/**
 * FormBuilder AR model class with dynamic field building capabilities
 *
 * @property integer $id
 * @property string $form_title
 * @property string $form_fields Form fields definitions stored as JSON String
 */
class FormBuilder extends CActiveRecord {

    public function init_form_model() {
        $dynamic_fields = CJSON::decode($this->form_fields);
        foreach($dynamic_fields as $field => $props) {
            // Neither this
            $this->$field = '';
            // nor this working!!!
            $this->setAttribute($field, '');
        }
    }

    /* other methods as it is */
}

// ./protected/controllers/FormBuilderController.php
class FormBuilderController extends CController {
    // ...
    public function actionServing($form_id) {
        $form = FormBuilder::models()->findByPk($form_id);
        $form->init_form_model();
        $this->render('dyn_frm', ['form' => $form]);
    }
    // ...
}

以上FormBuilder->init_form_model()方法中引发异常。该属性“FormBuilder.first_name”未定义。
有什么解决方案吗?如何进一步为模型类分配动态属性?Yii 1.1会在满足两个条件时设置属性,第一个条件是类本身已经定义了属性,第二个条件是AR模型的元数据中有一列被分配了该属性。
我也尝试使用PHP的ReflectionClass设置新属性,但得到了相同的错误消息。

txu3uszq

txu3uszq1#

好吧,我找到了解决方案来完成这个。PHP的重载工作得很好。
所以,我打开了Yii的CActiveRecord.php源代码,复制了它的四个魔术方法,并在我的model类中继承了如下:

/**
 * PHP getter magic method.
 * This method is overridden so that AR attributes can be accessed like properties.
 * @param string $name property name
 * @return mixed property value
 * @see getAttribute
 */
public function __get($name) {
    if (isset($this->form_fields[$name])) {
        if (isset($this->form_fields[$name]['value'])) {
            return $this->form_fields[$name]['value'];
        }
        return null;
    }

    return parent::__get($name);
}

/**
 * PHP setter magic method.
 * This method is overridden so that AR attributes can be accessed like properties.
 * @param string $name property name
 * @param mixed $value property value
 * @throws CException
 */
public function __set($name, $value) {
    if (isset($this->form_fields[$name])) {
        $this->form_fields[$name]['value'] = $value;
    } else {
        parent::__set($name, $value);
    }
}

/**
 * Checks if a property value is null.
 * This method overrides the parent implementation by checking
 * if the named attribute is null or not.
 * @param string $name the property name or the event name
 * @return boolean whether the property value is null
 */
public function __isset($name) {
    if (isset($this->form_fields[$name])) {
        return true;
    }
    return parent::__isset($name);
}

/**
 * Sets a component property to be null.
 * This method overrides the parent implementation by clearing
 * the specified attribute value.
 * @param string $name the property name or the event name
 * @throws CException
 */
public function __unset($name) {
    if (isset($this->form_fields[$name])) {
        unset($this->form_fields[$name]);
        return;
    }

    parent::__unset($name);
}

发现类似的问题在这里有答案:
Creating Yii FormModel objects (CFormModel) dynamically

相关问题