{"id":749,"date":"2011-07-28T15:40:13","date_gmt":"2011-07-28T21:40:13","guid":{"rendered":"http:\/\/www.curtisgibby.com\/blog\/?p=749"},"modified":"2016-05-11T06:38:32","modified_gmt":"2016-05-11T12:38:32","slug":"html5-form-inputs-in-cakephp-1-2","status":"publish","type":"post","link":"https:\/\/www.curtisgibby.com\/blog\/2011\/07\/html5-form-inputs-in-cakephp-1-2\/","title":{"rendered":"HTML5 form inputs in CakePHP 1.2"},"content":{"rendered":"<p>At work, we&#8217;re building out a mobile version of our replicated sites.\u00a0 As anyone who&#8217;s used an iPhone or Android browser to fill out a web form knows&#8230; using an iPhone or Android browser to fill out a web form is really annoying, and it&#8217;s best to make things as user-friendly as possible.\u00a0 That&#8217;s why I wanted to leverage the power of <a href=\"http:\/\/diveintohtml5.org\/forms.html\" target=\"_blank\">HTML5 form elements<\/a> to minimize that annoyance.<\/p>\n<p><!--more--><\/p>\n<p>On the iPhone, Mobile Safari renders its on-screen keyboard differently for &#8220;email,&#8221; &#8220;tel&#8221; and &#8220;url&#8221; form fields &#8212; you automatically get the keys that make the most sense for each specific situation.<\/p>\n<figure id=\"attachment_753\" aria-describedby=\"caption-attachment-753\" style=\"width: 320px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.curtisgibby.com\/blog\/wp-content\/uploads\/2011\/07\/iphone-email1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-753\" title=\"iphone email\" src=\"http:\/\/www.curtisgibby.com\/blog\/wp-content\/uploads\/2011\/07\/iphone-email1.png\" alt=\"HTML5 email form input rendered on an iPhone\" width=\"320\" height=\"480\" srcset=\"https:\/\/www.curtisgibby.com\/blog\/wp-content\/uploads\/2011\/07\/iphone-email1.png 320w, https:\/\/www.curtisgibby.com\/blog\/wp-content\/uploads\/2011\/07\/iphone-email1-200x300.png 200w\" sizes=\"auto, (max-width: 320px) 100vw, 320px\" \/><\/a><figcaption id=\"caption-attachment-753\" class=\"wp-caption-text\">HTML5 email form input rendered on an iPhone<\/figcaption><\/figure>\n<figure id=\"attachment_751\" aria-describedby=\"caption-attachment-751\" style=\"width: 320px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.curtisgibby.com\/blog\/wp-content\/uploads\/2011\/07\/iphone-tel.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-751\" title=\"iphone tel\" src=\"http:\/\/www.curtisgibby.com\/blog\/wp-content\/uploads\/2011\/07\/iphone-tel.png\" alt=\"HTML5 tel form input rendered on an iPhone\" width=\"320\" height=\"480\" srcset=\"https:\/\/www.curtisgibby.com\/blog\/wp-content\/uploads\/2011\/07\/iphone-tel.png 320w, https:\/\/www.curtisgibby.com\/blog\/wp-content\/uploads\/2011\/07\/iphone-tel-200x300.png 200w\" sizes=\"auto, (max-width: 320px) 100vw, 320px\" \/><\/a><figcaption id=\"caption-attachment-751\" class=\"wp-caption-text\">HTML5 tel form input rendered on an iPhone<\/figcaption><\/figure>\n<figure id=\"attachment_752\" aria-describedby=\"caption-attachment-752\" style=\"width: 320px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.curtisgibby.com\/blog\/wp-content\/uploads\/2011\/07\/iphone-url.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-752\" title=\"iphone url\" src=\"http:\/\/www.curtisgibby.com\/blog\/wp-content\/uploads\/2011\/07\/iphone-url.png\" alt=\"HTML5 url form input rendered on an iPhone\" width=\"320\" height=\"480\" srcset=\"https:\/\/www.curtisgibby.com\/blog\/wp-content\/uploads\/2011\/07\/iphone-url.png 320w, https:\/\/www.curtisgibby.com\/blog\/wp-content\/uploads\/2011\/07\/iphone-url-200x300.png 200w\" sizes=\"auto, (max-width: 320px) 100vw, 320px\" \/><\/a><figcaption id=\"caption-attachment-752\" class=\"wp-caption-text\">HTML5 url form input rendered on an iPhone<\/figcaption><\/figure>\n<p>However, the version of CakePHP that we&#8217;re running our replicated sites on (1.2.5) doesn&#8217;t have support for these awesome HTML5 inputs &#8212; any unknown input type is automatically rendered as a textarea.\u00a0 (What kind of weird default is that?)<\/p>\n<p>The HTML5 inputs <a href=\"http:\/\/cakephp.lighthouseapp.com\/projects\/42648\/tickets\/598-support-for-html5-input-types-in-formhelper\" target=\"_blank\"><em>are<\/em> supported<\/a> in CakePHP 2.0 (currently in beta), but we&#8217;re stuck with 1.2.5 for the time being.\u00a0 <a href=\"http:\/\/lennaert.nu\/2010\/12\/04\/html5-form-elements-in-cakephp-formhelper\" target=\"_blank\">Lennaert Ekelmans back-ported that support<\/a> to 1.3.6, but his solution didn&#8217;t work for me out of the box either &#8212; apparently there were a couple of changes in the Form helper between 1.2.5 and 1.3.6.\u00a0 So I back-back-ported his code to work with 1.2.5.\u00a0 Here it is:<\/p>\n<pre class=\"brush:php\">\u00a0&lt;?php \r\n# app\/views\/helpers\/html5_form.php\r\nApp::import('Helper', 'Form');\r\nclass Html5FormHelper extends FormHelper {\r\n\u00a0\u00a0 \u00a0\/**\r\n\u00a0\u00a0 \u00a0 * Generates a form input element complete with label and wrapper div\r\n\u00a0\u00a0 \u00a0 *\r\n\u00a0\u00a0 \u00a0 * Options - See each field type method for more information. Any options that are part of \r\n\u00a0\u00a0 \u00a0 * $attributes or $options for the different type methods can be included in $options for input().\r\n\u00a0\u00a0 \u00a0 *\r\n\u00a0\u00a0 \u00a0 * - 'type' - Force the type of widget you want. e.g. ```type =&gt; 'select'```\r\n\u00a0\u00a0 \u00a0 * - 'label' - control the label\r\n\u00a0\u00a0 \u00a0 * - 'div' - control the wrapping div element\r\n\u00a0\u00a0 \u00a0 * - 'options' - for widgets that take options e.g. radio, select\r\n\u00a0\u00a0 \u00a0 * - 'error' - control the error message that is produced\r\n\u00a0\u00a0 \u00a0 *\r\n\u00a0\u00a0 \u00a0 * @param string $fieldName This should be \"Modelname.fieldname\"\r\n\u00a0\u00a0 \u00a0 * @param array $options Each type of input takes different options.\r\n\u00a0\u00a0 \u00a0 * @return string Completed form widget\r\n\u00a0\u00a0 \u00a0 *\r\n\u00a0\u00a0 \u00a0 * different from regular form helper only in the textarea\/default case -- adds support for HTML5 form types and attributes like placeholder\r\n\u00a0\u00a0 \u00a0 *\r\n\u00a0\u00a0 \u00a0 *\/\r\n\u00a0\u00a0 \u00a0function input($fieldName, $options = array()) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$view =&amp; ClassRegistry::getObject('view');\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$this-&gt;setEntity($fieldName);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$entity = join('.', $view-&gt;entity());\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$defaults = array('before' =&gt; null, 'between' =&gt; null, 'after' =&gt; null);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$options = array_merge($defaults, $options);\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (!isset($options['type'])) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$options['type'] = 'text';\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (isset($options['options'])) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$options['type'] = 'select';\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0} elseif (in_array($this-&gt;field(), array('psword', 'passwd', 'password'))) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$options['type'] = 'password';\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0} elseif (isset($this-&gt;fieldset['fields'][$entity])) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$fieldDef = $this-&gt;fieldset['fields'][$entity];\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$type = $fieldDef['type'];\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$primaryKey = $this-&gt;fieldset['key'];\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0} elseif (ClassRegistry::isKeySet($this-&gt;model())) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$model =&amp; ClassRegistry::getObject($this-&gt;model());\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$type = $model-&gt;getColumnType($this-&gt;field());\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$fieldDef = $model-&gt;schema();\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (isset($fieldDef[$this-&gt;field()])) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$fieldDef = $fieldDef[$this-&gt;field()];\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0} else {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$fieldDef = array();\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$primaryKey = $model-&gt;primaryKey;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (isset($type)) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$map = array(\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0'string'\u00a0 =&gt; 'text',\u00a0\u00a0\u00a0\u00a0 'datetime'\u00a0 =&gt; 'datetime',\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0'boolean' =&gt; 'checkbox', 'timestamp' =&gt; 'datetime',\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0'text'\u00a0\u00a0\u00a0 =&gt; 'textarea', 'time'\u00a0\u00a0\u00a0\u00a0\u00a0 =&gt; 'time',\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0'date'\u00a0\u00a0\u00a0 =&gt; 'date',\u00a0\u00a0\u00a0\u00a0 'float'\u00a0\u00a0\u00a0\u00a0 =&gt; 'text'\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0);\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (isset($this-&gt;map[$type])) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$options['type'] = $this-&gt;map[$type];\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0} elseif (isset($map[$type])) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$options['type'] = $map[$type];\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if ($this-&gt;field() == $primaryKey) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$options['type'] = 'hidden';\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if ($this-&gt;model() === $this-&gt;field()) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$options['type'] = 'select';\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (!isset($options['multiple'])) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$options['multiple'] = 'multiple';\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$types = array('text', 'checkbox', 'radio', 'select');\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (!isset($options['options']) &amp;&amp; in_array($options['type'], $types)) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$view =&amp; ClassRegistry::getObject('view');\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$varName = Inflector::variable(\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0Inflector::pluralize(preg_replace('\/_id$\/', '', $this-&gt;field()))\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$varOptions = $view-&gt;getVar($varName);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (is_array($varOptions)) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if ($options['type'] !== 'radio') {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$options['type'] = 'select';\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$options['options'] = $varOptions;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$autoLength = (!array_key_exists('maxlength', $options) &amp;&amp; isset($fieldDef['length']));\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if ($autoLength &amp;&amp; $options['type'] == 'text') {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$options['maxlength'] = $fieldDef['length'];\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if ($autoLength &amp;&amp; $fieldDef['type'] == 'float') {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$options['maxlength'] = array_sum(explode(',', $fieldDef['length']))+1;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$out = '';\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$div = true;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$divOptions = array();\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (array_key_exists('div', $options)) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$div = $options['div'];\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0unset($options['div']);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (!empty($div)) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$divOptions['class'] = 'input';\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$divOptions = $this-&gt;addClass($divOptions, $options['type']);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (is_string($div)) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$divOptions['class'] = $div;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0} elseif (is_array($div)) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$divOptions = array_merge($divOptions, $div);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (in_array($this-&gt;field(), $this-&gt;fieldset['validates'])) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$divOptions = $this-&gt;addClass($divOptions, 'required');\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (!isset($divOptions['tag'])) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$divOptions['tag'] = 'div';\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$label = null;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (isset($options['label']) &amp;&amp; $options['type'] !== 'radio') {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$label = $options['label'];\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0unset($options['label']);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if ($options['type'] === 'radio') {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$label = false;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (isset($options['options'])) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (is_array($options['options'])) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$radioOptions = $options['options'];\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0} else {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$radioOptions = array($options['options']);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0unset($options['options']);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if ($label !== false) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$labelAttributes = $this-&gt;domId(array(), 'for');\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (in_array($options['type'], array('date', 'datetime'))) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$labelAttributes['for'] .= 'Month';\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0} else if ($options['type'] === 'time') {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$labelAttributes['for'] .= 'Hour';\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (is_array($label)) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$labelText = null;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (isset($label['text'])) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$labelText = $label['text'];\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0unset($label['text']);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$labelAttributes = array_merge($labelAttributes, $label);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0} else {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$labelText = $label;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (isset($options['id'])) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$labelAttributes = array_merge($labelAttributes, array('for' =&gt; $options['id']));\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$out = $this-&gt;label($fieldName, $labelText, $labelAttributes);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$error = null;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (isset($options['error'])) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$error = $options['error'];\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0unset($options['error']);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$selected = null;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (array_key_exists('selected', $options)) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$selected = $options['selected'];\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0unset($options['selected']);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (isset($options['rows']) || isset($options['cols'])) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$options['type'] = 'textarea';\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$empty = false;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (isset($options['empty'])) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$empty = $options['empty'];\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0unset($options['empty']);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$timeFormat = 12;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (isset($options['timeFormat'])) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$timeFormat = $options['timeFormat'];\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0unset($options['timeFormat']);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$dateFormat = 'MDY';\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (isset($options['dateFormat'])) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$dateFormat = $options['dateFormat'];\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0unset($options['dateFormat']);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$type\u00a0\u00a0 \u00a0 = $options['type'];\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$before\u00a0\u00a0 \u00a0 = $options['before'];\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$between = $options['between'];\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$after\u00a0\u00a0 \u00a0 = $options['after'];\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0unset($options['type'], $options['before'], $options['between'], $options['after']);\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0switch ($type) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0case 'hidden':\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$out = $this-&gt;hidden($fieldName, $options);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0unset($divOptions);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0break;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0case 'checkbox':\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$out = $before . $this-&gt;checkbox($fieldName, $options) . $between . $out;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0break;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0case 'radio':\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$out = $before . $out . $this-&gt;radio($fieldName, $radioOptions, $options) . $between;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0break;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0case 'text':\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0case 'password':\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$out = $before . $out . $between . $this-&gt;{$type}($fieldName, $options);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0break;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0case 'file':\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$out = $before . $out . $between . $this-&gt;file($fieldName, $options);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0break;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0case 'select':\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$options = array_merge(array('options' =&gt; array()), $options);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$list = $options['options'];\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0unset($options['options']);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$out = $before . $out . $between . $this-&gt;select(\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$fieldName, $list, $selected, $options, $empty\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0break;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0case 'time':\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$out = $before . $out . $between . $this-&gt;dateTime(\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$fieldName, null, $timeFormat, $selected, $options, $empty\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0break;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0case 'date':\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$out = $before . $out . $between . $this-&gt;dateTime(\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$fieldName, $dateFormat, null, $selected, $options, $empty\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0break;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0case 'datetime':\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$out = $before . $out . $between . $this-&gt;dateTime(\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$fieldName, $dateFormat, $timeFormat, $selected, $options, $empty\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0break;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0case 'textarea':\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$out = $before . $out . $between . $this-&gt;textarea($fieldName, $options + array('cols' =&gt; 30, 'rows' =&gt; 6));\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0break;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0default:\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$out = $before . $out . $between . $this-&gt;defaultInput($type, $fieldName, $options);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0break;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if ($type != 'hidden') {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$out .= $after;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if ($error !== false) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$errMsg = $this-&gt;error($fieldName, $error);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if ($errMsg) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$out .= $errMsg;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$divOptions = $this-&gt;addClass($divOptions, 'error');\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (isset($divOptions) &amp;&amp; isset($divOptions['tag'])) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$tag = $divOptions['tag'];\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0unset($divOptions['tag']);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$out = $this-&gt;Html-&gt;tag($tag, $out, $divOptions);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0return $out;\r\n\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0\/**\r\n\u00a0\u00a0 \u00a0* Creates a default input widget, whose type is determined by $options['type'].\r\n\u00a0\u00a0 \u00a0*\r\n\u00a0\u00a0 \u00a0* @param string $fieldName Name of a field, in the form \"Modelname.fieldname\"\r\n\u00a0\u00a0 \u00a0* @param array $options Array of HTML attributes.\r\n\u00a0\u00a0 \u00a0* @return string A generated HTML input element\r\n\u00a0\u00a0 \u00a0* @access public\r\n\u00a0\u00a0 \u00a0*\/\r\n\u00a0\u00a0 \u00a0function defaultInput($type, $fieldName, $options = array()) {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$options = $this-&gt;_initInputField($fieldName, array_merge(\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0array('type' =&gt; $type), $options\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0));\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0return sprintf(\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$this-&gt;Html-&gt;tags['input'],\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$options['name'],\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0$this-&gt;_parseAttributes($options, array('name'), null, ' ')\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0);\r\n\u00a0\u00a0 \u00a0}\r\n}\u00a0\u00a0 \u00a0\r\n?&gt;<\/pre>\n<p>Unlike Lennaert, I chose to extend the regular form helper by creating my own helper class instead of adding the necessary code to Cake&#8217;s own form helper. Now I can get good HTML5 form inputs by adding the Html5Form helper to my controller and then calling the following code in my view:<\/p>\n<pre class=\"brush:php\">echo $html5Form-&gt;input('email',\r\n\u00a0\u00a0 \u00a0array(\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0'autofocus' =&gt; 'autofocus',\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0'placeholder' =&gt; 'email@example.com',\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0'type' =&gt; 'email',\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0'label' =&gt; __('Email address', true),\r\n        'required' =&gt; 'required',\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0'div' =&gt; 'required'\r\n\u00a0\u00a0 \u00a0)\r\n);\r\necho $html5Form-&gt;input('phone',\r\n\u00a0\u00a0 \u00a0array(\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0'placeholder' =&gt; '801-867-5309',\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0'type' =&gt; 'tel',\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0'label' =&gt; __('Phone', true),\r\n        'required' =&gt; 'required',\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0'div' =&gt; 'required'\r\n\u00a0\u00a0 \u00a0)\r\n);\r\necho $html5Form-&gt;input('phone',\r\n\u00a0\u00a0 \u00a0array(\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0'placeholder' =&gt; 'http:\/\/www.curtisgibby.com',\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0'type' =&gt; 'url',\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0'label' =&gt; __('Web site', true),\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0'required' =&gt; 'required',\r\n        'div' =&gt; 'required'\r\n\u00a0\u00a0 \u00a0)\r\n);<\/pre>\n<p>That results in the following HTML:<\/p>\n<pre class=\"brush:html\">&lt;div&gt;\r\n\u00a0\u00a0 \u00a0&lt;label for=\"ContactEmail\"&gt;Email address&lt;\/label&gt;\r\n\u00a0\u00a0 \u00a0&lt;input name=\"data[Contact][email]\" type=\"email\" autofocus=\"autofocus\" placeholder=\"email@example.com\" required=\"required\" value=\"\" id=\"ContactEmail\" \/&gt;\r\n&lt;\/div&gt;\r\n&lt;div&gt;\r\n\u00a0\u00a0 \u00a0&lt;label for=\"ContactPhone\"&gt;Phone&lt;\/label&gt;\r\n\u00a0\u00a0 \u00a0&lt;input name=\"data[Contact][phone]\" type=\"tel\" placeholder=\"801-867-5309\" required=\"required\" value=\"\" id=\"ContactPhone\" \/&gt;\r\n&lt;\/div&gt;\r\n&lt;div&gt;\r\n\u00a0\u00a0 \u00a0&lt;label for=\"ContactPhone\"&gt;Web site&lt;\/label&gt;\r\n\u00a0\u00a0 \u00a0&lt;input name=\"data[Contact][phone]\" type=\"url\" placeholder=\"http:\/\/www.curtisgibby.com\" required=\"required\" value=\"\" id=\"ContactPhone\" \/&gt;\r\n&lt;\/div&gt;<\/pre>\n<p>(There doesn&#8217;t seem to be an easy way to output HTML5&#8217;s standalone attributes as simply <em>autofocus<\/em> or <em>required<\/em> rather than the more verbose XHTML-ish <em>autofocus = &#8216;autofocus&#8217;<\/em> or <em>required = &#8216;true&#8217;<\/em> &#8212; without hacking the CakePHP base helper class. I&#8217;m okay with this slightly lengthier version for now though.)<\/p>\n<p>If you find this code useful, let me know in the comments.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>At work, we&#8217;re building out a mobile version of our replicated sites.\u00a0 As anyone who&#8217;s used an iPhone or Android browser to fill out a web form knows&#8230; using an iPhone or Android browser to fill out a web form is really annoying, and it&#8217;s best to make things as user-friendly as possible.\u00a0 That&#8217;s why&hellip; <a class=\"more-link\" href=\"https:\/\/www.curtisgibby.com\/blog\/2011\/07\/html5-form-inputs-in-cakephp-1-2\/\">Continue reading <span class=\"screen-reader-text\">HTML5 form inputs in CakePHP 1.2<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,17],"tags":[15,138,137,139,16],"class_list":["post-749","post","type-post","status-publish","format-standard","hentry","category-programming","category-work","tag-cakephp","tag-form-inputs","tag-html5","tag-mobile","tag-php","entry"],"_links":{"self":[{"href":"https:\/\/www.curtisgibby.com\/blog\/wp-json\/wp\/v2\/posts\/749","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.curtisgibby.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.curtisgibby.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.curtisgibby.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.curtisgibby.com\/blog\/wp-json\/wp\/v2\/comments?post=749"}],"version-history":[{"count":8,"href":"https:\/\/www.curtisgibby.com\/blog\/wp-json\/wp\/v2\/posts\/749\/revisions"}],"predecessor-version":[{"id":809,"href":"https:\/\/www.curtisgibby.com\/blog\/wp-json\/wp\/v2\/posts\/749\/revisions\/809"}],"wp:attachment":[{"href":"https:\/\/www.curtisgibby.com\/blog\/wp-json\/wp\/v2\/media?parent=749"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.curtisgibby.com\/blog\/wp-json\/wp\/v2\/categories?post=749"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.curtisgibby.com\/blog\/wp-json\/wp\/v2\/tags?post=749"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}