2012-07-03 19 views
4

我正在研究一個涉及在高級抽象級別(它是CMS應用程序)中生成表單的應用程序。我想動態創建CFormModel對象並即時設置表單域。我想我可以通過擴展CFormModel來實現,然後動態創建代表表單字段的屬性類(Yii lingo中的'attributes')。動態創建Yii FormModel對象(CFormModel)

爲了說明,而不是指定在下面的類登錄表單(在一個文件中定義):

// 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'); ?> 

我想這一點,和$此 - > {$ ATTR}線與失敗:

Property "MyFormModel.username" is not defined. 

實際上該行的代碼只是:

$this->{$attr}; 

The ???表示我並不確定要爲此分配什麼。在Yii doc示例中,他們只是將這些字段定義爲公共類變量。

我應該使用魔術方法嗎?

我試圖在這裏甚至有可能做什麼?

回答

4

正如你可能知道Yii使用OOP overloading來解決你的AR屬性。

你需要在這裏做什麼類似於Yii內部做的。

定義硬編碼的屬性來存儲類似於數組所有的自定義屬性:$_data

而這一數據將是一個數組,並會認爲你在運行時添加的所有屬性。您可能需要通過覆蓋魔術方法(setter,getters,isset)來挑戰驗證,如同Yii一樣,首先解析屬性名稱從您的$_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(); 

可以像組件的普通屬性那樣訪問附加行爲。例如,如果一個命名樹行爲被附接到一個組件,我們可以使用獲得參考此行爲對象:

$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->xyz來訪問行爲的屬性。

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