Zend Framework

Creating View Helpers – Zend Framework

Before, I have posted about creating a custom action helper. Now since I’m back for a ZF project, I’m posting how to create a view helper. My examples will be about rendering SELECT (dropdown menu) elements (without using Zend Form).

What About Zend Form

I really hate Zend Form. That is why I’m creating HTML elements on the view. They performs way faster than having a form object with validators, filters, decorations, etc that slows things down. If only Zend Framework has something like Sprig in Kohana v3, that would be nice. But since there is none, I’ll do my form thing my own.

On the other hand, If ever, I may create a port of Sprig for Zend Framework in the future, if time and eagerness is still up.

Creating View Helpers

What I want to create is to load SELECT elements loaded with stuff like TITLES, ex: Mr. Ms, or a day/month/year SELECT elements. (By the way, I’ll be going to post a jQuery stuff about that in the future). And with those helpers, it would be easy for me to render a SELECT element on my views. Here we go:

Put your helpers on application/views/helpers

Now let’s create our first helper. I want a view helper that will accept parameters to build a SELECT/dropdown HTML element, so that other helper may use them. So I’ll be calling them HtmlSelect. Create HtmlSelect.php on the view helpers directory.

The class is so simple, it just need to extend Zend_View_Helper_Abstract so that it can also call other helpers (if you are sure it does not need other helper, you can skip the extend part). My HtmlSelect class has a single method htmlSelect that accepts parameters such as name, values, selected, attributes and other stuff. Your strategy may differ but in our system, there are specs that I cannot break even though they are against web standards.

<?php

/**
 * Person title helper
 *
 */
class Zend_View_Helper_HtmlSelect extends Zend_View_Helper_Abstract
{	
	/**
	 * Returns an HTML string for a select element
	 * containing titles as options
	 *
	 * @param string $name
	 * @param array $values
	 * @param mixed $selected
	 * @param boolean $emptyFirst
	 * @param array $attributes
	 * @return string
	 */
	public function htmlSelect($name, $values = array(), $selected = null, $emptyFirst = true, $attributes = array())
	{		
		// load attributes	
		$attrOthers = '';
		foreach ($attributes as $att => $val)
		{
			$attrOthers .= ' ' .  $att . '="' . $val . '"';
		}
		$s = '<select name="' . $name . '"' . $attrOthers . '>';
		
		// load empty option if set
		if ($emptyFirst)
		{
			$s .= '<option></option>';
		}
		
		foreach ($values as $key => $val)
		{
			if ($selected == $val)
			{
				$s .= '<option value="' . $key . '" selected="selected">' . $val . '</option>';
			}
			else
			{
				$s .= '<option value="' . $key . '">' . $val . '</option>';
			}
		}
		$s .= '</select>';
		
		return $s;
	}
}

Anywhere in your ZF views, you can call this helper by $this->htmlSelect(). However, our class is still almost useless. So let’s create the actual helper. I need a helper that allows me to render TITLES such as Mr. and Mrs into a SELECT element. I’ll be calling the class PersonTitle. Add PersonTitle.php to the view helpers directory.

<?php

/**
 * Person title helper
 *
 */
class Zend_View_Helper_PersonTitle extends Zend_View_Helper_Abstract
{
	/**
	 * Titles
	 *
	 * @var array
	 */
	protected $_titles = array('Ms', 'Mr', 'Mrs');
	
	/**
	 * Returns an HTML string for a select elemtn
	 * containing titles as options
	 *
	 * @param string $name
	 * @param mixed $selected
	 * @param boolean $emptyFirst
	 * @param array $attributes
	 * @return string
	 */
	public function personTitle($name, $selected = null, $emptyFirst = true, $options = array())
	{
		$titles = array_combine($this->_titles, $this->_titles);
		return $this->view->htmlSelect($name, $this->_titles, $selected, $emptyFirst, $options);
	}
}


The personTitle helper is able to call another helper because it extends Zend_View_Helper_Abstract. To call a helper, one may write: $this->view->helperName(). To render the TITLES into your view, you may write like this:


<div class="sel-short">
	<?php echo $this->personTitle('title') ?>
</div>

In my project, I need more SELECT elements like day(1-31), months(Jan-Dec) and year to represent a date. Since that is the most keyboard friendly interface. So I’ll be calling them DaySelect.php, MonthSelect.php and YearSelect.php. As you’ve noticed, there is a parameter on htmlSelect that allows the SELECT to have the first option as empty option. It is invalid XHTML, however, our specs may need them (or shall we say, will always need them).

Code for DaySelect.php – it simply renders options 1-31 representing the day of the month.

<?php

/**
 * Person title helper
 *
 */
