Tutorial on Form Validation & Emailing?


#1

Hi all! I know that Kirby has a validation class, and also an emailing helper function, but the docs are a bit too basic for a newbie… :cry:

Has anyone written a step-by-step “for dummies” lesson on how to get, let’s say, a simple site ‘Contact Form’ working, with validation and emailing?

Any guidance would be extremely welcome.


#2

You should have a look at the Uniform plugin: https://github.com/mzur/kirby-uniform

It makes creating contact forms a breeze!


#3

If you don’t want to use the Uniform plugin, have a look at this example contact form by @bastianallgeier https://gist.github.com/bastianallgeier/c396df7923848912393d. It’s not a tutorial but a starting point …


#4

Check out this blog post. It’s a step-by-step tutorial on how to implement a contact form using the Uniform plugin.


#5

@texnixe thank you so much - that’s exactly what I needed! :smile:

I did have a good look at the Uniform plugin. It looks fantastic - quite powerful and flexible - but unfortunately it requires us to turn on multi-language options on the site (even if it’s a single-language site), which I really don’t want to do.

Thank you all for your guidance - it’s truly appreciated!


#7

@texnixe I find that I keep going back to @bastianallgeier’s old email controller all the time, for its simplicity… It should be added to the docs, as a Contact Form ‘solution’.

I’m currently working on a project that has a contact form inside a modal dialogue. I’d like to be able to submit the form and update the interface without closing the modal - i.e, via ajax. Is there a step-by-step tutorial on how to do this? - i.e., how to submit a contact form via ajax in Kirby?..


#8

No, there is no tutorial. But basically, submitting a form via ajax is no different than any other ajax call and all not very Kirby specific.

We will certainly start adding tutorials at one point or the other; currently, we are still updating the Cheat Sheet to include all missing methods and with more examples; all this takes up a lot of time, given that we are not working full time on this - or at least not officially :wink:


#9

Your work is truly appreciated - thank you!


#10

There is a tutorial for Uniform on using AJAX with forms that will probably be helpful when you use the simple email controller, too :wink: It’s basically just a matter of how to set up the JSON communication between the JS of the form and the Kirby controller.


#11

@luxlogica: I was about to modify the Uniform plugin to not require the multi-language option for a project I’m working on, when I realized that it has recently been updated. Now, you can simply set a language in your config file, no need to turn on multi-language anymore.

Thanks, @mzur :slight_smile:


#12

Thank you all for giving me hints and tips - it has been very helpful, indeed.
In order to help other newbies, I’ll document here what my current steps are for getting an ajax-based contact form going in Kirby. For someone new to web development getting this going can seem daunting, so hopefully this guide - of sorts - might help… The end result is that we can have a form processor without having to add extra template/snippet/controller/content pages - it’s all done with a route and a plugin.

The code here is built from several different sources, including a post from @Targoran, hints by @texnixe and @mzur, code from @bastianallgeier and guidance from @distantnative. Also, had to do quite a bit of research on GitHub and StackOverflow, to make sure the code was reasonably sound. So, here goes.

Follow these 4 steps:

Step 1

Place the following lines in your site’s ‘config.php’, to create a form-processing route:

c::set('routes', array(
  array(
    // in 'pattern', enter the same url being called from your ajax javascript function
    'pattern' => 'api/form',
    'method' => 'POST',
    'action' => function() {
      // check whether this is an ajax request, and respond with an error if it isn't
      if(!kirby()->request()->ajax()){ return response::error("Page Not Found!","404");}
      // process the form data, send the email - and get the result (as an array)
      $data = mailFormData(kirby()->request()->data());
      // respond with the result - in JSON format
      return response::json($data);
      }
    )
));

Step 2

In one of your templates or snippets, setup a contact form - such as the one below:

<form id="my-form">
    
    <!-- for displaying the results of the sending operation -->
    <span class="form-result"></span>
    
    <label for="my-form-name">Your Name*</label>
    <input type="text" name="name" id="my-form-name" required>
    
    <label for="my-form-email">Your Email*</label>
    <input type="email" name="email" id="my-form-email" required>
    
    <label for="my-form-phone">Your Phone</label>
    <input type="tel" name="phone" id="my-form-phone">
    
    <!-- a 'honeypot' field, to help us detect spam bots (use css to hide it) -->
    <input type="text" name="website" id="my-form-website" value="" class="hidden">
    
    <label for="my-form-message">Your Message</label>
    <textarea name="message" id="my-form-message" rows="9"></textarea>
    
    <button type="submit" name="submit">Send</button>
    
</form>

You can add or remove fields to your form, as you wish. You should also add css classes to its elements, and style the form according to your requirements.

