This tutorial has a new version, check it out!

Using an External Form Type Class

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $12.00

Using an External Form Type Class

We built our form right inside the controller, which was really simple. But, it makes our controller a bit ugly and if we needed to re-use this form somewhere else, that wouldn’t be possible.

For those reasons, the code to create a form usually lives in its own class. Create a new Form directory and a new file called RegisterFormType. Create the class, give it a namespace and make it extend a class called AbstractType:

// src/Yoda/UserBundle/Form/RegisterFormType.php
namespace Yoda\UserBundle\Form;

use Symfony\Component\Form\AbstractType;

class RegisterFormType extends AbstractType

We need to add a few methods to this class. The first, and least important is getName(). Add this, and just return a string that’s unique among your forms. It’s used as part of the name attribute on your rendered form:

// src/Yoda/UserBundle/Form/RegisterFormType.php
// ...

public function getName()
    return 'user_register';

The really important method is buildForm(). I’m going to use my IDE to create this method for me. If you create your’s manually, just don’t forget the use statement for the FormBuilderInterface.

The buildForm method is where we build our form! Genius! Copy the code from our controller that adds the fields and put that here:

// src/Yoda/UserBundle/Form/RegisterFormType.php

use Symfony\Component\Form\FormBuilderInterface;
// ...

public function buildForm(FormBuilderInterface $builder, array $options)
        ->add('username', 'text')
        ->add('email', 'email')
        ->add('plainPassword', 'repeated', array(
            'type' => 'password'

Finally, create a setDefaultOptions function and set the data_class option on it:

// src/Yoda/UserBundle/Form/RegisterFormType.php

use Symfony\Component\OptionsResolver\OptionsResolverInterface;
// ...

public function setDefaultOptions(OptionsResolverInterface $resolver)
        'data_class' => 'Yoda\UserBundle\Entity\User',

That’s it! This class is now a recipe for exactly how the form should look.

Using the Form Class

Remove the builder code in our controller. Instead, replace it with a call to createForm and pass it an instance of the new RegisterFormType:

// src/Yoda/UserBundle/Controller/RegisterController.php

use Yoda\UserBundle\Form\RegisterFormType;
// ...

public function registerAction(Request $request)
    $defaultUser = new User();

    $form = $this->createForm(new RegisterFormType(), $defaultUser);

    // ...

Refresh! We’ve conquered forms!

Forms: From Space

Some quick review. A form is something you build, giving it the fields and field types you need. At first, a form just returns an associative array, but we can change that with the data_class option to return a populated object. Forms can also be built right inside the controller or in an external class.

Got it? Great! Let’s move on to validation.

Leave a comment!

What PHP libraries does this tutorial use?

// composer.json
    "require": {
        "php": ">=5.3.3",
        "symfony/symfony": "~2.4", // v2.4.2
        "doctrine/orm": "~2.2,>=2.2.3", // v2.4.2
        "doctrine/doctrine-bundle": "~1.2", // v1.2.0
        "twig/extensions": "~1.0", // v1.0.1
        "symfony/assetic-bundle": "~2.3", // v2.3.0
        "symfony/swiftmailer-bundle": "~2.3", // v2.3.5
        "symfony/monolog-bundle": "~2.4", // v2.5.0
        "sensio/distribution-bundle": "~2.3", // v2.3.4
        "sensio/framework-extra-bundle": "~3.0", // v3.0.0
        "sensio/generator-bundle": "~2.3", // v2.3.4
        "incenteev/composer-parameter-handler": "~2.0", // v2.1.0
        "doctrine/doctrine-fixtures-bundle": "~2.2.0", // v2.2.0
        "ircmaxell/password-compat": "~1.0.3", // 1.0.3
        "phpunit/phpunit": "~4.1" // 4.1.0