Laravel PHP

Fortifying Laravel Contact Forms: Dynamic reCAPTCHA and Streamlined Handling

Contact forms are the lifeblood of many websites, acting as a direct channel for user inquiries and feedback. However, they're also a prime target for spam and bots, making robust validation crucial. On our landing project, which serves as our primary public-facing portal, we recently undertook a significant refactor to enhance our contact message handling, with a particular focus on dynamic reCAPTCHA validation and a smoother user experience.

The Challenge: Balancing Security and UX

Our previous contact form setup, while functional, presented a few areas for improvement. reCAPTCHA validation, a critical defense against spam, was somewhat static. When validation failed, the user feedback wasn't always as clear as it could be, leading to frustration. On the backend, the message handling and email notification processes had room for streamlining to improve maintainability and developer experience.

Dynamic Validation for a Smarter Form

The core of this refactor involved making our reCAPTCHA validation more dynamic and configurable. Instead of hardcoding validation rules, we now leverage Laravel's FormRequest capabilities to apply reCAPTCHA rules based on application configuration. This allows for greater flexibility, enabling us to adjust sensitivity or even disable reCAPTCHA for specific environments without code changes.

Simultaneously, we've implemented multi-language user feedback for reCAPTCHA errors. Now, when a bot or an invalid submission is detected, users receive clear, localized messages, guiding them toward a successful submission or informing them of the issue.

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

class StoreContactRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true;
    }

    public function rules(): array
    {
        $rules = [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'email', 'max:255'],
            'message' => ['required', 'string'],
        ];

        // Dynamically add reCAPTCHA validation if enabled in configuration
        if (config('services.recaptcha.enabled')) {
            $rules['g-recaptcha-response'] = ['required', 'recaptcha'];
        }

        return $rules;
    }

    public function messages(): array
    {
        return [
            'g-recaptcha-response.required' => __('contact.recaptcha_required'),
            'g-recaptcha-response.recaptcha' => __('contact.recaptcha_failed'),
        ];
    }
}

Streamlined Message Handling

Beyond validation, we've refined the ContactController to simplify the message storage and notification logic. The process for saving a new contact message and sending an internal notification email has been condensed, reducing boilerplate and improving readability. The ContactMessageMail mailable class was also simplified, focusing on essential data to construct the email.

Additionally, to provide better context for internal administrators, we've integrated a referrer field. This field, visible only to super admin users, helps in understanding the source of inquiries, aiding in analytics and user journey mapping.

The Outcome

These changes result in a more robust, user-friendly, and maintainable contact form system. Users benefit from clearer feedback and a more reliable submission process, while administrators gain better insights and a streamlined backend for managing inquiries. By focusing on dynamic validation and efficient data flow, we've ensured our landing project's contact form remains a strong, secure communication channel.

GERARDO RUIZ

GERARDO RUIZ

Author

Share: