Develop Simply

Ivan K's development musings

Introducing Kohana Form Builder

I have a history with forms - all kinds of them - Symfony Forms, Cake Forms, Kohana Forms, Rails Forms - you name it. And every form builder had something missing - some feature that I had to build, some misconception about what is really desired of the builder. Some got it better than others - for example I am a big fan of rails form helper thingie. It has a ease-of-use feel to it that I hadn’t encountered elsewhere - but it does have some missing features that I always ended up implementing myself. Symfony on the other hand has quite a lot of features but it feels so complicated and cumbersome to use that I often don’t even bother. So I needed a form builder for Kohana 3.2 and decided to build one that had everything I dreamed of having - of course I ended up with a lot of compromises - but the result so far looks quite satisfying - form-builder

Requirements

I’ve put a lot of effort to make writing forms as effortless as possible. There are some basic requirements that I want out of the form builder module:

  1. Configurability - every project’s forms have different requirements of “when to show what” - this had to be implemented in such a way that you would be able to go straight down to HTML and basic PHP to customize your forms, preferably in a repeatable way.
  2. Jelly integration - you would probably have a lot of logic for validation and fields themselves already - I wanted to tap into this instead of duplicating it elsewhere.
  3. Stand on their own - but sometimes you do want to build forms without a specific jelly model attached to it, maybe with just a Validation object, or no object at all
  4. Nested forms - you might say that this is too specific and rarely used - but in every single project I dealt with there had to be at least one nested form - and it’s such a basic concept that I did want it to work right out of the box
  5. Extensibility - you must be able to write new widgets easily - with different properties - multiple fields, with required or optional parameters and to have access to the whole model
  6. Ease of writing - writing HTML forms in your templates should be easy and concise - period.

I’ve tried to address all of those properly and if I’ve strayed off this path I would be happy to receive suggestions how to get back on track :)

Example

So here’s an actual example of a form:

The Controller:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
class Controller_Users extends Controller_Template
{
  public function action_edit()
  {
      //Load 
      $user = Jelly::factory('user', $this->request->param('id'));
      $form = Form_Builder::factory($user, $_POST);

      if($this->request->method() == Request::POST AND $form->check())
      {
          $form->save();
          $this->redirect("/success");
      }
      $this->template->content = View::factory('form', array('form' => $form));
  }
}
?>

And the view:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php echo Form::open('/edit') ?>
  <fieldset>
  <legend>Basic Info</legend>
      <?php echo $form->row('input', 'email', null, array('type' => 'email')) ?>
      <?php echo $form->row('input', 'first_name') ?>
      <?php echo $form->row('input', 'last_name') ?>
      <?php echo $form->row('input', 'password') ?>
      <?php echo $form->row('checkboxes', 'roles', array('choices' => Jelly::query('role')->select())) ?>
  </legend>

  <fieldset>
  <legend>About</legend>
      <?php echo $form->row('checkbox', 'receive_newsletter', null, array('class' => 'span8')) ?>
      <?php echo $form->row('textarea', 'description', null, array('class' => 'span12')) ?>
  </fieldset>

  <fieldset>
  <legend>Contacts</legend>
      <?php echo $form->row('input', 'website') ?>
      <?php echo $form->row('input', 'twitter') ?>
      <?php echo $form->row('input', 'facebook') ?>
  </fieldset>

That form is sufficient to view and edit the user’s properties, displaying errors on fail when appropriate and it’s all quite self-explanatory - the only concept different from the already established ones in Kohana and Jelly is the concept of “widgets” - you basically have functions that construct some kind of input tags - in this example they are input, textarea, checkbox and checkboxes. All of this is explained in the README

The icing on the cake is that it reads Jelly Model’s rules and places html5 form validation whenever possible.