Adding Custom Variables to Zend Framework Forms

Published on July 25, 2012 by

It is often necessary to add data to form elements from outside of the form. For instance, it is common to fetch data from a database and to show this data in the form, such as in a select element. There are, as always, many ways of accomplishing this, but some are more elegant than others. In other situations you may need access to data stored in a session within your form. Perhaps you only need to show certain form elements if a session value is set to true. While accessing sessions within form classes works, it is not elegant and harder to maintain because logic is moved from the controller and into the form. There are many examples of when adding data to forms from controllers is handy, but in this article we will focus our attention on adding an array that was imaginably fetched from a data store to the form.

First, let us consider how many developers tend to do this.

class UserController extends Zend_Controller_Action {
    public function registerAction() {
	// The array to add to a Zend_Form_Element_Select element. Could be fetched from a database.
	$languages = array(
		0 => 'PHP',
		1 => 'Java',
		2 => 'Python',
		3 => 'C#'
	);

    	$form = new Default_Form_Register(); // The select element is created and added to the form in the init() method
    	
    	// "sltLanguages" is the name of the element
    	$form->sltLanguages->addMultiOptions($languages);
    }
}

Imagine having to do this with several elements. While the code required is minimal, it is definitely worth considering if you want to have this in your controller. While it is surely a subjective thing, most will probably agree that it is more logical to populate and manipulate elements from within the form class where the rest of the manipulation happens. That is, to keep it all centered at the same place. Let us see how we can accomplish just that.

What if we could use the constructor of our form to feed data to it? Then we could do what we previously did in the controller from within the form class. It might be tempting to just override the constructor, but that is not necessary and not recommended. If we look at the Zend_Form class’ constructor, it takes an optional options array. This allows us to specify several options, including our own variables. Let us take a moment to take a look at the source code of Zend_Form‘s constructor.

public function __construct($options = null) 
{ 
      if (is_array($options)) { 
          $this->setOptions($options); 
      } elseif ($options instanceof Zend_Config) { 
          $this->setConfig($options); 
      } 
 
      // Extensions... 
      $this->init(); 
 
      $this->loadDefaultDecorators(); 
}

In the code above, we can see that the options we pass are first set and afterwards, the init() method is run. Therefore, we can conclude that we can reference variables passed to the constructor from within the init() method of our form class, which is exactly what we wanted.

First, we pass our variables as key-value pairs to the constructor when initializing the form like below.

class UserController extends Zend_Controller_Action {
    public function registerAction() {
	$languages = array(
		0 => 'PHP',
		1 => 'Java',
		2 => 'Python',
		3 => 'C#'
	);

    	$form = new Default_Form_Register(array(
    		'languages' => $languages,
    		'anotherVariable' => 'theValue'
    	));
    }
}

There are a few more things to do before we are done, but let us first take a look at the setOptions()‘s source code.

public function setOptions(array $options) 
{
	// Some code omitted
	
	$forbidden = array( 
		'Options', 'Config', 'PluginLoader', 'SubForms', 'View', 'Translator', 'Attrib', 'Default', 
	);
	
	foreach ($options as $key => $value) {
		$normalized = ucfirst($key);
		
		if (in_array($normalized, $forbidden)) {
			continue;
		}

		$method = 'set' . $normalized;
		
		if (method_exists($this, $method)) { 
			$this->$method($value); 
		} else { 
			$this->setAttrib($key, $value); 
		}
	}
	
	// Some code omitted	
}

We can see that the options are looped through. First it assures that the option name is not one of the forbidden ones (if so, it is skipped). A method name is then constructed based on the string “set” and the option/variable name with an uppercase first letter. For example, if the option/variable name is “languages”, then the method name will be “setLanguages”. This method is then executed if it exists. Therefore, we have to create such a method. Open your form class and add the following:

// A variable name of "languages" is assumed. The parameter name is not important.
public function setLanguages($languages) {
	$this->_languages = $languages;
}

Above we are referencing a class member/attribute that we have not yet created. At the top of your form class, add the variable as shown below.

class Default_Form_Register extends Zend_Form {
	private $_languages;
}

The underscore in the variable name is simply a naming convention and has no deeper meaning. All we have to do now is to make use of our variable.

class Default_Form_Register extends Zend_Form {
	private $_languages;

	public function init() {
		$languages = new Zend_Form_Element_Select('sltLanguages');
		$languages->setMultiOptions($this->_languages);
			
		$this->addElement($languages); // Add element to form
	}
}

Congratulations, you now have a more focused controller and form class while improving maintainability.

Featured

Learn Zend Framework today!

Take an online course and become a ZF2 ninja!

Here is what you will learn:

  • Understand the theory of Zend Framework in details
  • How to implement an enterprise-ready architecture
  • Develop professional applications in Zend Framework
  • Proficiently work with databases in Zend Framework
  • ... and much more!
Zend Framework logo
Author avatar
Bo Andersen

About the Author

I am a back-end web developer with a passion for open source technologies. I have been a PHP developer for many years, and also have experience with Java and Spring Framework. I currently work full time as a lead developer. Apart from that, I also spend time on making online courses, so be sure to check those out!

One comment on »Adding Custom Variables to Zend Framework Forms«

  1. Tomas

    This is a great article. Well done.

Leave a Reply

Your e-mail address will not be published.