class Zend_View_Helper_DaySelect extends Zend_View_Helper_Abstract
{	
	/**
	 * Returns an HTML string for a select elemtn
	 * containing titles as options
	 *
	 * @param string $name
	 * @param mixed $selected
	 * @param boolean $emptyFirst
	 * @param array $attributes
	 * @return string
	 */
	public function daySelect($name, $selected = null, $emptyFirst = true, $attributes = array())
	{
		$days = array_combine(range(1, 31), range(1, 31));
		return $this->view->htmlSelect($name, $days, $selected, $emptyFirst, $attributes);
	}
}

Code for MonthSelect.php – it renders the months Jan-Dec as options.

<?php

/**
 * Person title helper
 *
 */
class Zend_View_Helper_MonthSelect extends Zend_View_Helper_Abstract
{
	/**
	 * Titles
	 *
	 * @var array
	 */
	protected $_months = array(
		1 => 'January',
		2 => 'February',
		3 => 'March',
		4 => 'April',
		5 => 'May',
		6 => 'June',
		7 => 'July',
		8 => 'August',
		9 => 'September',
		10 => 'October',
		11 => 'November',
		12 => 'December'
	);
	
	/**
	 * Returns an HTML string for a select elemtn
	 * containing titles as options
	 *
	 * @param string $name
	 * @param mixed $selected
	 * @param boolean $emptyFirst
	 * @param array $attributes
	 * @return string
	 */
	public function monthSelect($name, $selected = null, $emptyFirst = true, $attributes = array())
	{
		return $this->view->htmlSelect($name, $this->_months, $selected, $emptyFirst, $attributes);
	}
}

And finally the code for YearSelect.php – renders the current year down to 100 years before the current. This is used to represent birth date as a whole.

<?php

/**
 * Person title helper
 *
 */
class Zend_View_Helper_YearSelect extends Zend_View_Helper_Abstract
{	
	/**
	 * Returns an HTML string for a select elemtn
	 * containing titles as options
	 *
	 * @param string $name
	 * @param mixed $selected
	 * @param boolean $emptyFirst
	 * @param array $attributes
	 * @return string
	 */
	public function yearSelect($name, $selected = null, $emptyFirst = true, $attributes = array())
	{
		$years = array_reverse(range(date('Y') - 100, date('Y')));		
		$years = array_combine($years, $years);
		
		return $this->view->htmlSelect($name, $years, $selected, $emptyFirst, $attributes);
	}
}

Those three helpers will be called this way:

  1. $this->daySelect()
  2. $this->MonthSelect()
  3. $this->YearSelect()

So this is how our view file will look like:

<div class="rh-block">
	<div class="lbl">
		<span>Name</span>
	</div>
	<div class="field">
		<div class="sel-short">
			<?php echo $this->personTitle('title') ?>
		</div>
		<div class="txt-reg">
			<input type="text" name="fist_name" />
		</div>
		<div class="txt-reg">
			<input type="text" name="middle_name" />
		</div>
		<div class="txt-reg">
			<input type="text" name="last_name" />
		</div>
		<div class="search-btn">
			<input type="button" class="btn" name="search_btn" value="Search" />
		</div>
	</div><!-- field -->
</div><!-- rh-block Name -->

<div class="rh-block">
	<div class="lbl">
		<span>Birth Date</span>
	</div>
	<div class="field">
		<div class="sel-short">
			<?php echo $this->daySelect('birthdate_day', null, true, array('class' => 'sync-day-options-day')) ?>
		</div>
		<div class="sel-short">
			<?php echo $this->monthSelect('birthdate_month', null, true, array('class' => 'sync-day-options-month')) ?>
		</div>
		<div class="sel-short">
			<?php echo $this->yearSelect('birthdate_year', null, true, array('class' => 'sync-day-options-year')) ?>
		</div>
	</div><!-- field -->
</div><!-- rh-block Birthdate -->

And the screenshot just to be sure. You need to code your CSS though. These all Zend Framework code is using ZF 1.9.2 and up using autoloading (the standard ZF structure).

My Kohana posts are a bit delayed since most of my KO3 just works out of the way and there is no thrill / excitement that it does not give me motivation of writing posts about it. Zend Framework has always been so exciting.

Happy (view) helping!

4 thoughts on “Creating View Helpers – Zend Framework”

  1. Well, I can understand that you don’t want to use Zend_Forms but as Zend components tends to be loosly coupled why don’t you use the view helpers already there in Zend/View/Helper/Form* ?

  2. Hi Patrick,

    Thanks for your comment. Ummm… seems there a lot of reinventing the wheel going on there πŸ˜€

    I never thought of digging the Zend Form helpers. Thanks for reminding me of them. However, it seems that I only need to remove the htmlSelect part.

    Thanks again. Zend_View_Helper_FormSelect looks neat.

Leave a reply

Your email address will not be published. Required fields are marked *