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

Handling Form Submissions

Handling Form Submissions

Ok, let’s get this form to actually submit! Since we’re submitting back to the same route and controller, we want to process things only if the request is a POST.

Getting the Request object

First, we’ll need Symfony’s Request object. To get this in a controller, add a $request argument that’s type-hinted with Symfony’s Request class:

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

use Symfony\Component\HttpFoundation\Request;

class RegisterController extends Controller
{
    // ...
    public function registerAction(Request $request)
    {
        // ...
    }
}

Normally, if you have an argument here, Symfony tries to populate it from a routing wildcard with the same name as the variable. If it doesn’t find one, it throws a giant error. The only exception to that rule is this: if you type-hint an argument with the Request class, Symfony will give you that object. This doesn’t work for everything, only the Request class.

Using handleRequest

Use the form’s handleRequest method to actually process the data. Next, add an if statement that checks to see if the form was submitted and if all of the data is valid:

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

use Symfony\Component\HttpFoundation\Request;
// ...

public function registerAction(Request $request)
{
    $form = $this->createFormBuilder()
        // ...
        ->getForm()
    ;

    $form->handleRequest($request);
    if ($form->isSubmitted() && $form->isValid()) {

        // do something in a moment
    }

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

The handleRequest method grabs the POST’ed data from the request, processes it, and runs any validation. And actually, it only does this for POST requests so on a GET request, $form->isSubmitted() returns false.

Tip

If you have a form that’s submitted via a different HTTP method, set the method.

If the form is submitted because it’s a POST request and passes validation, let’s just print the submitted data for now. If the form is invalid, or if this is a GET request, it’ll just skip this block and re-render the form with errors if there are any:

if ($form->isSubmitted() && $form->isValid()) {
    var_dump($form->getData());die;
}

Time to test it! We haven’t added validation yet, but the password fields have built-in validation if the values don’t match. When I submit, the form is re-rendered, meaning there was an error.

In fact, there’s now a little red box on the web debug toolbar. If we click it, we can see details about the form: what was submitted and options for each field.

Head back and fill in the form correctly. Now we see our dumped data:

array(
    'username' => string 'foo' (length=3),
    'email' => string 'foo@foo.com' (length=11),
    'password' => string 'foo' (length=3),
)

Using the Submitted Data Array

Notice that the data is an array with a key and value for each field. Let’s take this data and build a new User object from it. There is an easier way to do this, and I’ll show you in a second:

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

use Yoda\UserBundle\Entity\User;
// ...

$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
    $data = $form->getData();

    $user = new User();
    $user->setUsername($data['username']);
    $user->setEmail($data['email']);
}

Encoding the User’s Password

We still need to encode and set the password. For now, let’s copy in some code from our user fixtures to help with this. We’ll make this much more awesome in the next screencast:

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

private function encodePassword(User $user, $plainPassword)
{
    $encoder = $this->container->get('security.encoder_factory')
        ->getEncoder($user)
    ;

    return $encoder->encodePassword($plainPassword, $user->getSalt());
}

Use this function, then finally persist and flush the new User:

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

if ($form->isValid()) {
    $data = $form->getData();

    $user = new User();
    $user->setUsername($data['username']);
    $user->setEmail($data['email']);
    $user->setPassword($this->encodePassword($user, $data['password']));

    $em = $this->getDoctrine()->getManager();
    $em->persist($user);
    $em->flush();

    // we'll redirect the user next...
}

Redirecting after Success

The last step of any successful form submit is to redirect - we’ll redirect to the homepage. First, we need to generate a URL - just like we do with the path() function in Twig. In a controller, there’s a generateUrl function that works exactly the same way:

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

if ($form->isSubmitted() && $form->isValid()) {
    // ...

    $em->flush();

    $url = $this->generateUrl('event');
}

To redirect, use the redirect function and pass it the URL:

if ($form->isSubmitted() && $form->isValid()) {
    // ...
    $url = $this->generateUrl('event');

    return $this->redirect($url);
}

