giannisok

Contact Form tutorial

20 posts in this topic

Simple Contact Form
Using Google Recaptcha & Valitron validation library

1.png

2.png

3.png

I just finished creating a simple Contact-Form for a client's website so i thought it would be really helpfull to share it with the community.

The contact form uses:

The contact-form is located inside a contact-page, so the bare minimum you need in order to setup your own is:

  1. contact.php (template file used by your contact-page)
  2.  _contact-controller.php (file used as a controller for your contact-form functionality like send email, validate fields etc)
  3. 2 extra lines inside your composer.json file


So, let's start:

First you need to update your composer.json file adding 2 lines inside the require object:

"vlucas/valitron": "^1.2",
"google/recaptcha": "~1.1"

Here is a sample composer.json file:

{
  "name": "processwire/processwire",
  "type": "library",
  "description": "ProcessWire CMS/CMF",
  "keywords": [ "cms","cmf", "content management system" ],
  "homepage": "https://processwire.com",
  "authors": [
    {
      "name": "Ryan Cramer",
      "email": "ryan@processwire.com",
      "homepage": "https://processwire.com",
      "role": "Developer"
    }
  ],
  "require": {
    "php": ">=5.3.8",
    "ext-gd": "*",
    "vlucas/valitron": "^1.2",
    "google/recaptcha": "~1.1"
  },
  "autoload": {
    "files": [ "wire/core/ProcessWire.php" ]
  },
  "minimum-stability": "dev"
}

open console and navigate to processwire root folder (where composer.json file is)
on this step i assume you have already setup composer for your project, otherwise google it :)
run the following command:

composer update

this will create a vendor folder (if it does not already exist) and download valitron and google recaptcha libraries.

Then open your contact-page template file(usually named contact.php inside your templates directory) and add the following:
* Note: The form below uses bootstrap 3.0.0 css, so if you are using something else you need to make the appropriate changes.

<?php namespace ProcessWire;
include('_contact-controller.php')
?>
<div class="container">
	<div class="row">
		<div class=" col-md-4">
            <h2>Contact Form</h2>

            <?php if($session->flashMessage):?>
            <div class="alert <?=!$session->sent && (!$v->validate() || !$resp->isSuccess()) ? 'alert-danger' : 'alert-success'?>" role="alert">
              <?php echo $session->flashMessage;?>
            </div>
            <?php endif;?>

            <form id="contact-form" method="post">
                <div class="form-group <?=$v->errors('name') ? 'has-error' : ''?>">
                    <label for="name">Name</label>
                    <input class="form-control" name="name" id="name" type="text" value="<?=$sanitizer->text($input->post->name)?>">
                </div>
                <div class="form-group <?=$v->errors('email') ? 'has-error' : ''?>">
                    <label for="email">Email</label>
                    <input class="form-control" name="email" id="email" type="text" value="<?=$sanitizer->text($input->post->email)?>">
                </div>
                <div class="form-group <?=$v->errors('message') ? 'has-error' : ''?>">
                    <label for="message">Message</label>
                    <textarea class="form-control" name="message" id="message"><?=$sanitizer->text($input->post->message)?></textarea>
                </div>
                <div class="form-group">

                    <!-- Google Recaptcha code START -->
                    <div class="g-recaptcha" data-sitekey="<?=$googleSiteKey?>"></div>
                    <script type="text/javascript"
                            src="https://www.google.com/recaptcha/api.js">
                    </script>
                    <!-- Google Recaptcha code END -->

                </div>
                <button type="submit" class="btn btn-primary">SEND</button>
            </form>
      	</div>
    </div>
</div>
<?php
    //here we remove the flash-message because it is already shown above the form.
    $session->remove('flashMessage');
    //reset 'sent' variable for future submit
	$session->sent = false;
?>


Next create a file inside you templates directory with name: _contact-controller.php:
and set the required variables($googleSiteKey, $contactFormRecipient, $contactPageID)

<?php
namespace ProcessWire;

/**
*    here we include Valitron & Google recaptcha libraries
*    make sure the path is correct in your template
*/
include(dirname(__FILE__) . "/../../vendor/vlucas/valitron/src/Valitron/Validator.php");
include(dirname(__FILE__) . '/../../vendor/google/recaptcha/src/ReCaptcha/ReCaptcha.php');

/**
*    here we add the form field values to Valitron
*/
$v = new \Valitron\Validator(array(
        'name' => $sanitizer->text($input->post->name),
        'email' => $sanitizer->email($input->post->email),
        'message' => $sanitizer->text($input->post->message),
    )
);

/**
*    validation rules set for each form field
*    For more details on Valitron/Validator usage visit: 
*    https://github.com/vlucas/valitron
*/
$v->rule('required', ['name', 'email', 'message']);
$v->rule('lengthMin', 'name', 5);
$v->rule('email', 'email');

