2011-07-05 32 views
5

我有我繼承爲每個用例基本用戶的形式,即註冊,編輯等如何使用Zend_Form->的createElement()

一些表單元素共同所有的用例,併爲這些我使用表單作爲元素工廠,例如$ this-> addElement('text','first_name',array(...))。這工作正常。

對於僅在某些用例中需要的元素,我在基本窗體類中創建它們,但不添加它們,例如, $ this-> createElement('text','id',array(...))。當我到達子類本身時,那就是當我實際添加這些可選元素時。現在

,我認爲在子類中,我將能夠簡單地添加使用兩種元素:

$this->addElement($this->getElement('id')); 

或者

$this->addElement($this->id); 

但事實並非如此。我收到一個異常,說我想添加元素(NULL)。

我可以得到想要的結果的唯一方法是將create元素專門分配給成員變量,然後再使用該變量名稱。

例如在基本形式:

$this->id = $this->createElement('text', 'id', array(...)); 

然後在子類:

$this->addElement($this->id); 

在我看來,這應該產生一個變量名衝突。如果createElement沒有命名我的元素'id',它是什麼命名的?

編輯

我使用init()在兩家母公司和子類,和孩子的init()的方法調用父的init()作爲其首要任務。

回答

3

createElement不向表單添加元素,只是創建它。除非你將它添加到你的表單中,否則表單將不會知道它。這就是爲什麼$this->id
$this->getElement('id')不能在你的第一個例子中工作。

在第二個示例中,首先將新創建的元素添加到表單中(即$this->id = $this->createElement('text', 'id', array(...));),然後看起來您正在再次添加它(即$this->addElement($this->id);)。我相信不會有任何名字衝突,因爲Zend_Form只會重新分配它。因此我認爲$this->addElement($this->id);實際上並不需要。

希望這會有所幫助。

+0

感謝Marcin,您是對的 - 第二項任務不是必需的。當我回頭看看當天早些時候的子表單時,他們也有可選的元素。 –

0

假設你正在使用Zend_Form :: init()而不是在子類中調用parent :: init(),你可能會重寫父類的方法。這意味着您的基本元素都不會添加到子類窗體中。如果將parent :: init()添加到子類的init()中,它將繼承父元素到子類窗體。然後,您可以根據需要爲子類添加和刪除元素。

public function init() 
{ 
    parent::init(); 
    /** Additional code here **/ 
} 
+0

謝謝user828841。我按照建議使用init()。應該在我原來的問題中指出這一點。現在已經更新了這個問題... –

+0

如果你調用了parent :: init(),你不需要使用$ this-> addElement($ this-> getElement('id')); $ this-> getElement('id)意味着元素已經添加到表單中,因此您不需要冗餘 –

3

一切都按預期工作。沒有名稱衝突,因爲當您使用$ this-> createElement()時,您創建的元素實際上並不保存在任何位置。使用這種方法,您必須明確地將元素保存在某個變量(如成員變量)中,然後使用$ this-> addElement()將其添加到表單元素集。

如果你看看Zend_Form的源代碼,你會發現:

1-當調用的createElement(),元素被創建並立即返回;換句話說,該元素是不是內部保持在任何地方,所以你必須自己保存它,把它添加到表格後:

public function createElement($type, $name, $options = null) 
{ 
    ... 
    $element = new $class($name, $options); 
    return $element; 
} 

2 - 當你打電話的addElement(),元素被加入到窗體,並在內部保存在名爲_elements的受保護成員數組中。這是同樣的事情,這樣做:

$this->id = $this->createElement('text', 'id', array(...)); 

這神奇的addElement調用()(在他的評論中指出由用戶user594791)。你也可以直接把元素放在_elements數組中,但是我建議不要這樣做,因爲addElement()會做一些進一步的處理。沒有名稱衝突,因爲你正在做同樣的動作兩次(正如在另一個答案中由Marcin指出的那樣),並且在第二次你用自己覆蓋元素。

最後,我還建議不要使用實例化你不會使用的元素(浪費資源而不是很好的編程實踐)。最好在父類中爲可能必需的元素保留一個配置的關聯數組;那麼在你的子類中,你只能使用預先存儲在父類中的相應配置數組實例化你真正需要的元素。舉個例子:

class ParentForm extends Zend_Form { 
    ... 
    protected $_elementConfig; 
    ... 
    public function init() { 
     ... 
     // Add element configuration, but don't instantiate element right now 
     $this->_elementConfig = array(); 
     // Element 1, a text input 
     $this->elementConfig['myTextInput'] = array(
      'Text', 
      array(
       'label' => 'Theme', 
       'description' => 'Main application theme', 
       'maxLength' => 128, 
       'validators' => array(
        array('StringLength', false, array('max' => 128)) 
       ), 
       'filters' => array(
        array('HtmlEntities') 
       ) 
      ) 
     ); 
     // Element 2, a submit button 
     $this->elementConfig['mySubmitButton'] = array(
      'Submit', 
      array(
       'label' => 'Save' 
      ) 
     ); 
     // Element 3, something else 
     ... 
    } 
    ... 
} 

class ChildForm extends ParentForm { 
    public function init() { 
     parent::__construct(); // Parent init() is called by the parent constructor 
     ... 
     // Will use the submit button 
     $this->addElement(
      $this->_elementConfig['mySubmitButton'][0], // Type of element 
      'mySubmitButton', // Name of element 
      $this->_elementConfig['mySubmitButton'][1] // Config of element 
     ); 
    } 
} 

如果你有很多元素,並且不希望非常污染父init()方法,我建議您將完整的元素定義在外部文件中,它可以是一個PHP該文件返回一個帶有完整配置的PHP數組,一個XML文件,INI文件或Zend_Config支持的任何其他格式(您可以定義沒有一段實際PHP代碼的元素 - here - 在頁面底部 - 是一個使用INI文件定義元素的示例)。

+0

我認爲賦值給'$ this-> id'將執行__set方法,該方法將執行addElement方法來添加元素。 – user594791

+0

你是絕對正確的,我會糾正我的答案。我有時會忘記這些惡魔般的PHP巫師;) – faken

+0

嗨Faken,謝謝你的出色答案。我將這些分數授予Marcin,因爲他更準確,但是您的答案有一些很好的信息 - 是的,我只想在父表單中配置元素配置方法的更多細節... –