Learn how to create a contact form easily in Symfony 3 with FormType.

Dealing with HTML forms is one of the most common and challenging tasks for a web developer. Symfony integrates a Form component that makes dealing with forms easy.

In this article, you'll learn how to create a basic contact form in Symfony 3 using the FormBuilder and SwiftMailer to send the Email.

Requirements

  • Symfony 3.
  • SwiftMailer Bundle (which comes usually pre-installed and all the symfony distributions).

Implementation

The use of a FormType is encouraged as it is the correct workflow when using Symfony. It will help you to deal easily with the customization of errors, properties easily.

Creating a FormType for the contact form

The following class contains the ContactType class which will be used to create the form in the controller later.

<?php
// your-path-to-types/ContactType.php

namespace myapplication\myBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\NotBlank;

class ContactType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name', TextType::class, array('attr' => array('placeholder' => 'Your name'),
                'constraints' => array(
                    new NotBlank(array("message" => "Please provide your name")),
                )
            ))
            ->add('subject', TextType::class, array('attr' => array('placeholder' => 'Subject'),
                'constraints' => array(
                    new NotBlank(array("message" => "Please give a Subject")),
                )
            ))
            ->add('email', EmailType::class, array('attr' => array('placeholder' => 'Your email address'),
                'constraints' => array(
                    new NotBlank(array("message" => "Please provide a valid email")),
                    new Email(array("message" => "Your email doesn't seems to be valid")),
                )
            ))
            ->add('message', TextareaType::class, array('attr' => array('placeholder' => 'Your message here'),
                'constraints' => array(
                    new NotBlank(array("message" => "Please provide a message here")),
                )
            ))
        ;
    }

    public function setDefaultOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'error_bubbling' => true
        ));
    }

    public function getName()
    {
        return 'contact_form';
    }
}

Note: change the namespace according to the location of the FormType in your bundle and save it to use it in the next step.

Creating the view in Twig

Now, the view (in this case that will be rendered via twig), should be basic to test :

{# contact.html.twig #}

{{ form_start(form) }}

    <div>
        {{ form_widget(form.subject) }}
        {{ form_errors(form.subject) }}
    </div>
    <div>
        {{ form_widget(form.name) }}
        {{ form_errors(form.name) }}
    </div>
    <div>
        {{ form_widget(form.email) }}
        {{ form_errors(form.email) }}
    </div>
    <div>
        {{ form_widget(form.message) }}
        {{ form_errors(form.message) }}
    </div>

    {# Render CSRF token etc .#}
    <div style="display:none">
        {{ form_rest(form) }}
    </div>
    
    <input type="submit" value="Submit">
    
{{ form_end(form) }}

Creating the controller

Now, comes the most important point in the tutorial, the controller that will handle our form.

As usual, your action in the controller should already have a path in the routing.yml file and it targets to it :

myapplication_contact:
    path:     /contact
    defaults: { _controller: myBundle:Default:contact }

Finally, our controller (with the contact action) should look like :

<?php

namespace myapplication\myBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;

class DefaultController extends Controller
{
    public function contactAction(Request $request)
    {
        // Create the form according to the FormType created previously.
        // And give the proper parameters
        $form = $this->createForm('myapplication\myBundle\Form\ContactType',null,array(
            // To set the action use $this->generateUrl('route_identifier')
            'action' => $this->generateUrl('myapplication_contact'),
            'method' => 'POST'
        ));

        if ($request->isMethod('POST')) {
            // Refill the fields in case the form is not valid.
            $form->handleRequest($request);

            if($form->isValid()){
                // Send mail
                if($this->sendEmail($form->getData())){

                    // Everything OK, redirect to wherever you want ! :
                    
                    return $this->redirectToRoute('redirect_to_somewhere_now');
                }else{
                    // An error ocurred, handle
                    var_dump("Errooooor :(");
                }
            }
        }

        return $this->render('myBundle:Default:contact.html.twig', array(
            'form' => $form->createView()
        ));
    }

    private function sendEmail($data){
        $myappContactMail = '[email protected]';
        $myappContactPassword = 'yourmailpassword';
        
        // In this case we'll use the ZOHO mail services.
        // If your service is another, then read the following article to know which smpt code to use and which port
        // http://ourcodeworld.com/articles/read/14/swiftmailer-send-mails-from-php-easily-and-effortlessly
        $transport = \Swift_SmtpTransport::newInstance('smtp.zoho.com', 465,'ssl')
            ->setUsername($myappContactMail)
            ->setPassword($myappContactPassword);

        $mailer = \Swift_Mailer::newInstance($transport);
        
        $message = \Swift_Message::newInstance("Our Code World Contact Form ". $data["subject"])
        ->setFrom(array($myappContactMail => "Message by ".$data["name"]))
        ->setTo(array(
            $myappContactMail => $myappContactMail
        ))
        ->setBody($data["message"]."<br>ContactMail :".$data["email"]);
        
        return $mailer->send($message);
    }
}

The contactAction is a normal and typical symfony 3 Form. It validates if the form has been submitted with the POST method, then it checks if the given constraints given in the ContactType are correct. If they're valid, proceed to send the email using the sendEmail function.

FormType symfony 3

Conclusion


Senior Software Engineer at Software Medico. Interested in programming since he was 14 years old, Carlos is a self-taught programmer and founder and author of most of the articles at Our Code World.

Sponsors