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 = "\n\t<option value='{$value}' selected='selected'>{$value}</option>";
			else
				$others .= "\n\t<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 = "\n\t<option value='{$key}' selected='selected'>{$value}</option>";
			else
				$others .= "\n\t<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

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

  • Share/Bookmark