【问题标题】:Creating Yii FormModel objects (CFormModel) dynamically动态创建 Yii FormModel 对象(CFormModel)
【发布时间】:2012-07-04 10:59:35
【问题描述】:

我正在开发一个涉及在高抽象级别生成表单的应用程序(它是一个 CMS 应用程序)。我想动态创建 CFormModel 对象并即时设置表单字段。我想我可以通过扩展 CFormModel 来做到这一点,然后动态创建代表表单字段的类属性(Yii 术语中的“属性”)。

为了说明,而不是在以下类中指定登录表单(在文件中定义):

// From: http://www.yiiframework.com/doc/guide/1.1/en/form.model
class LoginForm extends CFormModel
{
    public $username;
    public $password;
    public $rememberMe=false;

    private $_identity;

    public function rules()
    {
        return array(
            array('username, password', 'required'),
            array('rememberMe', 'boolean'),
            array('password', 'authenticate'), // assume function authenticate defined elsewhere
        );
    }
}

我想这样做:

class MyFormModel extends CFormModel {

    protected $_rules = array();

    public function __construct($attributes=array(), $rules=array()) {

        foreach ($attributes as $i => $attr) {
            $this->{$attr} = ???; // <<== This is the key here
        }

        // pass in array of rules as described in Yii doc for CFormModel
        $this->_rules = $rules;
    }

    public function rules() {
        return $_rules;
    }
}

并在需要时调用它,如下所示:

$myModelObj = new MyFormModel($attr, $rules);

在哪里:

$attr = array(
            'username',
            'rememberMe',
            'password',
        );
$rules = array(
            array('username, password', 'required'),
            array('rememberMe', 'boolean'),
            array('password', 'authenticate'), // assume function authenticate defined elsewhere
        );

注意我要完成的工作,任何文件中都没有写入“LoginClass”,它是在代码中动态创建的。

这将允许我创建表单(在视图中)做这样的事情:

// based on http://www.yiiframework.com/doc/guide/1.1/en/form.view
<?php echo $wForm->textField($myModelObj,'username'); ?>

等等

我试过了,$this->{$attr} 行失败了:

Property "MyFormModel.username" is not defined.

实际上该行的代码只是:

$this->{$attr};

???表示我不确定要为此分配什么。在 Yii 文档示例中,他们只是将字段定义为公共类变量。

我应该使用魔法方法吗?

我在这里尝试做的事情可能吗?

【问题讨论】:

    标签: php forms class yii magic-methods


    【解决方案1】:

    你可能知道 Yii 使用 OOP overloading 来解析你的 AR 属性。

    这里需要做的和 Yii 内部做的差不多。

    定义一个硬编码的属性来存储你所有的自定义属性,比如一个数组:$_data

    并且此数据将是一个数组,并将保存您在运行时添加的所有属性。您可能需要像 Yii 那样覆盖魔术方法(setters、getters、isset)来挑战验证,首先从您的$_data 属性持有者解析属性名称。

    你会在CActiveRecord 中找到某种代码来查找所有那些__XXX 类似的方法。

    如果您将 AR 属性处理复制到您的自定义类中,您将在您的级别上运行所有这些,并且当您的魔术方法无法解决它时将退回到 Yii。

    我还会研究行为,因为您可以将许多常见功能委托给行为类。

    组件行为的使用

    组件支持mixin 模式并且可以附加一个或多个行为。行为是一个对象,其方法可以通过收集功能而不是专门化(即普通类继承)的方式由其附加组件“继承”。一个组件可以附加多个行为,从而实现“多重继承”。

    行为类必须实现IBehavior 接口。大多数行为可以从CBehavior 基类扩展。如果需要将行为附加到模型,它还可以从 CModelBehaviorCActiveRecordBehavior 扩展,实现模型的附加功能。

    要使用行为,必须首先通过调用行为的attach() 方法将其附加到组件。然后我们可以通过组件调用行为方法:

    // $name uniquely identifies the behavior in the component
    $component->attachBehavior($name,$behavior);
    // test() is a method of $behavior
    $component->test();
    

    附加的行为可以像组件的普通属性一样被访问。例如,如果一个名为 tree 的行为附加到一个组件,我们可以使用以下方法获取对该行为对象的引用:

    $behavior=$component->tree;
    // equivalent to the following:
    // $behavior=$component->asa('tree');
    

    可以暂时禁用行为,使其方法无法通过组件使用。例如,

    $component->disableBehavior($name);
    // the following statement will throw an exception
    $component->test();
    $component->enableBehavior($name);
    // it works now
    $component->test();
    

    附加到同一组件的两个行为可能具有相同名称的方法。在这种情况下,第一个附加行为的方法将优先。

    events 一起使用时,行为更加强大。一个行为,当被附加到一个组件时,可以将它的一些方法附加到组件的一些事件上。这样,行为就有机会观察或改变组件的正常执行流程。

    行为的属性也可以通过它所附加的组件来访问。这些属性包括公共成员变量和通过行为的 getter 和/或 setter 定义的属性。例如,如果行为具有名为 xyz 的属性,并且该行为附加到组件 $a。然后我们可以使用表达式$a-&gt;xyz 来访问行为的属性。

    更多阅读:
    http://www.yiiframework.com/wiki/44/behaviors-events
    http://www.ramirezcobos.com/2010/11/19/how-to-create-a-yii-behavior/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多