/**
*    set Google recaptcha site-key & secret-key
*    create a new key from: https://www.google.com/recaptcha/admin
*/
$googleSiteKey = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
$googleSecretKey = 'YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY';

/**
*    set the email of the contact form recipient(usually the website owner)
*/
$contactFormRecipient = 'your@company.com';

/**
*    set the id of contact-page in order to redirect there when the form is sent
*/
$contactPageID = '1045';

//here we check whether the 'name' field exists inside post variables (which means the form is posted)
if ($input->post->name) {

    //if fields validation passes
    if ($v->validate()) {

        $reCaptcha = new \ReCaptcha\ReCaptcha($googleSecretKey);
        $resp = $reCaptcha->verify($input->post->{'g-recaptcha-response'}, $_SERVER["REMOTE_ADDR"]);

        //if google-recaptcha validation passes
        if ($resp->isSuccess()) {
        
            //This is the HTML message
            $message = '
                <html>
                    <head>
                        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
                        <title>Contact Form | ' . $input->post->name . '</title>
                    </head>
                    <body>
                        <p>' . $input->post->message . '</p>
                    </body>
                </html>';

            //here we send the form to $contactFormRecipient
            wireMail($contactFormRecipient, $input->post->email, "Contact Form | " . $input->post->name, $message);
            
            //here we set a flash-message to notify the user that the form was successfully sent
            $session->flashMessage = 'Thank you for your message! We will get in touch with you shortly.';
            
            //save in session that the form is sent
			$session->sent = true;

            //finally redirect user to contact-page
            $session->redirect($pages->get($contactPageID)->url);
        } else {
            //self explain
            $session->flashMessage = 'Error while validating you are not a robot!';
        }
    }
}
?>

Thats all!
You now have a simple contact-form working with captcha and field validation!
I would be more than happy to help anyone having problems on the setup.
 

Edited by giannisok
add images
14 people like this

Share this post


Link to post
Share on other sites
11 hours ago, giannisok said:

You now have a simple contact-form working with captcha and field validation!
I would be more than happy to help anyone having problems on the setup.

"Valitron is a simple, minimal and elegant stand-alone validation library with NO dependencies."

That's the way I like it :) Thanks for the detailed instructions. I will probably use it in one of my projects in the near future.

Edited by szabesz
spelling
3 people like this

Share this post


Link to post
Share on other sites

@giannisok thanks for this post! though we probably need to move your post to it's own thread, as this topic is for the Module by @justb3a

 

 

Edited by SiNNuT
moved post into its own thread
1 person likes this

Share this post


Link to post
Share on other sites

Thanks for sharing! Valitron seems like a nice library to have in the toolbox.

One question: Is it necessary to define the namespace twice in contact.php?

1 person likes this

Share this post


Link to post
Share on other sites

Thanks for sharing.

I have one comment. I have a doubt about this variable :  $input->post->g-recaptcha-response - it return a PHP notice undefined constant (or I am dumb).

Share this post


Link to post
Share on other sites

