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.
Conclusion
- Note that the sendEmail function is a straight-forward implementation use of SwiftMailer. We've just used the implementation with Zoho Mail, if you use another email provider you need to change the SMTP address and check if your service requires SSL. You can read how to send mails from SwiftMailer to different emails providers in this article. In the function, you just need to change the mail variable and the password and you'll receive an email sent from the same direction that you receive ([email protected] sends to [email protected]).
- You can add more fields easily to your form in the FormType, to retrieve them in the sendEmail function (which becomes an array from
$form->getData
) use it's key value. - You can use Google Recaptcha in your forms too if you want to prevent robots etc. Read the following article to learn how to implement recaptcha in a Symfony 3 form.
- The use of the Symfony Form component is more reliable than implement a form by yourself without CSRF protection and it provides an easy way to handle errors.