Step 3

In your form template/snippet, right after your form element, place the following javascript:

<script>
    // AJAX FORM PROCESSING
    $('#my-form').on('submit', function(e){
        e.preventDefault();
        var form = $(this);
        $.ajax({
            type: 'POST',
            // use the same url here as the 'pattern' in your route
            url: 'api/form',
            data: form.serialize(),
            success: function(result){
                // form data successfully reached form processor api
                if(result.success){
                    // message successfully sent
                    form.find('.form-result').text('Your message was sent successfully - thank you!');
                } else {
                    // an issue was encountered
                    if(result.errors == undefined || result.errors == null || result.errors.length == 0){
                        // no validation errors - an email sending error was encountered
                        form.find('.form-result').text(result.msg);
                    } else {
                        // a validation error was encountered
                        var msg = "Please note: <br>";
                        if(result.errors.indexOf('name') != -1){ 
                            msg += "Name field must not be empty. <br>";
                         }
                        if(result.errors.indexOf('email') != -1){ 
                            msg += "Email field must contain a valid email. <br>";
                        }
                        if(result.errors.indexOf('website') != -1){ 
                            msg += "You seem to be a robot. <br>";
                        }
                        form.find('.form-result').html(msg);
                    }
                }
            },
            error: function(result){
                // the form was unable to reach processor api
                form.find('.form-result').text('Error '+ result.status + ' - unable to process form: ' + result.statusText);
            },
            dataType: 'json'
        });
    });
</script>

Note that the javascript above uses jQuery.

Step 4

In your ‘site/plugins’ folder, create another folder called ‘mail-form-data’. Inside that folder, create a new document, and call it ‘mail-form-data.php’. Inside this document, place the following PHP function, and customise it to suit!:

<?php

function mailFormData($data) {
    // $data (array) contains the form's sent data
    $name = $data['name'];
    $email = $data['email'];
    $phone = $data['phone'];
    $website = $data['website'];
    $message = $data['message'];
    
    // perform form data validation - we can use Kirby's validators,
    // available via "v":
    $errors = array();
    
    if(empty(trim($name))){ $errors[] = 'name'; }
    if(!v::email($data['email'])) { $errors[] = 'email'; }
    if(!empty($website)){ $errors[] = 'website'; }
    
    $result = array();
    $result['errors'] = $errors;
    
    // if we have validation errors, we can stop and return them:
    if(!empty($errors)){
        $result['success'] = false;
        $result['msg'] = 'Validation Failed';
        return $result;
    }
    
    // if we have no errors, we can go ahead and build an email message.
    // $to, $from and $subject can be hard-coded here, or can alternatively
    // be retrieved from values entered by the user in a page:
    $to = 'recipient@example.com';
    $from = $email;
    $subject = 'Message From Your Website';
    $body = <<<BODY

From: {$name}
--------------------------------------------------------
Email: {$email}
--------------------------------------------------------
Phone: {$phone}
--------------------------------------------------------
Message:

{$message}
BODY;
    
    // now, let's try sending the email:
    $email = email(array('to' => $to,'from' => $from,'subject' => $subject,'body' => $body));
    if($email->send()){
        // email was sent successfully
        $result['success'] = true;
        $result['msg'] = "Email sent successfully.";
    } else {
        // email delivery was not successful - report error
        $result['success'] = false;
        $result['msg'] = 'Email Delivery Failed: ' . $email->error()->message();
    }
    
    return $result;
}

Please be aware that it’s likely that this code still has errors, and can be optimised. Hopefully others will continue to tip in and improve on it!


How to create a newsletter subscription form using Uniform & Mailchimp?
How to create a newsletter subscription form using Uniform & Mailchimp?
How to create a newsletter subscription form using Uniform & Mailchimp?
How to create a newsletter subscription form using Uniform & Mailchimp?
#13

Hey guys, is this the best practice to do e-mail forms in Kirby? If yes - where do the user e-mails go to when they submit the form?


#14

It depends what your needs are. I would definitely recommend using the Uniform plugin. The form submissions can sent to you as an email, or you can log them to a file on the server, or store them in a database… or all three :slight_smile:

Kirby does have a built in email class if you don’t want to use the plugin, but i have never used it so cant help much other then point you at the docs for it.


#15

If you are not familiar with PHP form handling, use the Uniform plugin. It implements some best practices, including CSRF tokens, the Post-Redirect-Get pattern, a honeypot etc. and has actions for common form actions like uploading, sending email…


#16

If it’s only to send emails I’ve already created a “mini plugin” for Kirby 2 with the help of @bastianallgeier.
No ajax, with honeypot.