Buy
This tutorial has a new version, check it out!

Registration Form

Let’s make our site a little bit more legit with a registration form. Go grab some coffee, cause we’re about to rock our world with some big and powerful concepts like forms and validation.

Creating the Registration Page

Let’s start by creating a new RegisterController class in UserBundle. Creating a controller by hand is easy: just add the right namespace and then extend Symfony’s base controller class. The registerAction method will be our actual registration page:

// src/Yoda/UserBundle/Controller/RegisterController.php
namespace Yoda\UserBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class RegisterController extends Controller
{
    public function registerAction()
    {
        // todo
    }
}

I’m kinda liking these annotation routes, so let’s use those again. Remember, to do this, we need two things. First, add the Route use statement and then setup the route above the method:

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

// ...
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;

class RegisterController extends Controller
{
    /**
     * @Route("/register", name="user_register")
     */
    public function registerAction()
    {
        // todo
    }
}

Second, we need to import the routes in routing.yml. And hey! We’re already importing annotations from the entire Controller/ directory, so we’re ready to go!

# app/config/routing.yml
# ...

user_routes:
    resource: "@UserBundle/Controller"
    type: annotation

To see if the route is being loaded, run the router:debug console task.

php app/console router:debug

Yep, there it is!

Building the Form

Now let’s build a form, which is an object that knows all of the fields we want and their types. It’ll help us render the form and process its values. It’s pretty fancy!

Start by calling the createFormBuilder() method. Now, use the add function to give the form username, email and password fields:

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

public function registerAction()
{
    $form = $this->createFormBuilder()
        ->add('username', 'text')
        ->add('email', 'text')
        ->add('password', 'password')
        ->getForm()
    ;

    // todo next - render a template
}

The two arguments to add are the name of the field and the field “type”. Symfony comes with built-in types for creating text fields, select fields, date fields and forcefields. I’ll show you where to find a list in a minute.

When we’re all done, we call getForm().

Passing the Form into Twig

I want to render the form, so let’s pass it to Twig. To save and impress my ewok friends, I’m going use the @Template annotation trick we saw earlier. Pass the form as the only variable:

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

/**
 * @Route("/register", name="user_register")
 * @Template
 */
public function registerAction()
{
    $form = $this->createFormBuilder()
        // ...
        ->getForm()
    ;

    return array('form' => $form);
}

Tip

The above code has some bugs! Yuck! Keep reading below to fix them.

Fixing the Missing @Template Annotation

So let’s create the Twig template. Make a “Register” directory in Resources/views since we’re rendering from RegisterController and @Template uses that to figure out the template path. I’ll paste in some HTML-goodness to get us started:

{# src/Yoda/UserBundle/Resources/views/Register/register.html.twig #}
{% extends '::base.html.twig' %}

{% block stylesheets %}
    {{ parent() }}

    <link rel="stylesheet" href="{{ asset('bundles/user/css/login.css') }}" />
{% endblock %}

{% block body %}
<section class="login">
    <article>
        <h1>Register</h1>

    </article>
</section>
{% endblock %}

Tip

You can find this template code in the resources/episode2 directory of the code download. Go get it!

So let’s head to the browser to see how things look so far. When we go to /register, we see a nice looking page. Kidding! We see a huge, horrible threatening error!

AnnotationException: [SemanticalError] The annotation “@Template” in method Yoda\UserBundle\Controller\RegisterController::registerAction() was never imported. Did you maybe forget to add a “use” statement for this annotation?

Tip

Sometimes errors are nested, and the most helpful parts are further below.

Look closely, the error contains the answer. Ah, I’ve used the @Template shortcut but forgot to put a use statement for it. After adding the namespace, I can refresh and see the page:

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

// ...
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

Leave a comment!

  • 2018-02-23 Victor Bocharsky

    Hey Junaid,

    Ah, ok :) Well, yes, with form types you can easily reuse forms.. and also it's easy to render form fields, you can easily change form themes and see different rendering, see related docs: http://symfony.com/doc/curr... .

    Hm, have it rendered according to the data or variables passed from the view sounds a bit weird to me, but probably I don't see the whole picture and you allow a lot of customization from suer side. So if it works for you and you can easily understand how it works - I think it's fine. But yeah, best practice probably would be avoid passing vars from the view. But once again, probably I just doe not see the entire picture ;)

    Cheers!

  • 2018-02-22 Junaid Farooq

    Hey Victor Bocharsky

    I got it. I originally meant to create forms in Twig just as we do in normal HTML but your answer gave me more than i had thought and that too to my advantage. Creating a form in a controller and then re-using it elsewhere is totally advantageous, i got it. But do you think it would be a bad-practice if i create a Form Type and then have it rendered according to the data or variables passed from my view. For Example, a friend of mine is working on a project where they have form types in Symfony but they are rendering them according to the data passed onto the Form Type from View (whatever that might be,,,Twig, JS, etc). I hope you get my point.

    Cheers!

  • 2018-02-22 Victor Bocharsky

    Hey Junaid,

    Probably, the simplest answer is that you also need to use forms inside controllers first, so it'll be impossible to reuse form in controllers if you create it in templates, but possible the reverse. :)

    But let's figure it out. First of all, I suppose you mean Twig template here, then you can create a form in PHP only, because you need to call $this->createForm() method and because you don't have an ability to create a form inside templates out of the box. Well, you probably can create a custom Twig function which will create a form you need, but the question is why you want in create it in a template? Actually, this is a bad practice, you need to *pass* all the variables you need from controllers to templates instead of creating them directly inside templates, i.e. we're talking about different layers here: Controller vs View - and you should avoid mixing those layers. So the best practice is to prepare (i.e. create variables) inside controllers and pass them to templates where those variables are *used* (rendered).

    Hope this helps you to understand it better.

    Cheers!

  • 2018-02-22 Junaid Farooq

    Hi there,

    I have a question here. Here we are building the form in the controller. Why not to do it in the template. what are the advantages/disadvantages of one over the other? Thanks in advance.

    Cheers!