Symfony 3 Form Validation BotDetect CAPTCHA Example

First Time Here?

Check the BotDetect Symfony 3 Captcha Quickstart for key integration steps.

Symfony Form Validation BotDetect CAPTCHA Example shows how to integrate CaptchaBundle in a form. We have also demonstrated how to create the ValidCaptcha constraint in order to validate captcha code user submits.

The brief example is based around a contact form which sends email if user input is considered valid -– a likely real world scenario for Captcha protection integration.

Files for this ('bd-captcha-symfony3-examples') example are:

All files are available for download as a part of the BotDetect Captcha Symfony integration package.

Symfony 3 Contact BotDetect Captcha validation screenshot

Config - /app/config/captcha.php

<?php if (!class_exists('CaptchaConfiguration')) { return; } 

// BotDetect PHP Captcha configuration options 

return [ 
  // Captcha configuration for contact page 
  'ContactCaptcha' => [ 
    'UserInputID' => 'captchaCode', 
    'CodeLength' => CaptchaRandomization::GetRandomCodeLength(4, 6), 
    'ImageStyle' => ImageStyle::AncientMosaic, 
  ], 

]; 

In order to use the CaptchaBundle, we have defined Captcha configuration which will be used as a CaptchaType in ContactType form. Detailed description of this approach is available in a BotDetect Symfony 3 integration guide.

Type - /src/AppBundle/Form/Type/ContactType.php

<?php 

namespace AppBundle\Form\Type; 

use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilderInterface; 
use Symfony\Component\Form\Extension\Core\Type\EmailType; 
use Symfony\Component\Form\Extension\Core\Type\SubmitType; 
use Symfony\Component\Form\Extension\Core\Type\TextareaType; 
use Symfony\Component\Form\Extension\Core\Type\TextType; 
// Importing the CaptchaType class 
use Captcha\Bundle\CaptchaBundle\Form\Type\CaptchaType; 

class ContactType extends AbstractType 
{ 
  public function buildForm(FormBuilderInterface $builder, array $options) 
  { 
    $builder 
      ->add('name', TextType::class) 
      ->add('email', EmailType::class) 
      ->add('subject', TextType::class) 
      ->add('message', TextareaType::class) 
      ->add('captchaCode', CaptchaType::class, array( 
        'captchaConfig' => 'ContactCaptcha', 
        'label' => 'Retype the characters from the picture' 
      )) 
      ->add('submit', SubmitType::class) 
    ; 
  } 
} 

The above code uses the CaptchaType to add Captcha to contact form. It is required to declare captchaConfig option and assign it a captcha configuration variable defined in app/config/captcha.php file.

Entity - /src/AppBundle/Entity/Contact.php

<?php namespace AppBundle\Entity; 

use Symfony\Component\Validator\Constraints as Assert; 
use Captcha\Bundle\CaptchaBundle\Validator\Constraints as CaptchaAssert; 

class Contact 
{ 
  /** 
   * @Assert\Length( 
   *      min = 2, 
   *      max = 10, 
   *      minMessage = "Your name must be at least {{ limit }} characters long", 
   *      maxMessage = "Your name cannot be longer than {{ limit }} characters" 
   * ) 
   */ 
  protected $name; 

  /** 
   * @Assert\Email( 
   *      message = "The email '{{ value }}' is not a valid email.", 
   * ) 
   */ 
  protected $email; 

  /** 
   * @Assert\Length( 
   *      min = 1, 
   *      max = 50, 
   *      minMessage = "Your subject must be at least {{ limit }} characters long", 
   *      maxMessage = "Your subject cannot be longer than {{ limit }} characters" 
   * ) 
   */ 
  protected $subject; 

  /** 
   * @Assert\Length( 
   *      min = 2, 
   *      max = 255, 
   *      minMessage = "Your message must be at least {{ limit }} characters long", 
   *      maxMessage = "Your message cannot be longer than {{ limit }} characters" 
   * ) 
   */ 
  protected $message; 

  /** 
   * @CaptchaAssert\ValidCaptcha( 
   *      message = "CAPTCHA validation failed, try again." 
   * ) 
   */ 
  protected $captchaCode; 

  public function getCaptchaCode() 
  { 
    return $this->captchaCode; 
  } 

  public function setCaptchaCode($captchaCode) 
  { 
    $this->captchaCode = $captchaCode; 
  } 

  public function getName() 
  { 
    return $this->name; 
  } 

  public function setName($name) 
  { 
    $this->name = $name; 
  } 

  public function getEmail() 
  { 
    return $this->email; 
  } 

  public function setEmail($email) 
  { 
    $this->email = $email; 
  } 

  public function getSubject() 
  { 
    return $this->subject; 
  } 

  public function setSubject($subject) 
  { 
    $this->subject = $subject; 
  } 

  public function getMessage() 
  { 
    return $this->message; 
  } 

  public function setMessage($message) 
  { 
    $this->message = $message; 
  } 
} 

To validate the captchaCode field in contact form, we have added the ValidCaptcha constraint to Contact Entity.

Controller - /src/AppBundle/Controllers/ContactController.php

<?php 

namespace AppBundle\Controller; 

use AppBundle\Entity\Contact; 
use AppBundle\Form\Type\ContactType; 
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; 
use Symfony\Component\HttpFoundation\Request; 
use Symfony\Bundle\FrameworkBundle\Controller\Controller; 

class ContactController extends Controller 
{ 
  /** 
   * @Route("/contact") 
   */ 
  public function getForm(Request $request) 
  { 
    // create contact form 
    $contactForm = $this->createForm(ContactType::class, new Contact()); 

    // initially, the message shown to the visitor is empty 
    $message = ''; 

    $contactForm ->handleRequest($request); 
    if ($contactForm->isValid()) { 
      // Captcha validation passed 
      // TODO: send email 
      $message = 'Your message was sent successfully.'; 
    } 

    return $this->render('AppBundle:Contact:contact.html.twig', array( 
      'form' => $contactForm->createView(), 
      'message' => $message 
    )); 
  } 
} 

When user submits a valid captcha code, isValid() returns true. Before redirecting user, it is possible to perform some actions using the $contactForm object. Code above assigns a success message to the $message variable which will be displayed on a contact page.

View - /src/AppBundle/Resources/views/Contact/contact.html.twig

<!DOCTYPE html> 
<html> 
<head> 
  <title>Symfony 3 Form Validation BotDetect CAPTCHA Example</title> 
</head> 

<body> 
  <h2>Symfony 3 Form Validation BotDetect CAPTCHA Example</h2> 
  
  {# show message #} 
  {% if message is not empty %} 
    <p>{{ message }}</p> 
  {% endif %} 
  
  {{ form_start(form) }} 
  {{ form_widget(form) }} 
  {{ form_end(form) }} 
</body> 
</html> 

The form has already been created, the next step is render it by using a set of forms helper functions, and to prints out a message (set in Controller) about Captcha validation success.