Forms

Phalcon\Forms\Form is a component that helps with the creation and maintenance of forms in web applications.

The following example shows its basic usage:

  1. <?php
  2. use Phalcon\Forms\Form;
  3. use Phalcon\Forms\Element\Text;
  4. use Phalcon\Forms\Element\Select;
  5. $form = new Form();
  6. $form->add(
  7. new Text(
  8. 'name'
  9. )
  10. );
  11. $form->add(
  12. new Text(
  13. 'telephone'
  14. )
  15. );
  16. $form->add(
  17. new Select(
  18. 'telephoneType',
  19. [
  20. 'H' => 'Home',
  21. 'C' => 'Cell',
  22. ]
  23. )
  24. );

Forms can be rendered based on the form definition:

  1. <h1>
  2. Contacts
  3. </h1>
  4. <form method='post'>
  5. <p>
  6. <label>
  7. Name
  8. </label>
  9. <?php echo $form->render('name'); ?>
  10. </p>
  11. <p>
  12. <label>
  13. Telephone
  14. </label>
  15. <?php echo $form->render('telephone'); ?>
  16. </p>
  17. <p>
  18. <label>
  19. Type
  20. </label>
  21. <?php echo $form->render('telephoneType'); ?>
  22. </p>
  23. <p>
  24. <input type='submit' value='Save' />
  25. </p>
  26. </form>

Each element in the form can be rendered as required by the developer. Internally, Phalcon\Tag is used to produce the correct HTML for each element and you can pass additional HTML attributes as the second parameter of render():

  1. <p>
  2. <label>
  3. Name
  4. </label>
  5. <?php echo $form->render('name', ['maxlength' => 30, 'placeholder' => 'Type your name']); ?>
  6. </p>

HTML attributes also can be set in the element’s definition:

  1. <?php
  2. $form->add(
  3. new Text(
  4. 'name',
  5. [
  6. 'maxlength' => 30,
  7. 'placeholder' => 'Type your name',
  8. ]
  9. )
  10. );

Initializing forms

As seen before, forms can be initialized outside the form class by adding elements to it. You can re-use code or organize your form classes implementing the form in a separated file:

  1. <?php
  2. use Phalcon\Forms\Form;
  3. use Phalcon\Forms\Element\Text;
  4. use Phalcon\Forms\Element\Select;
  5. class ContactForm extends Form
  6. {
  7. public function initialize()
  8. {
  9. $this->add(
  10. new Text(
  11. 'name'
  12. )
  13. );
  14. $this->add(
  15. new Text(
  16. 'telephone'
  17. )
  18. );
  19. $this->add(
  20. new Select(
  21. 'telephoneType',
  22. TelephoneTypes::find(),
  23. [
  24. 'using' => [
  25. 'id',
  26. 'name',
  27. ],
  28. 'useEmpty' => true,
  29. 'emptyText' => 'Select one...',
  30. 'emptyValue' => '',
  31. ]
  32. )
  33. );
  34. }
  35. }

Additionally, the Select elements support the useEmpty option to enable the use of a blank element within the list of available options. The options emptyText and emptyValue are optional, which allow you to customize, respectively, the text and the value of the empty element

Phalcon\Forms\Form extends Phalcon\Di\Injectable so you have access to the application services if needed:

  1. <?php
  2. use Phalcon\Forms\Form;
  3. use Phalcon\Forms\Element\Text;
  4. use Phalcon\Forms\Element\Hidden;
  5. class ContactForm extends Form
  6. {
  7. /**
  8. * This method returns the default value for field 'csrf'
  9. */
  10. public function getCsrf()
  11. {
  12. return $this->security->getToken();
  13. }
  14. public function initialize()
  15. {
  16. // Set the same form as entity
  17. $this->setEntity($this);
  18. // Add a text element to capture the 'email'
  19. $this->add(
  20. new Text(
  21. 'email'
  22. )
  23. );
  24. // Add a text element to put a hidden CSRF
  25. $this->add(
  26. new Hidden(
  27. 'csrf'
  28. )
  29. );
  30. }
  31. }

The associated entity added to the form in the initialization and custom user options are passed to the form constructor:

  1. <?php
  2. use Phalcon\Forms\Form;
  3. use Phalcon\Forms\Element\Text;
  4. use Phalcon\Forms\Element\Hidden;
  5. class UsersForm extends Form
  6. {
  7. /**
  8. * Forms initializer
  9. *
  10. * @param Users $user
  11. * @param array $options
  12. */
  13. public function initialize(Users $user, array $options)
  14. {
  15. if ($options['edit']) {
  16. $this->add(
  17. new Hidden(
  18. 'id'
  19. )
  20. );
  21. } else {
  22. $this->add(
  23. new Text(
  24. 'id'
  25. )
  26. );
  27. }
  28. $this->add(
  29. new Text(
  30. 'name'
  31. )
  32. );
  33. }
  34. }

