Как использовать Zend_Form-> createElement () - PullRequest
6 голосов
/ 05 июля 2011

У меня есть базовая форма пользователя, которую я делю на подклассы для каждого варианта использования, то есть зарегистрироваться, изменить и т. Д.

Некоторые элементы формы являются общими для всех случаев использования, и для них я использую форму в качестве фабрики элементов, например, $ 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", как он называется?

EDIT

Я использую методы init () в родительских и дочерних классах, а дочерняя init () вызывает родительскую init () в качестве своей первой задачи.

Ответы [ 3 ]

4 голосов
/ 05 июля 2011

Все работает как положено. Столкновение имен отсутствует, поскольку при использовании $ 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 () выполняет некоторую дальнейшую обработку. Конфликты имен отсутствуют, потому что вы выполняете одно и то же действие дважды (как указано Марчином в другом ответе), а во второй раз вы перезаписываете элемент самим собой.

Наконец, я также советую не создавать элементы, которые вы не будете использовать (пустая трата ресурсов и не очень хорошая практика программирования). Желательно сохранить ассоциативный массив конфигураций для возможно необходимых элементов в вашем родительском классе; затем в ваших подклассах вы создаете только те элементы, которые вам действительно нужны, используя соответствующие массивы конфигурации, которые были предварительно сохранены в родительском классе. Пример:

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 - здесь - внизу страницы - пример определения элемента с файлом INI).

3 голосов
/ 05 июля 2011

createElement не добавляет элемент в форму, он просто создает его. Если вы не добавите его в свою форму, форма не будет знать об этом. Вот почему $this->id и
$this->getElement('id') не работает в вашем первом примере.

Во втором примере вы сначала добавляете вновь созданный элемент в форму (т. Е. $this->id = $this->createElement('text', 'id', array(...));), а затем кажется, что вы добавляете его снова (т. Е. $this->addElement($this->id);). Я полагаю, что никакого столкновения имен не будет, поскольку Zend_Form просто переназначит его. Таким образом, я думаю, $this->addElement($this->id); на самом деле не нужен.

Надеюсь, это поможет.

0 голосов
/ 05 июля 2011

Предполагая, что вы используете Zend_Form :: init () и не вызываете parent :: init () в подклассе, вы можете переопределить метод родительского класса.Это означает, что ни один из ваших базовых элементов не добавляется в форму подкласса.Если вы добавите parent :: init () в init () подкласса, он унаследует родительские элементы в форме подкласса.Затем вы можете добавлять и удалять элементы по мере необходимости для подкласса.

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