Tip

If you use Symfony 2.6 or newer, you have a redirectToRoute method that allows you to redirect based on the route name instead of having to generate the URL first. It’s a shortcut!

Remember that a controller always returns a Response object. redirect is just a shortcut to create a Response that’s all setup to redirect to this URL.

Ok, time to kick this proton torpedo! As expected, we end up on the homepage. We can even login as the new user!

You Don’t Need isSubmitted

Head back to the controller and remove the isSubmitted() call in the if statement:

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

$form->handleRequest($request);
if ($form->isValid()) {
    // ...
}

This actually doesn’t change anything because isValid() automatically returns false if the form wasn’t submitted - meaning, if the request isn’t a POST. So either just do this, or keep the isSubmitted part in there if you want - I find it adds some clarity.

Leave a comment!

  • 2018-04-10 Ganesh Lemoius
  • 2018-04-10 Victor Bocharsky

    Hey Ganesh,

    Well, that's a bit wide question, they are kinda different. First of all, WhatsApp is a mobile application, but with FOSMessageBundle we're talking about web application based on Symfony. And we're not talking about secured end-to-end encryption with FOSMessageBundle, at least, out of the box. I suppose you know WhatsApp well, so here's a few features that FOSMessageBundle supports:

    - Support for both the Doctrine ORM and ODM for message storage
    - Threaded conversations
    - Spam detection support
    - Soft deletion of threads
    - Permissions for messaging.

    I hope this helps you to understand the difference.

    Cheers!

  • 2018-04-09 Ganesh Lemoius

    Fos Message Bundle Same as for whatsapp or its different ?

  • 2018-04-04 Victor Bocharsky

    Hey Ganesh,

    Hm, I'd like to recommend you to watch our PHP OOP courses: https://knpuniversity.com/t... - the error you mention relates to the basics of PHP. From the error, I see you're trying to instantiate an abstract class: "FOS\MessageBundle\Entity\Thread" - but PHP does not allow it. You need to extend that class with our own, probably you also will need to implement some methods, PhpStorm could suggest you to do so, and then configure your system to use your custom class instead of the abstract.

    Cheers!

  • 2018-04-03 Ganesh Lemoius

    Error: Cannot instantiate abstract class FOS\MessageBundle\Entity\Thread

    CRITICAL - Uncaught PHP Exception Symfony\Component\Debug\Exception\FatalErrorException: "Error: Cannot instantiate abstract class FOS\MessageBundle\Entity\Thread" at ..\vendor\friendsofsymfony\message-bundle\FOS\MessageBundle\ModelManager\ThreadManager.php line 24

    How to solve this error?

  • 2018-03-27 Victor Bocharsky

    Hey Ganesh,

    Looks like a Thread entity is missing metadata. I suppose if you look at Thread::$metadata field - you'll null there. Not sure what exactly you're doing when see this error, but looks like that metadata relation is required in this case. So you need to fill that in with a metadata object, I see it typehinted with "FOS\MessageBundle\Model\ThreadMetadata" class, so I suppose you should have an entity which extends this model in your system. So try to debug why that Thread entity does not have a related metadata and fix it.

    Cheers!

  • 2018-03-26 Ganesh Lemoius

    I got this error.

    Exception detected!
    [Semantical Error] line 0, col 70 near 'tm INNER JOIN': Error: Class FOS\MessageBundle\Entity\Thread has no association named metadata
    500 Internal Server Error - QueryException
    1 linked Exception: QueryException »

    [2/2] QueryException: [Semantical Error] line 0, col 70 near 'tm INNER JOIN': Error: Class FOS\MessageBundle\Entity\Thread has no association named metadata +
    [1/2] QueryException: SELECT t FROM FOS\MessageBundle\Entity\Thread t INNER JOIN t.metadata tm INNER JOIN tm.participant p WHERE p.id = :user_id AND t.isSpam = :isSpam AND tm.isDeleted = :isDeleted AND tm.lastMessageDate IS NOT NULL ORDER BY tm.lastMessageDate DESC +

    How to solve this error ?

  • 2018-03-20 Victor Bocharsky

    Hey Ganesh,

    I'm not pretty well know this bundle, I'd recommend you to ask your question in the bundle's repository, maybe someone from its maintainers or devs who use this bundle actively could help with this error.

    Cheers!

  • 2018-03-20 Victor Bocharsky

    Hey Ganesh,

    From their installation page I see:
    > Note FOSMessageBundle by default has a requirement for FOSUserBundle for some of its interfaces which can be swapped out if you're not using FOSUserBundle.

    So if you do not have FOSUserBundle, look at https://github.com/FriendsO... for more information how to avoid FOSUserBundle. FYI, FOSUserBundle provides login, register, profile show/edit, and reset password features out of the box. We also have a screencast about it: https://knpuniversity.com/s... in case you're interested in it.

    Cheers!

  • 2018-03-19 Ganesh Lemoius

    FOS Message bundle only to use our page is possible or not ?

    What Purpose to use FOSUserBundle ?

  • 2018-03-19 Victor Bocharsky

    Hey Ganesh Lemoius ,

    Looks like you have "fos_user" key in your configuration but you don't have FOSUserBundle installed. Or maybe you just didn't enable it in your "app/AppKernel.php" file (or config/bundles.php if you're on Symfony 4). Please, make sure you have FOSUserBundle installed and enabled. Try to check their installation instruction if you needed.

    Cheers!

  • 2018-03-19 Ganesh Lemoius

    FOSMessageBundle -> Controller -> inboxAction()

    $provider = $this->container->get('fos_message.provider');
    $threads = $provider->getInboxThreads();

    I have to hide this code and then open that viewpage...

    Then unhide this code come this error
    Full authentication is required to access this resource..

    How can i solve this error

  • 2018-03-19 Victor Bocharsky

    Hey Ganesh,

    I suppose you have an error working with FOSMessageBundle at some point. Could you explain a bit more, what exactly you're trying to do when you see this error and what exactly error do you see? It's difficult to say without more context. I have never used this bundle by myself, but I'd try to help you.

    Cheers!

  • 2018-03-16 Ganesh Lemoius

    FOSMESSAGEBUNDLE

    Full authentication is required to access this resource.

    InsufficientAuthenticationException: ERROR

    How To solve this

  • 2018-03-16 Ganesh Lemoius

    Full authentication is required to access this resource.
    500 Internal Server Error - InsufficientAuthenticationException
    1 linked Exception: AccessDeniedException »

    InsufficientAuthenticationException: Full authentication is required to access this resource.

    AccessDeniedException: Must be logged in with a ParticipantInterface instance

  • 2018-02-27 Victor Bocharsky

    Hey Ganesh,

    Well, if page refreshing is OK for you - I'd recommend to look at FOSMessageBundle, otherwise you can take a look at "cunningsoft/chat-bundle" package which is simple implementation. I have never used it, but looks like it allows you to chat without page refresh. If you're looking for more complex and innovative solution - probably look at NodeJS and NPM packages instead.

    Cheers!

  • 2018-02-26 Ganesh Lemoius

    Just i Want to Chat n no of user and n no of admin any reference you have for chat

  • 2018-02-26 Junaid Farooq

    Hey Victor.

    Thanks for your reply. Ye i got it and i am doing the same in my getRoles() method. I was just wondering how would a new user get a defualt role. Thanks.

    Cheers!

  • 2018-02-26 Victor Bocharsky

    Hey Junaid,

    First of all, Symfony does not care *where* you store your users and their roles: you can store it in files, in database, in cache, etc. but what Symfony do care is your User object should extend UserInterface from the core which enforce you to have getRoles() method. And that's how Symfony knows about the roles users have. So, you can store default ROLE_USER in the database for your users or always return ROLE_USER from getRoles() method like in this example: https://knpuniversity.com/s... - it's up to you. But anyways, try to follow a simple rule - always return at least one role from getRoles() - think about it like about best practice. One more time, no matter *how* you get that default role in getRoles(): hardcode it like Ryan showed in his example about or make sure all your users in the DB has at least one role - but I think the first solution is more robust.

    I hope it helps you to understand it better ;)

    Cheers!

  • 2018-02-26 Victor Bocharsky

    Hey Ganesh,

    Yes, FOSMessageBundle is a popular bundle for Symfony if you're looking for User-to-user messaging. I'm not sure, but probably this bundle is not a kind of chat application where you don't need to refresh the page to see new messages out of the box. To achieve this, you'll need to do some extra work. And unfortunately, it does not have Symfony 4 support yet, see related issue: https://github.com/FriendsO... .

    Cheers!

  • 2018-02-24 Ganesh Lemoius

    FOSMessageBundle chat application is working for symfony ?
    Give me solution for this question..

  • 2018-02-21 Junaid Farooq

    Hey weaverryan

    Thanks for your prompt reply. Yes that clarifies but i still have a doubt, ie., if the user is created without a default role assigned, will it not be blocked from accessing even the basic stuff of our site meant for everyone's use. I did see empty roles for a user from the profiler. Do we not need to set the roles on user creation or they are set automatically by Symfony by calling the getRoles() method internally. Please clarify as i am still new to Symfony. For this to work for now, i had to manually set it and i put this logic in the UserListener (created in the last episode).

    Cheers! and thanks again. :)

  • 2018-02-20 weaverryan

    Hey Junaid Farooq!

    I agree! That IS weird! However, I *might* be able to explain. Our getRoles() implementation looks like this:


    public function getRoles()
    {
    $roles = $this->roles;
    $roles[] = 'ROLE_USER';

    return array_unique($roles);
    }

    This means that:

    A) Whenever the Symfony security system calls getRoles(), the user will always *at least* have ROLE_USER
    B) BUT, this does NOT mean that the user has ROLE_USER if you look in the database. In fact, by default, in the database, this field will look empty. And... that's ok! We don't really care if it's stored in the database, because either way, the above code will guarantee that ROLE_USER is returned from this method. Of course, by calling $user->setRoles($user->getRoles())), you're causing ROLE_USER to be *set* onto the roles property, and then saved to the database. But, it's not really important.

    Does that help clarify? Or is there a different issue?

    Cheers!

  • 2018-02-20 Junaid Farooq

    Hi there,

    I don't why but i had to set the roles for the user by calling the setter method (ie., $user->setRoles($user->getRoles())) for the same in the registerAction method as the user would have an empty roles array without me setting them manually. Same existed for the LoadUsers fixture class but now that works without it. I must be missing something here.

  • 2018-02-16 Victor Bocharsky

    Hey Ganesh,

    If you're looking for support chat, here's the link: https://symfony.com/support - you can find a link to the Slack channel there.

    Cheers!

  • 2018-02-16 Ganesh Lemoius

    Symfony chat web and app if you have any reference for this one

  • 2018-02-14 Ganesh Lemoius

    thank u Victor Bocharsky
    I Completed Otp Concept....

  • 2018-02-13 Victor Bocharsky

    Hey Ganesh,

    If the question is only in how to send SMS, then you need to find an SMS service, and most probably it will be a paid service (however some of them may have free limited sms for testing). There're plenty of services who provide sending SMS features via API, but unfortunately I do not know a good one, so can't suggest you something here. But you need to find a service who provide an API and it'd be good if they also have a PHP SDK library with nice docs, so you can able to install it with Composer, register your account on their website, setup your credentials and start using it whenever you need to send SMS.

    Cheers!

  • 2018-02-12 Ganesh Lemoius

    How can i send sms for using otp ? @Victor Bocharsky
    If U have any example ?

  • 2018-02-06 Diego Aguiar

    Hey Ganesh Lemoius

    That's a great topic, you can find a lot of information, tricks, and useful tools, in our tutorials about RESTful API's https://knpuniversity.com/t...

    Cheers!

  • 2018-02-05 Victor Bocharsky

    Hey Ganesh,

    You can look at our REST track: https://knpuniversity.com/t... - if you're interested in creating REST API app

    Cheers!

  • 2018-02-03 Ganesh Lemoius

    thank you @diego
    Now it is working...
    How Can I Create Rest Api json for Web App...

  • 2018-02-03 Ganesh Lemoius

    thank u Victor Bocharsky

    How Can I Create Rest Api json for Web App...

  • 2018-01-30 Victor Bocharsky

    Hey Ganesh,

    What do you mean? You can upgrade your packages with "composer update", but first of all you need to do some tweaks for version constraints in composer.json. But of course there's could be more work. If you're really on Symfony 2.7, then we have a tutorial for you: https://knpuniversity.com/s...

    Cheers!

  • 2018-01-30 Ganesh Lemoius

    hey weaverryan
    symfony upgrade online was possible ?

    How can I Do this ?

  • 2018-01-30 weaverryan

    Hey Ganesh Lemoius!

    Hmm, it sounds like your version of Symfony might not be compatible with PHP 7. What version of Symfony are you using? If you're using 2.7.1 or older, you might need to upgrade.

    Cheers!

  • 2018-01-29 Ganesh Lemoius

    thank u weaverryan

  • 2018-01-29 weaverryan

    Hey Ganesh Lemoius!

    Are you using a Virtual machine or developing on a server that is not your local computer? If so, you should open the web/app_dev.php file and (temporary) comment out the big if block: https://github.com/symfony/.... This is a security mechanism to make sure nobody can access your dev environment on production. If you're developing from a non-local machine, you'll need to comment this out to access your dev environment.

    Cheers!

  • 2018-01-27 Ganesh Lemoius

    thank u Victor Bocharsky
    You are not allowed to access this file. Check app_dev.php for more information.
    This error come online how to rectify this error

  • 2018-01-26 Victor Bocharsky

    Hey Ganesh,

    If you want to get the current user in Twig, you can use "{{ app.user.email }}". Or you can pass "$this->getUser()" into Twig templates when render them:


    $user = $this->getUser();

    $this->render('template-name.html.twig', [
    'user' => $user,
    ]);

    And then you can call just "{{ user.email }}"

    Cheers!

  • 2018-01-26 Ganesh Lemoius

    $user = $this->getUser(); this code is not working Diego Aguiar

    I Want display current user for twig file...
    FindAll() -> dispplay all rows
    How can i get current inserting row ?

  • 2018-01-25 Diego Aguiar

    Oh, if getting the current logged in user is what you are after for, inside a controller you can do this:


    // some controller.php
    public function someAction()
    {
    $user = $this->getUser(); // If this method does not return null, then you got the logged in user
    }

    Cheers!

  • 2018-01-25 Ganesh Lemoius

    thank u @Diego Aguiar
    i don't have to get current id from new page.
    how can i change url for current user ?

    For Example

    https://knpuniversity.com ---> this is for current login page
    https://knpuniversity.com/ (current id) new update page

  • 2018-01-23 Diego Aguiar

    Hey Ganesh Lemoius

    If I understood correctly, what you want to do is to show a candidate's information based on the given ID. If I'm right you can do something like this:


    /**
    * @Route("/candidates/{id}", name="candidate_show")
    */
    public function showAction(Candidate $candidate, Request $request)
    {
    return $this->render('HomeBundle:Default:welcome.html.twig', ['candidate' => $candidate]);
    }


    This code makes use of the ParamConverter, so if the ID exists, you will get a candidate object, if it's not, a 404 error will be shown

    Cheers!

  • 2018-01-23 Ganesh Lemoius

    Thank You Victor

    I have to display current id get and then display for that all row content with including update option

    For Example
    <-- Controller Page -->

    public function JobseekerAction(Request $request) {
    $candidate = $this->getDoctrine()->getRepository('CandidateCandidateBundle:Candidateprofile')->findAll();
    dump($candidate);
    return $this->render('HomeBundle:Default:welcome.html.twig', ['candidate' => $candidate]);
    }
    <-- View Page -->

    {% for candidate in candidate %}

    <form id="form" method="POST" action="{{path('welcome_homepage')}}">

    </form>

    % endfor %}

  • 2018-01-15 Victor Bocharsky

    Hey Ganesh,

    Could you explain a bit more what you're trying to do with a little example? If you wonder how to get an ID in a controller - the most common way is getting that ID from URL, e.g. when you request a page like "/blog/25", you're requesting a post which ID is "25", so if you have a Symfony route like "/blog/{postId}", then you can request "$postId" variable in the method to get this ID:


    /**
    * @Route("/blog/{postId}")
    */
    public function showPostAction($postId)
    {
    dump($postId); die; // where $postId holds that ID, i.e. "25" in my example
    }

    I hope this example helps you.

    Cheers!

  • 2018-01-11 Ganesh Lemoius

    Hi Sir I am fresher in symfony.. I Have one doubt..How get id from controller redirecting new page to display that ID. Then i will Update current value and then new feild also update that form..

  • 2015-10-06 Shairyar Baig

    Thanks Ryan, ya i am thinking the same. I will create a new form class and use that for sorting purpose.

    Thanks for the tips :)

  • 2015-10-05 weaverryan

    Hey Shairyar!

    Yes, this is tricky: creating new Goals and allowing them to be re-ordered all at once. Typically, I avoid the collection type when things get this complicated and instead save things via AJAX (e.g. the moment you create a new goal, I save it. The moment you re-order, I save that, etc). A few things:

    1) The getId/setId() error is coming directly from you having an "id" field on your GoalType form. You should remove this, which makes sense - you don't really want the id of the Goal being changed by the user :).

    2) Very clever solution to set the orderBy - that looks good to me. I'm not sure why setting that would suddenly cause issues with sorting, however. The collection type isn't really built to handle ordering, it's possible that you could find some weird behavior with this. For example, I *think* if it lists 3 goals on the page, and you submit 3 goals, it updates the first goal in the DB with the data from the first submitted goal, etc. In other words, I think if you had 2 goals and you re-ordered them, the first would be updated with the second's data and the second with the first's data. Does that makes sense? In other words, changing the order might be causing weird issues - which is why there's no native support with "ordering" things with the collection type.

    Let me know if this helps. You're in a complicated area, and my best advice is to consider simplifying by not using the collection type :).

    Cheers!

  • 2015-10-05 Shairyar Baig

    Hi Ryan,

    I am working with Symfony Forms and jQuery sortable and ran into a weird issue, I was hoping to get your expertise as I am out of all solutions.

    I have a form (it is a collection form) and inside that form a user can change the priority of their goals, to set the priority from top to bottom I am using jQuery sortable, i am able to send the sort order to controller just fine via ajax and I am able to save the data in db just fine as well. After completing the task of sorting and all, i reloaded the page and saw even though the sort order is saved in database but the goals are actually not being displayed in the correct order, I thought this should be easy, I already have relationship setup so an `orderBy` should solve this but this is where the problem started.

    Here is the link to the yml file where i added the `orderBy`
    https://gist.github.com/sha...

    So after doing that as long as I do not sort the form, data gets saved just fine, but if i sort and then save i see the following error

    Neither the property "id" nor one of the methods "addId()"/"removeId()", "setId()", "id()", "__set()" or "__call()" exist and have public access in class "MyBundle\Entity\Goals".

    Why am I seeing this error? the only reason i am making use of Goal Entity Id is so that I know what sort order to assign to which id. https://gist.github.com/sha...

    Is it possible to display the correct order from database without using orderBy in this case? At this point I am pretty clueless as to what I am doing wrong. Any help will be really appreciated.