Generate HTML drop downs from arrays & ranges with a PHP class

There comes a time (or a multitude of times) where a developer finds him- or herself rewriting the same code over and over again. Eventually, we get tired of it and need to find a solution. Recently, I frequently found myself writing code to generate HTML drop downs.  This became tedious, and I started to think it was unnecessary. But wait!  There must be a better way!  I didn’t want to use Zend_Form or any other 3rd party solution; I wanted to create my own class to help take care of this problem.  Below is the code/examples for the class, then a description of some of the methods, and lastly a link to download the source code.  As you can see, there are some nice features, and the class is easy to use and extend.

The Html_Dropdown Class

/**
 * Webjawns.com Html_Dropdown
 * 
 * @author Chris Strosser
 * @version 1.0 20091201
 * @desc Generate HTML drop down markup from arrays and numeric ranges on the fly.
 * @link http://webjawns.com/2009/12/generate-html-drop-downs-from-arrays-ranges-with-a-php-class
 */
class Html_Dropdown {
	/**
	 * The attributes for the <select> box
	 * 
	 * @var array
	 */
	private $_attribs = array();
	
	/**
	 * Whether or not to render <select> wrapper (defaults to true)
	 * 
	 * @var bool
	 */
	private $_renderSelect = true;
	
	/**
	 * Stores array of numbers or $key to $value pairs
	 * 
	 * @var array
	 */
	private $_array;
	
	/**
	 * Start value of range
	 * 
	 * @var int
	 */
	private $_rangeStart;
	
	/**
	 * End value of range
	 * 
	 * @var int
	 */
	private $_rangeEnd;
	
	/**
	 * Increment between elements in the range
	 * 
	 * @var int
	 */
	private $_rangeStep = 1;
	
	/**
	 * Default/selected value in dropdown
	 * 
	 * @var mixed
	 */
	private $_selected;
	
	/**
	 * Html_Dropdown Constructor
	 * 
	 * Can be used to set ID and name attributes for <select> element.
	 * 
	 * @param string $name Optional. Sets ID and name attributes for <select> element.
	 */
	public function __construct($name = '') {
		if (!empty($name))
			$this->setName($name);
	}
	
	/**
	 * Use numeric range to generate drop down values.
	 * 
	 * @param int $start The range start value
	 * @param int $end The range end value
	 * @param int $step Increment between elements in the range
	 * @return Html_Dropdown
	 */
	public function setRange($start, $end, $step = 1) {
		$this->reset();
		
		$this->_rangeStart = (int) $start;
		$this->_rangeEnd = (int) $end;
		$this->_rangeStep = (int) $step;
		return $this;
	}
	
	/**
	 * Use passed array to generate drop down values. 
	 * 
	 * @param array $array
	 * @return Html_Dropdown
	 */
	public function setArray(Array $array) {
		$this->reset();
		
		$this->_array = $array;
		return $this;
	}
	
	/**
	 * Set an attribute for the <select> element.
	 * 
	 * @param string $attribute
	 * @param string $value
	 * @return Html_Dropdown
	 */
	public function setAttrib($attribute, $value) {
		$attribute = $this->_cleanHtml($attribute);
		$this->_attribs[$attribute] = htmlspecialchars($value, ENT_QUOTES);
		return $this;
	}
	
	/**
	 * Set the name and ID of the <select> wrapper.
	 * 
	 * @param string $name The ID/name of the select element.
	 * @return Html_Dropdown
	 */
	public function setName($name) {
		$name = $this->_cleanHtml($name);
		$this->_attribs['id'] = $name;
		$this->_attribs['name'] = $name;
		return $this;
	}
	
	/**
	 * Set the default selected value for the dropdown.
	 * 
	 * @param mixed $value
	 * @return Html_Dropdown
	 */
	public function setDefaultValue($value) {
		$this->_selected = $value;
		return $this;
	}
	
	/**
	 * Alias of setDefaultValue()
	 * 
	 * @see setDefaultValue()
	 */
	public function selected($value) {
		return $this->setDefaultValue($value);
	}
	
	/**
	 * Toggle <select> rendering. If disabled, <option> elements will be 
	 * displayed without a <select> element wrapper.
	 * 
	 * @param bool $render Whether or not to render the select element.
	 * @return Html_Dropdown
	 */
	public function setRenderSelect($render) {
		$this->_renderSelect = ($render === true);
		return $this;
	}
	
	/**
	 * Reset the loop values back to null.
	 * 
	 * @return Html_Dropdown
	 */
	public function reset() {
		$this->_array = null;
		$this->_rangeStart = null;
		$this->_rangeEnd = null;
		$this->_rangeStep = 1;
		return $this;
	}
	
	/**
	 * Resets attributes back to empty array.
	 * 
	 * @return Html_Dropdown
	 */
	public function resetAttribs() {
		$this->_attribs = array();
		return $this;
	}
	
