动态创建Yii FormModel对象(CFormModel) [英] Creating Yii FormModel objects (CFormModel) dynamically

查看:78
本文介绍了动态创建Yii FormModel对象(CFormModel)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm working on an application that involves generating forms at a high level of abstraction (it's a CMS app). I want to dynamically create CFormModel objects and set the form fields on-the-fly. I think I can do this by extending CFormModel, and then dynamically creating the class properites that represent the form fields ('attributes' in the Yii lingo).

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

To illustrate, instead of specifying a login form in the following class (defined in a file):

// 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;
    }
}

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

And invoke it when needed as follows:

$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,

Note in what I'm trying to accomplish, there is no "LoginClass" written in any file, it's created on-the-fly in code.

这将允许我创建表单(在视图中)以执行以下操作:

This would allo me to create forms (in views) doing stuff like this:

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

等。

我尝试过这,并且$ this-> {$ attr}行失败并显示以下信息:

I've tried this, and the $this->{$attr} line is failing with:

Property "MyFormModel.username" is not defined.

实际上,该行的代码为:

Actually the code for that line is just:

$this->{$attr};

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

The ??? indicates I'm not really sure what to assign to this. In the Yii doc examples, they just define the fields as public class variables.

我应该使用魔术方法吗?

Should I be using magic methods?

我在这里甚至想做些什么吗?

Is what I'm trying to do here even possible?

推荐答案

您可能已经知道Yii使用 OOP重载来解决您的AR问题属性。

As you probably know Yii uses OOP overloading to resolve your AR like properties.

此处需要执行的操作与Yii内部执行的操作类似。

What you need to do here is similar to what Yii internally does.

定义硬编码属性将所有自定义属性存储为数组: $ _ data

Define a hardcoded property to store all your custom properties like an array: $_data

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

and this data will be an array and will hold all your attributes that you added at runtime. You may need to challenge the validation by overwriting the magic methods (setters,getters,isset) as Yii does, to first resolve the property names FROM your $_data property holder.

您会在 CActiveRecord 查找所有类似方法的 __ XXX

Some sort of code you will find in CActiveRecord look for all those __XXX like methods.

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

If you duplicate the AR property handling to your custom class, you will get all this running at your level, and will fall back to Yii when your magic methods are not resolving it.

我也会研究行为,因为您可以将很多通用函数委派给行为类。

Also I would look into Behaviours as you can delegate a lot of common function to a behaviour class.

使用组件行为

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

A component supports the mixin pattern and can be attached with one or several behaviors. A behavior is an object whose methods can be 'inherited' by its attached component through the means of collecting functionality instead of specialization (i.e., normal class inheritance). A component can be attached with several behaviors and thus achieve 'multiple inheritance'.

行为类必须实现 IBehavior 接口。大多数行为都可以从 CBehavior 基类扩展。如果需要将行为附加到模型,则它也可以从 CModelBehavior 扩展或 CActiveRecordBehavior ,它为模型实现了特定的其他功能。

Behavior classes must implement the IBehavior interface. Most behaviors can extend from the CBehavior base class. If a behavior needs to be attached to a model, it may also extend from CModelBehavior or CActiveRecordBehavior which implements additional features specifc for models.

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

To use a behavior, it must be attached to a component first by calling the behavior's attach() method. Then we can call a behavior method via the component:

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

可以像组件的常规属性一样访问附加行为。例如,如果将名为tree的行为附加到组件,则可以使用以下方法获取对此行为对象的引用:

An attached behavior can be accessed like a normal property of the component. For example, if a behavior named tree is attached to a component, we can obtain the reference to this behavior object using:

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

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

A behavior can be temporarily disabled so that its methods are not available via the component. For example,

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

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

It is possible that two behaviors attached to the same component have methods of the same name. In this case, the method of the first attached behavior will take precedence.

事件,行为就更加强大。将行为附加到组件时,可以将其某些方法附加到组件的某些事件。这样,该行为就有机会观察或更改该组件的正常执行流程。

When used together with events, behaviors are even more powerful. A behavior, when being attached to a component, can attach some of its methods to some events of the component. By doing so, the behavior gets a chance to observe or change the normal execution flow of the component.

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

A behavior's properties can also be accessed via the component it is attached to. The properties include both the public member variables and the properties defined via getters and/or setters of the behavior. For example, if a behavior has a property named xyz and the behavior is attached to a component $a. Then we can use the expression $a->xyz to access the behavior's property.

更多阅读:< br>
http://www.yiiframework.com/wiki/44/behaviors -事件

http://www.ramirezcobos.com/2010/11/19/how-to-create-a-yii-behavior/

这篇关于动态创建Yii FormModel对象(CFormModel)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