2011-07-05 11 views
5

Tengo una forma básica de usuario que estoy de subclases para cada caso de uso, es decir, registrar, editar, etc.Cómo utilizar Zend_Form-> createElement()

Algunos elementos del formulario son comunes a todos los casos de uso y para éstos Estoy usando la forma como una fábrica de elementos, por ejemplo $ this-> addElement ('text', 'first_name', array (...)). Eso funciona bien

Para los elementos que solo se requieren en algunos casos de uso, los estoy creando en la clase de formulario base, pero no los estoy agregando, p. Ej. $ this-> createElement ('text', 'id', array (...)). Cuando llego a la subclase, es cuando realmente agrego estos elementos opcionales.

Ahora, pensé que en la subclase que sería capaz de simplemente agregar el elemento utilizando:

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

O

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

Pero ese no es el caso. Recibo una excepción que dice que estoy tratando de agregar elemento (NULO).

La única manera en que puedo obtener el resultado deseado es asignar específicamente el elemento create a una variable miembro, y luego usar ese nombre de variable.

p. Ej. En forma de base:

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

Luego, en la clase substitución:

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

Me parece que esto debería producir un conflicto de nombres variables. Si createElement no nombra mi elemento 'id', ¿qué nombre le da?

EDITAR

estoy usando el init() de los padres y las clases hijas, e init del niño() llama a init parent() como su primera tarea.

Respuesta

3

createElement no agrega un elemento al formulario, simplemente lo crea. A menos que lo agregue a su formulario, el formulario no lo sabrá. Es por eso que $this->id y
$this->getElement('id') no funcionan en su primer ejemplo.

En el segundo ejemplo, primero agrega el elemento recién creado al formulario (es decir, $this->id = $this->createElement('text', 'id', array(...));) y luego parece que lo está agregando de nuevo (es decir, $this->addElement($this->id);). Creo que no habrá ningún conflicto de nombres, ya que Zend_Form simplemente lo reasignará. Por lo tanto, creo que $this->addElement($this->id); de hecho no es necesario.

Espero que esto ayude.

+0

Gracias Marcin, tenía razón, la segunda asignación no es necesaria. Cuando volví y miré mis subformularios desde el principio del día, también tenían los elementos opcionales. –

0

Suponiendo que está utilizando Zend_Form :: init() y no está llamando a parent :: init() en la clase secundaria, es posible que esté anulando el método de la clase principal. Lo que significa que ninguno de sus elementos base se agrega a la forma de subclase. Si agrega parent :: init() en el init() de la subclase, heredará los elementos principales del formulario de subclase. Luego, puede agregar y eliminar elementos según sea necesario para la subclase.

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

Gracias user828841. Estoy usando el init() como se recomienda. Debería haber señalado esto en mi pregunta original. He actualizado la pregunta ... –

+0

Si llama al padre :: init() no necesita usar $ this-> addElement ($ this-> getElement ('id')); $ this-> getElement ('id) implica que el elemento ya está agregado al formulario, por lo que no necesita la redundancia –

3

Todo está funcionando como se esperaba. No hay conflicto de nombres porque cuando usas $ this-> createElement(), el elemento que creas no se guarda en ningún lugar.Con este enfoque, debe mantener explícitamente el elemento en alguna variable (como una variable miembro) y luego agregarlo al conjunto de elementos de formulario usando $ this-> addElement().

Si se echa un vistazo al código fuente Zend_Form se puede observar que:

1- Cuando se llama a createElement(), se crea el elemento y regresó de inmediato; en otras palabras, el elemento no se mantiene internamente en cualquier lugar, por lo que debe mantener por sí mismo y agregarlo a la forma última:

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

2- Cuando se llama a addElement(), se añade entonces el elemento de la forma , e internamente mantenido en una matriz de miembros protegida llamada _elements. Esto es lo mismo que hacer:

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

que exige mágicamente addElement() (como se ha señalado por user594791 usuario en su comentario). También podría poner directamente el elemento en la matriz _elements, pero desaconsejo esto, porque addElement() realiza un procesamiento adicional. No hay conflictos de nombres porque está haciendo la misma acción dos veces (como señaló Marcin en la otra respuesta), y en la segunda vez está sobrescribiendo el elemento consigo mismo.

Finalmente, también desaconsejo crear instancias de elementos que no usará (pérdida de recursos y práctica de programación no muy buena). Es preferible mantener una matriz asociativa de configuraciones para elementos posiblemente necesarios en su clase principal; luego, en sus subclases, solo crea una instancia de los elementos que realmente necesita, utilizando las matrices de configuración respectivas que se pre-almacenaron en la clase principal. Un ejemplo:

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

Si tiene muchos elementos, y no desea contaminar el init parent() método mucho, sugiero colocar las definiciones completas de elementos en un archivo externo, que puede ser o bien un PHP archivo que devuelve una matriz de PHP con la configuración completa, un archivo XML, un archivo INI o cualquier otro formato compatible con Zend_Config (puede definir los elementos sin una parte del código PHP real - here -en la parte inferior de la página- es un ejemplo de definir un elemento con un archivo INI).

+0

Creo que la asignación a '$ this-> id' ejecutará el método __set que a su vez ejecutará el método addElement para agregar un elemento. – user594791

+0

Tiene toda la razón, corregiré mi respuesta. A veces me olvido de estas diabólicas hechicerías de PHP;) – faken

+0

Hola Faken, gracias por una excelente respuesta. Le concedí los puntos a Marcin, porque era más preciso, sin embargo, tu respuesta tiene información excelente, y sí, agradecería más detalles sobre tu método de configuración de elementos solo en la forma principal ... –