In the form’s instantiation you must use:

  1. <?php
  2. $form = new UsersForm(
  3. new Users(),
  4. [
  5. 'edit' => true,
  6. ]
  7. );

Validation

Phalcon forms are integrated with the validation component to offer instant validation. Built-in or custom validators could be set to each element:

  1. <?php
  2. use Phalcon\Forms\Element\Text;
  3. use Phalcon\Validation\Validator\PresenceOf;
  4. use Phalcon\Validation\Validator\StringLength;
  5. $name = new Text(
  6. 'name'
  7. );
  8. $name->addValidator(
  9. new PresenceOf(
  10. [
  11. 'message' => 'The name is required',
  12. ]
  13. )
  14. );
  15. $name->addValidator(
  16. new StringLength(
  17. [
  18. 'min' => 10,
  19. 'messageMinimum' => 'The name is too short',
  20. ]
  21. )
  22. );
  23. $form->add($name);

Then you can validate the form according to the input entered by the user:

  1. <?php
  2. if (!$form->isValid($_POST)) {
  3. $messages = $form->getMessages();
  4. foreach ($messages as $message) {
  5. echo $message, '<br>';
  6. }
  7. }

Validators are executed in the same order as they were registered.

By default messages generated by all the elements in the form are joined so they can be traversed using a single foreach, you can change this behavior to get the messages separated by the field:

  1. <?php
  2. foreach ($form->getMessages(false) as $attribute => $messages) {
  3. echo 'Messages generated by ', $attribute, ':', "\n";
  4. foreach ($messages as $message) {
  5. echo $message, '<br>';
  6. }
  7. }

Or get specific messages for an element:

  1. <?php
  2. $messages = $form->getMessagesFor('name');
  3. foreach ($messages as $message) {
  4. echo $message, '<br>';
  5. }

Filtering

A form is also able to filter data before it is validated. You can set filters in each element:

  1. <?php
  2. use Phalcon\Forms\Element\Text;
  3. $name = new Text(
  4. 'name'
  5. );
  6. // Set multiple filters
  7. $name->setFilters(
  8. [
  9. 'string',
  10. 'trim',
  11. ]
  12. );
  13. $form->add($name);
  14. $email = new Text(
  15. 'email'
  16. );
  17. // Set one filter
  18. $email->setFilters(
  19. 'email'
  20. );
  21. $form->add($email);
Learn more about filtering in Phalcon by reading the Filter documentation

Forms + Entities

An entity such as a model/collection/plain instance or just a plain PHP class can be linked to the form in order to set default values in the form’s elements or assign the values from the form to the entity easily:

  1. <?php
  2. $robot = Robots::findFirst();
  3. $form = new Form($robot);
  4. $form->add(
  5. new Text(
  6. 'name'
  7. )
  8. );
  9. $form->add(
  10. new Text(
  11. 'year'
  12. )
  13. );

Once the form is rendered if there is no default values assigned to the elements it will use the ones provided by the entity:

  1. <?php echo $form->render('name'); ?>

You can validate the form and assign the values from the user input in the following way:

  1. <?php
  2. $form->bind($_POST, $robot);
  3. // Check if the form is valid
  4. if ($form->isValid()) {
  5. // Save the entity
  6. $robot->save();
  7. }

Setting up a plain class as entity also is possible:

  1. <?php
  2. class Preferences
  3. {
  4. public $timezone = 'Europe/Amsterdam';
  5. public $receiveEmails = 'No';
  6. }

Using this class as entity, allows the form to take the default values from it:

  1. <?php
  2. $form = new Form(
  3. new Preferences()
  4. );
  5. $form->add(
  6. new Select(
  7. 'timezone',
  8. [
  9. 'America/New_York' => 'New York',
  10. 'Europe/Amsterdam' => 'Amsterdam',
  11. 'America/Sao_Paulo' => 'Sao Paulo',
  12. 'Asia/Tokyo' => 'Tokyo',
  13. ]
  14. )
  15. );
  16. $form->add(
  17. new Select(
  18. 'receiveEmails',
  19. [
  20. 'Yes' => 'Yes, please!',
  21. 'No' => 'No, thanks',
  22. ]
  23. )
  24. );