And here is the ALL-IN-ONE-FILE-WITHOUT-COMMENTS version...just put this in your contact.php template file (don't forget about composer update though):

<?php
namespace ProcessWire;
include(dirname(__FILE__) . "/../../vendor/vlucas/valitron/src/Valitron/Validator.php");
include(dirname(__FILE__) . '/../../vendor/google/recaptcha/src/ReCaptcha/ReCaptcha.php');

$v = new \Valitron\Validator(array(
        'name' => $sanitizer->text($input->post->name),
        'email' => $sanitizer->email($input->post->email),
        'message' => $sanitizer->text($input->post->message),
    )
);

$v->rule('required', ['name', 'email', 'message']);
$v->rule('lengthMin', 'name', 5);
$v->rule('email', 'email');

$googleSiteKey = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
$googleSecretKey = 'YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY';
$contactFormRecipient = 'your@company.com';
$contactPageID = '1045';

if ($input->post->name) {
    if ($v->validate()) {
        $reCaptcha = new \ReCaptcha\ReCaptcha($googleSecretKey);
        $resp = $reCaptcha->verify($input->post->{'g-recaptcha-response'}, $_SERVER["REMOTE_ADDR"]);

        if ($resp->isSuccess()) {
            $message = '
                <html>
                    <head>
                        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
                        <title>Contact Form | ' . $input->post->name . '</title>
                    </head>
                    <body>
                        <p>' . $input->post->message . '</p>
                    </body>
                </html>';

            wireMail($contactFormRecipient, $input->post->email, "Contact Form | " . $input->post->name, $message);
            $session->flashMessage = 'Thank you for your message! We will get in touch with you shortly.';
			$session->sent = true;
            $session->redirect($pages->get($contactPageID)->url);
        } else {
            $session->flashMessage = 'Error while validating you are not a robot!';
        }
    }
}
?>
<div class="container">
	<div class="row">
		<div class=" col-md-4">
            <h2>Contact Form</h2>

            <?php if($session->flashMessage):?>
            <div class="alert <?=!$session->sent && (!$v->validate() || !$resp->isSuccess()) ? 'alert-danger' : 'alert-success'?>" role="alert">
              <?php echo $session->flashMessage;?>
            </div>
            <?php endif;?>

            <form id="contact-form" method="post">
                <div class="form-group <?=$v->errors('name') ? 'has-error' : ''?>">
                    <label for="name">Name</label>
                    <input class="form-control" name="name" id="name" type="text" value="<?=$sanitizer->text($input->post->name)?>">
                </div>
                <div class="form-group <?=$v->errors('email') ? 'has-error' : ''?>">
                    <label for="email">Email</label>
                    <input class="form-control" name="email" id="email" type="text" value="<?=$sanitizer->text($input->post->email)?>">
                </div>
                <div class="form-group <?=$v->errors('message') ? 'has-error' : ''?>">
                    <label for="message">Message</label>
                    <textarea class="form-control" name="message" id="message"><?=$sanitizer->text($input->post->message)?></textarea>
                </div>
                <div class="form-group">
                    <!-- Google Recaptcha code START -->
                    <div class="g-recaptcha" data-sitekey="<?=$googleSiteKey?>"></div>
                    <script type="text/javascript"
                            src="https://www.google.com/recaptcha/api.js">
                    </script>
                    <!-- Google Recaptcha code END -->
                </div>
                <button type="submit" class="btn btn-primary">SEND</button>
            </form>
      </div>
  </div>
</div>
<?php
	$session->remove('flashMessage');
	$session->sent = false;
?>
Edited by giannisok
fixed error
3 people like this

Share this post


Link to post
Share on other sites

Hello Giannisok,

at the moment i try to built my first processwire website. It's fine, but now i have problems to built a simple bootstrap form.

You have made a very interesting possibility, but is it possible to make your form without using composer in a simple way?

Many thanks

Lena

 

Share this post


Link to post
Share on other sites

Yes it is... :)

Instead of using composer just download the 2 libraries:

unzip them inside a folder

...and replace the lines:

include(dirname(__FILE__) . "/../../vendor/vlucas/valitron/src/Valitron/Validator.php");
include(dirname(__FILE__) . '/../../vendor/google/recaptcha/src/ReCaptcha/ReCaptcha.php');

with:

include(dirname(__FILE__) . "yourfolder/vlucas/valitron/src/Valitron/Validator.php");
include(dirname(__FILE__) . 'yourfolder/google/recaptcha/src/ReCaptcha/ReCaptcha.php');

Hope it helps!

Actually composer doesn't do any magic...it just downloads the libraries inside the vendor folder but you can always do it manually if you want.

2 people like this

Share this post


Link to post
Share on other sites

Thank you very much,

I did it. But know i get this warning:

Fehler: class Valitron\Validator not found.

The links are correct. Do you have any idea?

Greetings from Berlin

Lena

Share this post


Link to post
Share on other sites

Replace include with require:

require(dirname(__FILE__) . "yourfolder/vlucas/valitron/src/Valitron/Validator.php");
require(dirname(__FILE__) . 'yourfolder/google/recaptcha/src/ReCaptcha/ReCaptcha.php');

This way if the paths are not correct you will get an error...

Share this post


Link to post
Share on other sites

Thank you,

I changed my  code to require, it doesn' work. So I try it again with include. But I got the same error.

Fehler: Class 'Valitron\Validator' not found (Zeile 35 in /mnt/web116/d3/92/57789292/htdocs/processwire/site/templates/crs-contact2.php)

include(dirname(__FILE__) . 'Valitron/Validator.php');
include(dirname(__FILE__) . 'recaptcha/src/ReCaptcha/ReCaptcha.php');

Code 35:

$v = new \Valitron\Validator(array(
        'name' => $sanitizer->text($input->post->name),
        'email' => $sanitizer->email($input->post->email),
        'message' => $sanitizer->text($input->post->message),
    )
);

I tried several links to the directory, but every link output the same error. 

Have you another idea?

Thank you

Lena

Share this post


Link to post
Share on other sites

@giannisok thanks for sharing this, is awesome for a simple form where I don't need to save the user data anywhere!

Got it all working with recaptcha/validation, however, when I receive the email, it's still as plain text:

// received email
<html>
    <head>
        <meta http-equiv="Content-Type: text/html" content="text/html; charset=utf-8" />
        <title>Contact Form | Sam</title>
    </head>
    <body>
        <p>test message</p>
    </body>
</html>

Any ideas why this is? The content type is set so I thought it would show as formatted html. Thanks for any info.

 

Share this post


Link to post
Share on other sites

Thanks for this. I have done several web forms already, but captcha could be a good idea in the Future. :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.