	/**
	 * Render dropdown HTML to browser.
	 * 
	 * @return bool True if successful, false otherwise.
	 */
	public function render() {
		if (!$this->_ready())
			return false;
		
		// Check if there is an array defined
		if (is_array($this->_array)) {
			$options = $this->_loopArray($this->_array);
			return $this->_render($options);
		}
		
		// Check if there is a range defined
		if (isset($this->_rangeStart) && isset($this->_rangeEnd)) {
			$options = $this->_loopRange($this->_rangeStart, $this->_rangeEnd, $this->_rangeStep);
			return $this->_render($options);
		}
		
		return false;
	}
	
	/**
	 * Helper function for render(). Wraps options in <select> and applies attributes.
	 * 
	 * @param string $options
	 * @return void
	 */
	private function _render($options) {
		if (!$this->_renderSelect) {
			echo $options;
			return true;
		}
		
		// Render select element without attributes
		if (count($this->_attribs) == 0) {
			echo "n<select name='webjawns_dropdown' id='webjawns_dropdown'>";
			echo $options . "n</select>";
			return true;
		}
		
		$select = "n<select";
		foreach ($this->_attribs as $attr => $value) {
			$attr = preg_replace("/[^0-9a-z_-]/i", '', $attr);
			$value = htmlspecialchars($value, ENT_QUOTES);
			$select .= " {$attr}="{$value}"";
		}
		
		// Render select element with attributes
		echo "n{$select}>{$options}n</select>n";
		
		return true;
	}
	
	/**
	 * Create <option> elements for a numeric range.
	 * 
	 * @param int $start The start value
	 * @param int $end The end value
	 * @param int $step Increment between elements in sequence. Defaults to 1.
	 * @return string HTML for all options
	 */
	private function _loopRange($start, $end, $step = 1) {
		if (null === $start || null === $end)
			return false;
		
		// Initialize variabless
		$default = '';
		$others = '';
		
		foreach (range($start, $end, $step) as $value) {
			if ($this->_selected == $value)
				$default = "nt<option value='{$value}' selected='selected'>{$value}</option>";
			else
				$others .= "nt<option value='{$value}'>{$value}</option>";
		}
		
		return $default . $others;
	}
	
	/**
	 * Create <option> elements for array. Must be array key to value.
	 * 
	 * @param array $data Array of data
	 * @return string HTML for all options
	 */
	private function _loopArray(Array $data) {
		if (null === $this->_array)
			return false;
		
		// Initialize variables
		$default = '';
		$others = '';
		
		foreach ($data as $key => $value) {
			if ($this->_selected == $value)
				$default = "nt<option value='{$key}' selected='selected'>{$value}</option>";
			else
				$others .= "nt<option value='{$key}'>{$value}</option>";
		}
		
		return $default . $others;
	}
	
	/**
	 * Check if there is a range or array defined.
	 * 
	 * @return bool True if we have variables to process, false otherwise.
	 */
	private function _ready() {
		if (null === $this->_array) {
			if (null === $this->_rangeStart || null === $this->_rangeEnd) {
				return false;
			}
		}
		return true;
	}
	
	/**
	 * Clean a string for use as an HTML attribute.
	 * 
	 * @param string $value
	 * @return The cleaned string
	 */
	private function _cleanHtml($value) {
		$value = preg_replace("/[^a-z0-9_-]/i", '', $value);
		return $value;
	}
}

Example Usage

<p>
<?php

$dd = new Html_Dropdown('selectBoxTest');
$dd->setRange(1986, date('Y'))
   ->selected(1999)
   ->render();

?>
<select name="noRenderSelect">
<?php
$dd = new Html_Dropdown();
$dd->setArray(array('1' => 'Approved', '2' => 'Pending', '3' => 'Not Approved'))
   ->setAttrib('disabled', 'disabled')
   ->setRenderSelect(false)
   ->render();

?>
</select>
</p>

The Results

1999
1986
1987
1988
1989

1990
1991
1992
1993
1994
1995

1996
1997
1998
2000
2001
2002

2003
2004
2005
2006
2007
2008

2009

Approved
Pending
Not Approved

Html_Dropdown Class Synopsis

Html_Dropdown::setRange(int $start, int $end, int $step) – Used to create dropdown from numeric range (Ex. 2008-2010, 1-12, etc.)
Html_Dropdown::setArray(Array $array) – Used to create dropdown from array (must be $key => $value to work properly)
Html_Dropdown::setAttrib(string $attribute, mixed $value) – Used to set <select> element attributes
Html_Dropdown::setName(string $name) – Used to set ID and name of <select> element
Html_Dropdown::setDefaultValue(int|string $value) – Used to set a default selected value
Html_Dropdown::selected(int|string $value) – Alias of setDefaultValue()
Html_Dropdown::setRenderSelect(bool $render) – Whether or not to render a <select> element wrapper or only <option> elements
Html_Dropdown::reset() – Used to reset the array and range values back to their default values
Html_Dropdown::resetAttribs() – Used to clear all attributes
Html_Dropdown::render() – Display drop down HTML on screen

Download Html_Dropdown Source Code

One thought on “Generate HTML drop downs from arrays & ranges with a PHP class”

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>