Entities can implement getters, which have a higher precedence than public properties. These methods give you more freedom to produce values:

  1. <?php
  2. class Preferences
  3. {
  4. public $timezone;
  5. public $receiveEmails;
  6. public function getTimezone()
  7. {
  8. return 'Europe/Amsterdam';
  9. }
  10. public function getReceiveEmails()
  11. {
  12. return 'No';
  13. }
  14. }

Form Elements

Phalcon provides a set of built-in elements to use in your forms, all these elements are located in the Phalcon\Forms\Element namespace:

NameDescription
Phalcon\Forms\Element\TextGenerate INPUT[type=text] elements
Phalcon\Forms\Element\PasswordGenerate INPUT[type=password] elements
Phalcon\Forms\Element\SelectGenerate SELECT tag (combo lists) elements based on choices
Phalcon\Forms\Element\CheckGenerate INPUT[type=check] elements
Phalcon\Forms\Element\TextAreaGenerate TEXTAREA elements
Phalcon\Forms\Element\HiddenGenerate INPUT[type=hidden] elements
Phalcon\Forms\Element\FileGenerate INPUT[type=file] elements
Phalcon\Forms\Element\DateGenerate INPUT[type=date] elements
Phalcon\Forms\Element\NumericGenerate INPUT[type=number] elements
Phalcon\Forms\Element\SubmitGenerate INPUT[type=submit] elements
Phalcon\Forms\Element\TextGenerate INPUT[type=text] elements
Phalcon\Forms\Element\TextAreaGenerate TEXTAREA elements

Event Callbacks

Whenever forms are implemented as classes, the callbacks: beforeValidation() and afterValidation() can be implemented in the form’s class to perform pre-validations and post-validations:

  1. <?php
  2. use Phalcon\Forms\Form;
  3. class ContactForm extends Form
  4. {
  5. public function beforeValidation()
  6. {
  7. }
  8. }

Rendering Forms

You can render the form with total flexibility, the following example shows how to render each element using a standard procedure:

  1. <?php
  2. <form method='post'>
  3. <?php
  4. // Traverse the form
  5. foreach ($form as $element) {
  6. // Get any generated messages for the current element
  7. $messages = $form->getMessagesFor(
  8. $element->getName()
  9. );
  10. if (count($messages)) {
  11. // Print each element
  12. echo '<div class='messages'>';
  13. foreach ($messages as $message) {
  14. echo $message;
  15. }
  16. echo '</div>';
  17. }
  18. echo '<p>';
  19. echo '<label for='', $element->getName(), ''>', $element->getLabel(), '</label>';
  20. echo $element;
  21. echo '</p>';
  22. }
  23. ?>
  24. <input type='submit' value='Send' />
  25. </form>

Or reuse the logic in your form class:

  1. <?php
  2. use Phalcon\Forms\Form;
  3. class ContactForm extends Form
  4. {
  5. public function initialize()
  6. {
  7. // ...
  8. }
  9. public function renderDecorated($name)
  10. {
  11. $element = $this->get($name);
  12. // Get any generated messages for the current element
  13. $messages = $this->getMessagesFor(
  14. $element->getName()
  15. );
  16. if (count($messages)) {
  17. // Print each element
  18. echo "<div class='messages'>";
  19. foreach ($messages as $message) {
  20. echo $this->flash->error($message);
  21. }
  22. echo '</div>';
  23. }
  24. echo '<p>';
  25. echo '<label for="', $element->getName(), '">', $element->getLabel(), '</label>';
  26. echo $element;
  27. echo '</p>';
  28. }
  29. }

In the view:

  1. <?php
  2. echo $element->renderDecorated('name');
  3. echo $element->renderDecorated('telephone');

Creating Form Elements

In addition to the form elements provided by Phalcon you can create your own custom elements:

  1. <?php
  2. use Phalcon\Forms\Element;
  3. class MyElement extends Element
  4. {
  5. public function render($attributes = null)
  6. {
  7. $html = // ... Produce some HTML
  8. return $html;
  9. }
  10. }

Forms Manager

This component provides a forms manager that can be used by the developer to register forms and access them via the service locator:

  1. <?php
  2. use Phalcon\Forms\Manager as FormsManager;
  3. $di['forms'] = function () {
  4. return new FormsManager();
  5. };

Forms are added to the forms manager and referenced by a unique name:

  1. <?php
  2. $this->forms->set(
  3. 'login',
  4. new LoginForm()
  5. );

Using the unique name, forms can be accessed in any part of the application:

  1. <?php
  2. $loginForm = $this->forms->get('login');
  3. echo $loginForm->render();

External Resources

  • Vökuró, is a sample application that uses the forms builder to create and manage forms, [Github]