Symfony – forms in Symfony

What forms are really like in Symfony

You know what your Book object looks like, Symfony created the Book class and the BookForm class for you.

Once you do

$form = new BookForm()

in one of your actions, displaying the form in the template is as easy as:

<form action=<?php echo url_for('book/new') ?> action="post">
    <?php echo $form ?>
    <input type="submit" value="Add new book" />
</form>

The echo $form part outputs rows using the Book’s properties. Each row has label, input, error message.
Pretty cool, huh?

This may work wonders in the backend, but what if you want your user to add a new book? At this point Symfony displays ALL the Book’s properties, like title, description, author, isbn, and that’s fine. But it also displays is_active, created_at, updated_at, and you don’t want that exposed to the users.

1. So you start customizing. You edit the BookForm class to hide certain fields:

$this->useFields(array('title', 'description', 'image', 'author_id', 'isbn'));

2. You need to clearly identify some fields. For example, the image is just a string in your database. But in your form you can turn it into a file upload field by doing:

$this->widgetSchema['image'] = new sfWidgetFormInputFile(array(
    'label' => 'Book cover',
));

3. You also want some simple validation for that image field:

$this->validatorSchema['image'] = new sfValidatorFile(array(
    'required'   => false,
    'path'       => sfConfig::get('sf_upload_dir').'/book_covers',
    'mime_types' => 'web_images',
    'validated_file_class' => 'sfResizedFile'
));

4. Once that is done, you want more control over the overall design of the view. So echo $form is no longer enough.
You can split the form by rows using:

<div class="form_row">
    $form['title']->render();
</div>
<div class="form_row">
    $form['description']->render();
</div>
<div class="form_row>
    $form['author_id']->render();
</div>
<div class="form_row">
    $form['isbn']->render();
</div>

5. But that’t rarely enough. You will usually get to creating the form entirely by hand:

<div class="form_row">
    <div class="field_label">
        <label for="title">Book title</label>
    </div>
    <div class="field_container">
        <?php echo $form['title']->render(array('class' => 'field_input')) ?>
        <?php echo $form['title']->renderError() ?>
    </div>
</div>
<div class="form_row">
    <div>
        <label for="description">Description</label>
    </div>
    <div class="field_label">
        <?php echo $form['description']->render(array('class' => 'field_input_textarea')) ?>
        <?php echo $form['description']->renderError() ?>
    </div>
</div>

If you need even more control over, for example, the error field you’ll need to split things up even more.

Now imagine that you need to embed another form into this form (say a Book can be linked to a Review, which is a different object, different database table and you want the Review content field into the Book form). And then think about using AJAX or jQuery to make things cooler. :)
And it all started from that little echo $form

I think that’s exactly the point with Symfony: easy to set up and make it work, a lot harder to customize and tweak it the way you like.

Anyway, though frustrating to learn, Symfony is pretty cool. My mind does slip towards Django or Code Igniter sometimes though… I haven’t tried those yet, but soon.

Tags:

Leave a Reply