FormHelper
class
FormHelper(View $view, array $settings = array())
The FormHelper does most of the heavy lifting in form creation. The FormHelper focuses on creating forms quickly, in a way that will streamline validation, re-population and layout. The FormHelper is also flexible - it will do almost everything for you using conventions, or you can use specific methods to get only what you need.
Creating Forms
The first method you'll need to use in order to take advantage of the FormHelper is create()
. This special method outputs an opening form tag.
method
FormHelper::create(string $model = null, array $options = array())
Options for create()
There are a number of options for create():
$options['type']
This key is used to specify the type of form to be created. Valid values include 'post', 'get', 'file', 'put' and 'delete'.Supplying either 'post' or 'get' changes the form submission method accordingly:
phpecho $this->Form->create('User', array('type' => 'get'));
Output:
html<form id="UserAddForm" method="get" action="/users/add">
Specifying 'file' changes the form submission method to 'post', and includes an enctype of "multipart/form-data" on the form tag. This is to be used if there are any file elements inside the form. The absence of the proper enctype attribute will cause the file uploads not to function:
phpecho $this->Form->create('User', array('type' => 'file'));
Output:
html<form id="UserAddForm" enctype="multipart/form-data" method="post" action="/users/add">
When using 'put' or 'delete', your form will be functionally equivalent to a 'post' form, but when submitted, the HTTP request method will be overridden with 'PUT' or 'DELETE', respectively. This allows CakePHP to emulate proper REST support in web browsers.
$options['action']
The action key allows you to point the form to a specific action in your current controller. For example, if you'd like to point the form to the login() action of the current controller, you would supply an $options array like the following:phpecho $this->Form->create('User', array('action' => 'login'));
Output:
html<form id="UserLoginForm" method="post" action="/users/login">
Deprecated in version 2.8.0
The
$options['action']
option was deprecated as of 2.8.0. Use the$options['url']
and$options['id']
options instead.$options['url']
If the desired form action isn't in the current controller, you can specify a URL for the form action using the 'url' key of the $options array. The supplied URL can be relative to your CakePHP application:phpecho $this->Form->create(false, array( 'url' => array('controller' => 'recipes', 'action' => 'add'), 'id' => 'RecipesAdd' ));
Output:
html<form method="post" action="/recipes/add">
or can point to an external domain:
phpecho $this->Form->create(false, array( 'url' => 'https://www.google.com/search', 'type' => 'get' ));
Output:
html<form method="get" action="https://www.google.com/search">
Also check
HtmlHelper::url()
method for more examples of different types of URLs.Changed in version 2.8.0
Use
'url' => false
if you don’t want to output a URL as the form action.$options['default']
If 'default' has been set to boolean false, the form's submit action is changed so that pressing the submit button does not submit the form. If the form is meant to be submitted via AJAX, setting 'default' to false suppresses the form's default behavior so you can grab the data and submit it via AJAX instead.$options['inputDefaults']
You can declare a set of default options forinput()
with theinputDefaults
key to customize your default input creation:phpecho $this->Form->create('User', array( 'inputDefaults' => array( 'label' => false, 'div' => false ) ));
All inputs created from that point forward would inherit the options declared in inputDefaults. You can override the defaultOptions by declaring the option in the input() call:
phpecho $this->Form->input('password'); // No div, no label // has a label element echo $this->Form->input( 'username', array('label' => 'Username') );
Closing the Form
method
FormHelper::end($options = null, $secureAttributes = array())
Creating form elements
There are a few ways to create form inputs with the FormHelper. We'll start by looking at input()
. This method will automatically inspect the model field it has been supplied in order to create an appropriate input for that field. Internally input()
delegates to other methods in FormHelper.
method
FormHelper::input(string $fieldName, array $options = array())
method
FormHelper::inputs(mixed $fields = null, array $blacklist = null, $options = array())
Field naming conventions
The Form helper is pretty smart. Whenever you specify a field name with the form helper methods, it'll automatically use the current model name to build an input with a format like the following:
<input type="text" id="ModelnameFieldname" name="data[Modelname][fieldname]">
This allows you to omit the model name when generating inputs for the model that the form was created for. You can create inputs for associated models, or arbitrary models by passing in Modelname.fieldname as the first parameter:
echo $this->Form->input('Modelname.fieldname');
If you need to specify multiple fields using the same field name, thus creating an array that can be saved in one shot with saveAll(), use the following convention:
echo $this->Form->input('Modelname.0.fieldname');
echo $this->Form->input('Modelname.1.fieldname');
Output:
<input type="text" id="Modelname0Fieldname"
name="data[Modelname][0][fieldname]">
<input type="text" id="Modelname1Fieldname"
name="data[Modelname][1][fieldname]">
FormHelper uses several field-suffixes internally for datetime input creation. If you are using fields named year
, month
, day
, hour
, minute
, or meridian
and having issues getting the correct input, you can set the name
attribute to override the default behavior:
echo $this->Form->input('Model.year', array(
'type' => 'text',
'name' => 'data[Model][year]'
));
Options
FormHelper::input()
supports a large number of options. In addition to its own options input()
accepts options for the generated input types, as well as HTML attributes. The following will cover the options specific to FormHelper::input()
.
$options['type']
You can force the type of an input, overriding model introspection, by specifying a type. In addition to the field types found in the Automagic Form Elements, you can also create 'file', 'password', and any type supported by HTML5:phpecho $this->Form->input('field', array('type' => 'file')); echo $this->Form->input('email', array('type' => 'email'));
Output:
html<div class="input file"> <label for="UserField">Field</label> <input type="file" name="data[User][field]" value="" id="UserField" /> </div> <div class="input email"> <label for="UserEmail">Email</label> <input type="email" name="data[User][email]" value="" id="UserEmail" /> </div>
$options['div']
Use this option to set attributes of the input's containing div. Using a string value will set the div's class name. An array will set the div's attributes to those specified by the array's keys/values. Alternatively, you can set this key to false to disable the output of the div.Setting the class name:
phpecho $this->Form->input('User.name', array( 'div' => 'class_name' ));
Output:
html<div class="class_name"> <label for="UserName">Name</label> <input name="data[User][name]" type="text" value="" id="UserName" /> </div>
Setting multiple attributes:
phpecho $this->Form->input('User.name', array( 'div' => array( 'id' => 'mainDiv', 'title' => 'Div Title', 'style' => 'display:block' ) ));
Output:
html<div class="input text" id="mainDiv" title="Div Title" style="display:block"> <label for="UserName">Name</label> <input name="data[User][name]" type="text" value="" id="UserName" /> </div>
Disabling div output:
phpecho $this->Form->input('User.name', array('div' => false)); ?>
Output:
html<label for="UserName">Name</label> <input name="data[User][name]" type="text" value="" id="UserName" />
$options['label']
Set this key to the string you would like to be displayed within the label that usually accompanies the input:phpecho $this->Form->input('User.name', array( 'label' => 'The User Alias' ));
Output:
html<div class="input"> <label for="UserName">The User Alias</label> <input name="data[User][name]" type="text" value="" id="UserName" /> </div>
Alternatively, set this key to false to disable the output of the label:
phpecho $this->Form->input('User.name', array('label' => false));
Output:
html<div class="input"> <input name="data[User][name]" type="text" value="" id="UserName" /> </div>
Set this to an array to provide additional options for the
label
element. If you do this, you can use atext
key in the array to customize the label text:phpecho $this->Form->input('User.name', array( 'label' => array( 'class' => 'thingy', 'text' => 'The User Alias' ) ));
Output:
html<div class="input"> <label for="UserName" class="thingy">The User Alias</label> <input name="data[User][name]" type="text" value="" id="UserName" /> </div>
$options['error']
Using this key allows you to override the default model error messages and can be used, for example, to set i18n messages. It has a number of suboptions which control the wrapping element, wrapping element class name, and whether HTML in the error message will be escaped.To disable error message output & field classes set the error key to false:
php$this->Form->input('Model.field', array('error' => false));
To disable only the error message, but retain the field classes, set the errorMessage key to false:
php$this->Form->input('Model.field', array('errorMessage' => false));
To modify the wrapping element type and its class, use the following format:
php$this->Form->input('Model.field', array( 'error' => array( 'attributes' => array('wrap' => 'span', 'class' => 'bzzz') ) ));
To prevent HTML being automatically escaped in the error message output, set the escape suboption to false:
php$this->Form->input('Model.field', array( 'error' => array( 'attributes' => array('escape' => false) ) ));
To override the model error messages use an array with the keys matching the validation rule names:
php$this->Form->input('Model.field', array( 'error' => array('tooShort' => __('This is not long enough')) ));
As seen above you can set the error message for each validation rule you have in your models. In addition you can provide i18n messages for your forms.
Added in version 2.3
Support for the
errorMessage
option was added in 2.3$options['before']
,$options['between']
,$options['separator']
, and$options['after']
Use these keys if you need to inject some markup inside the output of the input() method:
phpecho $this->Form->input('field', array( 'before' => '--before--', 'after' => '--after--', 'between' => '--between---' ));
Output:
html<div class="input"> --before-- <label for="UserField">Field</label> --between--- <input name="data[User][field]" type="text" value="" id="UserField" /> --after-- </div>
For radio inputs the 'separator' attribute can be used to inject markup to separate each input/label pair:
phpecho $this->Form->input('field', array( 'before' => '--before--', 'after' => '--after--', 'between' => '--between---', 'separator' => '--separator--', 'options' => array('1', '2'), 'type' => 'radio' ));
Output:
html<div class="input"> --before-- <input name="data[User][field]" type="radio" value="1" id="UserField1" /> <label for="UserField1">1</label> --separator-- <input name="data[User][field]" type="radio" value="2" id="UserField2" /> <label for="UserField2">2</label> --between--- --after-- </div>
For
date
anddatetime
type elements the 'separator' attribute can be used to change the string between select elements. Defaults to '-'.$options['format']
The ordering of the HTML generated by FormHelper is controllable as well. The 'format' options supports an array of strings describing the template you would like said element to follow. The supported array keys are:array('before', 'input', 'between', 'label', 'after','error')
.$options['inputDefaults']
If you find yourself repeating the same options in multiple input() calls, you can use inputDefaults` to keep your code dry:phpecho $this->Form->create('User', array( 'inputDefaults' => array( 'label' => false, 'div' => false ) ));
All inputs created from that point forward would inherit the options declared in inputDefaults. You can override the defaultOptions by declaring the option in the input() call:
php// No div, no label echo $this->Form->input('password'); // has a label element echo $this->Form->input('username', array('label' => 'Username'));
If you need to later change the defaults you can use
FormHelper::inputDefaults()
.$options['maxlength']
Set this key to set themaxlength
attribute of theinput
field to a specific value. When this key is omitted and the input-type istext
,textarea
,email
,tel
,url
orsearch
and the field-definition is not one ofdecimal
,time
ordatetime
, the length option of the database field is used.
GET Form Inputs
When using FormHelper
to generate inputs for GET
forms, the input names will automatically be shortened to provide more human friendly names. For example:
// Makes <input name="email" type="text" />
echo $this->Form->input('User.email');
// Makes <select name="Tags" multiple="multiple">
echo $this->Form->input('Tags.Tags', array('multiple' => true));
If you want to override the generated name attributes you can use the name
option:
// Makes the more typical <input name="data[User][email]" type="text" />
echo $this->Form->input('User.email', array('name' => 'data[User][email]'));
Generating specific types of inputs
In addition to the generic input()
method, FormHelper
has specific methods for generating a number of different types of inputs. These can be used to generate just the input widget itself, and combined with other methods like ~FormHelper::label()
and ~FormHelper::error()
to generate fully custom form layouts.
Common options
Many of the various input element methods support a common set of options. All of these options are also supported by input()
. To reduce repetition the common options shared by all input methods are as follows:
$options['class']
You can set the class name for an input:phpecho $this->Form->input('title', array('class' => 'custom-class'));
$options['id']
Set this key to force the value of the DOM id for the input.$options['default']
Used to set a default value for the input field. The value is used if the data passed to the form does not contain a value for the field (or if no data is passed at all).Example usage:
phpecho $this->Form->input('ingredient', array('default' => 'Sugar'));
Example with select field (Size "Medium" will be selected as default):
php$sizes = array('s' => 'Small', 'm' => 'Medium', 'l' => 'Large'); echo $this->Form->input( 'size', array('options' => $sizes, 'default' => 'm') );
NOTE
You cannot use
default
to check a checkbox - instead you might set the value in$this->request->data
in your controller, or set the input optionchecked
to true.Date and datetime fields' default values can be set by using the 'selected' key.
Beware of using false to assign a default value. A false value is used to disable/exclude options of an input field, so
'default' => false
would not set any value at all. Instead use'default' => 0
.
In addition to the above options, you can mixin any HTML attribute you wish to use. Any non-special option name will be treated as an HTML attribute, and applied to the generated HTML input element.
Options for select, checkbox and radio inputs
$options['selected']
Used in combination with a select-type input (i.e. For types select, date, time, datetime). Set 'selected' to the value of the item you wish to be selected by default when the input is rendered:phpecho $this->Form->input('close_time', array( 'type' => 'time', 'selected' => '13:30:00' ));
NOTE
The selected key for date and datetime inputs may also be a UNIX timestamp.
$options['empty']
If set to true, forces the input to remain empty.When passed to a select list, this creates a blank option with an empty value in your drop down list. If you want to have a empty value with text displayed instead of just a blank option, pass in a string to empty:
phpecho $this->Form->input('field', array( 'options' => array(1, 2, 3, 4, 5), 'empty' => '(choose one)' ));
Output:
html<div class="input"> <label for="UserField">Field</label> <select name="data[User][field]" id="UserField"> <option value="">(choose one)</option> <option value="0">1</option> <option value="1">2</option> <option value="2">3</option> <option value="3">4</option> <option value="4">5</option> </select> </div>
NOTE
If you need to set the default value in a password field to blank, use 'value' => '' instead.
A list of key-value pairs can be supplied for a date or datetime field:
phpecho $this->Form->dateTime('Contact.date', 'DMY', '12', array( 'empty' => array( 'day' => 'DAY', 'month' => 'MONTH', 'year' => 'YEAR', 'hour' => 'HOUR', 'minute' => 'MINUTE', 'meridian' => false ) ) );
Output:
html<select name="data[Contact][date][day]" id="ContactDateDay"> <option value="">DAY</option> <option value="01">1</option> // ... <option value="31">31</option> </select> - <select name="data[Contact][date][month]" id="ContactDateMonth"> <option value="">MONTH</option> <option value="01">January</option> // ... <option value="12">December</option> </select> - <select name="data[Contact][date][year]" id="ContactDateYear"> <option value="">YEAR</option> <option value="2036">2036</option> // ... <option value="1996">1996</option> </select> <select name="data[Contact][date][hour]" id="ContactDateHour"> <option value="">HOUR</option> <option value="01">1</option> // ... <option value="12">12</option> </select>:<select name="data[Contact][date][min]" id="ContactDateMin"> <option value="">MINUTE</option> <option value="00">00</option> // ... <option value="59">59</option> </select> <select name="data[Contact][date][meridian]" id="ContactDateMeridian"> <option value="am">am</option> <option value="pm">pm</option> </select>
$options['hiddenField']
For certain input types (checkboxes, radios) a hidden input is created so that the key in $this->request->data will exist even without a value specified:html<input type="hidden" name="data[Post][Published]" id="PostPublished_" value="0" /> <input type="checkbox" name="data[Post][Published]" value="1" id="PostPublished" />
This can be disabled by setting the
$options['hiddenField'] = false
:phpecho $this->Form->checkbox('published', array('hiddenField' => false));
Which outputs:
html<input type="checkbox" name="data[Post][Published]" value="1" id="PostPublished" />
If you want to create multiple blocks of inputs on a form that are all grouped together, you should use this parameter on all inputs except the first. If the hidden input is on the page in multiple places, only the last group of input's values will be saved
In this example, only the tertiary colors would be passed, and the primary colors would be overridden:
html<h2>Primary Colors</h2> <input type="hidden" name="data[Color][Color]" id="Colors_" value="0" /> <input type="checkbox" name="data[Color][Color][]" value="5" id="ColorsRed" /> <label for="ColorsRed">Red</label> <input type="checkbox" name="data[Color][Color][]" value="5" id="ColorsBlue" /> <label for="ColorsBlue">Blue</label> <input type="checkbox" name="data[Color][Color][]" value="5" id="ColorsYellow" /> <label for="ColorsYellow">Yellow</label> <h2>Tertiary Colors</h2> <input type="hidden" name="data[Color][Color]" id="Colors_" value="0" /> <input type="checkbox" name="data[Color][Color][]" value="5" id="ColorsGreen" /> <label for="ColorsGreen">Green</label> <input type="checkbox" name="data[Color][Color][]" value="5" id="ColorsPurple" /> <label for="ColorsPurple">Purple</label> <input type="checkbox" name="data[Addon][Addon][]" value="5" id="ColorsOrange" /> <label for="ColorsOrange">Orange</label>
Disabling the
'hiddenField'
on the second input group would prevent this behavior.You can set a different hidden field value other than 0 such as 'N':
phpecho $this->Form->checkbox('published', array( 'value' => 'Y', 'hiddenField' => 'N', ));
Datetime options
$options['timeFormat']
Used to specify the format of the select inputs for a time-related set of inputs. Valid values include12
,24
, andnull
.$options['dateFormat']
Used to specify the format of the select inputs for a date-related set of inputs. Valid values include any combination of 'D', 'M' and 'Y' ornull
. The inputs will be put in the order defined by the dateFormat option.$options['minYear'], $options['maxYear']
Used in combination with a date/datetime input. Defines the lower and/or upper end of values shown in the years select field.$options['orderYear']
Used in combination with a date/datetime input. Defines the order in which the year values will be set. Valid values include 'asc', 'desc'. The default value is 'desc'.$options['interval']
This option specifies the number of minutes between each option in the minutes select box:phpecho $this->Form->input('Model.time', array( 'type' => 'time', 'interval' => 15 ));
Would create 4 options in the minute select. One for each 15 minutes.
$options['round']
Can be set to up or down to force rounding in either direction. Defaults to null which rounds half up according to interval.Added in version 2.4
Form Element-Specific Methods
All elements are created under a form for the User
model as in the examples above. For this reason, the HTML code generated will contain attributes that reference to the User model. Ex: name=data[User][username], id=UserUsername
method
FormHelper::label(string $fieldName, string $text, array $options)
method
FormHelper::text(string $name, array $options)
method
FormHelper::password(string $fieldName, array $options)
method
FormHelper::hidden(string $fieldName, array $options)
method
FormHelper::textarea(string $fieldName, array $options)
method
FormHelper::checkbox(string $fieldName, array $options)
method
FormHelper::radio(string $fieldName, array $options, array $attributes)
method
FormHelper::select(string $fieldName, array $options, array $attributes)
method
FormHelper::file(string $fieldName, array $options)
Validating Uploads
Below is an example validation method you could define in your model to validate whether a file has been successfully uploaded:
public function isUploadedFile($params) {
$val = array_shift($params);
if ((isset($val['error']) && $val['error'] == 0) ||
(!empty( $val['tmp_name']) && $val['tmp_name'] != 'none')
) {
return is_uploaded_file($val['tmp_name']);
}
return false;
}
Creates a file input:
echo $this->Form->create('User', array('type' => 'file'));
echo $this->Form->file('avatar');
Will output:
<form enctype="multipart/form-data" method="post" action="/users/add">
<input name="data[User][avatar]" value="" id="UserAvatar" type="file">
NOTE
When using $this->Form->file()
, remember to set the form encoding-type, by setting the type option to 'file' in $this->Form->create()
Creating buttons and submit elements
method
FormHelper::submit(string $caption, array $options)
method
FormHelper::button(string $title, array $options = array())
method
FormHelper::postButton(string $title, mixed $url, array $options = array ())
method
FormHelper::postLink(string $title, mixed $url = null, array $options = array ())
Creating date and time inputs
method
FormHelper::dateTime($fieldName, $dateFormat = 'DMY', $timeFormat = '12', $attributes = array())
method
FormHelper::year(string $fieldName, int $minYear, int $maxYear, array $attributes)
method
FormHelper::month(string $fieldName, array $attributes)
method
FormHelper::day(string $fieldName, array $attributes)
method
FormHelper::hour(string $fieldName, boolean $format24Hours, array $attributes)
method
FormHelper::minute(string $fieldName, array $attributes)
method
FormHelper::meridian(string $fieldName, array $attributes)
Displaying and checking errors
method
FormHelper::error(string $fieldName, mixed $text, array $options)
method
FormHelper::isFieldError(string $fieldName)
method
FormHelper::tagIsInvalid()
Setting Defaults for all fields
Added in version 2.2
You can declare a set of default options for input()
using FormHelper::inputDefaults()
. Changing the default options allows you to consolidate repeated options into a single method call:
$this->Form->inputDefaults(array(
'label' => false,
'div' => false,
'class' => 'fancy'
)
);
All inputs created from that point forward will inherit the options declared in inputDefaults. You can override the default options by declaring the option in the input() call:
echo $this->Form->input('password'); // No div, no label with class 'fancy'
// has a label element same defaults
echo $this->Form->input(
'username',
array('label' => 'Username')
);
Working with SecurityComponent
SecurityComponent
offers several features that make your forms safer and more secure. By simply including the SecurityComponent
in your controller, you'll automatically benefit from CSRF and form tampering features.
As mentioned previously when using SecurityComponent, you should always close your forms using FormHelper::end()
. This will ensure that the special _Token
inputs are generated.
method
FormHelper::unlockField($name)
method
FormHelper::secure(array $fields = array())
2.0 updates
$selected parameter removed
The $selected
parameter was removed from several methods in FormHelper. All methods now support a $attributes['value']
key now which should be used in place of $selected
. This change simplifies the FormHelper methods, reducing the number of arguments, and reduces the duplication that $selected
created. The effected methods are:
- FormHelper::select()
- FormHelper::dateTime()
- FormHelper::year()
- FormHelper::month()
- FormHelper::day()
- FormHelper::hour()
- FormHelper::minute()
- FormHelper::meridian()
Default URLs on forms is the current action
The default URL for all forms, is now the current URL including passed, named, and querystring parameters. You can override this default by supplying $options['url']
in the second parameter of $this->Form->create()
FormHelper::hidden()
Hidden fields no longer remove the class attribute. This means that if there are validation errors on hidden fields, the error-field class name will be applied.