Jump to content

Contact Form tutorial


giannisok

Recommended Posts

Hi thanks for replay , I tryed SamC version , but had constant failure loading Post class, tryed to include it manually, but didnt help so moved to latest suggestion by giannisok.

The form visually works. validates input, and shows success message on pressing send button, but no actual mail sent, anyone how to run mail server or no idea how it works here to send mail, even no logging to check it out, MOdx was much easier in this part.,

what should i install extra to send Mail????? 

----------------------------------

Installed WireMailSmtp->works!   is it the only way???

Edited by danielsl
fixed
Link to comment
Share on other sites

6 hours ago, SamC said:

@danielsl could you post the code you're using? Otherwise we're probably stabbing in the dark.

well, i rewritten it many times until stopped on the last option suggested by giannisok  so cant return back, but i had exactly same issues as discussed somewhere in the forum, that not all classes  in recaptcha were included.

anyway i try to rewrite in in uikit style and reupload it here later.

also just Wiremail doesnt work probably because i have localdevelpment server, and php mail need to be setup  somehow 

Link to comment
Share on other sites

1 hour ago, danielsl said:

well, i rewritten it many times until stopped on the last option suggested by giannisok  so cant return back

Course you can :) I do it all the time, just blank it and start again, the second time round you usually understand better.

1 hour ago, danielsl said:

anyway i try to rewrite in in uikit style and reupload it here later.

Why not just upload what you have so we can have a look? Might be something obvious.

1 hour ago, danielsl said:

also just Wiremail doesnt work probably because i have localdevelpment server, and php mail need to be setup  somehow 

My code posted earlier works for me on MAMP (macbook) and XAMPP (windows 10 desktop) without any extra modules/any tweaks to apache, nothing. Both local servers, both send email fine.

You mentioned you tried my version "but had constant failure loading Post class", I'm not sure what you mean by this.

Link to comment
Share on other sites

17 hours ago, SamC said:

Course you can :) I do it all the time, just blank it and start again, the second time round you usually understand better.

Why not just upload what you have so we can have a look? Might be something obvious.

My code posted earlier works for me on MAMP (macbook) and XAMPP (windows 10 desktop) without any extra modules/any tweaks to apache, nothing. Both local servers, both send email fine.

You mentioned you tried my version "but had constant failure loading Post class", I'm not sure what you mean by this.

np i installed previous version on live server


Fatal error: Uncaught Error: Class 'ReCaptcha\RequestMethod\Post' not found in /home/nginx/domains/expo.0dan.ru/public/site/templates/library_php/Recaptcha/src/ReCaptcha/ReCaptcha.php:74 Stack trace: #0 /home/nginx/domains/expo.0dan.ru/public/site/templates/_contact-controller.php(53): ReCaptcha\ReCaptcha->__construct('6LeDkBkUAAAAAHi...') #1 /home/nginx/domains/expo.0dan.ru/public/site/templates/contact1.php(2): include('/home/nginx/dom...') #2 /home/nginx/domains/expo.0dan.ru/public/wire/core/TemplateFile.php(268): require('/home/nginx/dom...') #3 /home/nginx/domains/expo.0dan.ru/public/wire/core/Wire.php(377): ProcessWire\TemplateFile->___render() #4 /home/nginx/domains/expo.0dan.ru/public/wire/core/WireHooks.php(698): ProcessWire\Wire->_callMethod('___render', Array) #5 /home/nginx/domains/expo.0dan.ru/public/wire/core/Wire.php(439): ProcessWire\WireHooks->runHooks(Object(ProcessWire\TemplateFile), 'render', Array) #6 /home/nginx/domains/expo.0dan.ru/public/wire/modules/PageRender.module(514): ProcessWire\Wire->__call in /home/nginx/domains/expo.0dan.ru/public/site/templates/library_php/Recaptcha/src/ReCaptcha/ReCaptcha.php on line 74
Error: Uncaught Error: Class 'ReCaptcha\RequestMethod\Post' not found in /home/nginx/domains/expo.0dan.ru/public/site/templates/library_php/Recaptcha/src/ReCaptcha/ReCaptcha.php:74
Stack trace:
#0 /home/nginx/domains/expo.0dan.ru/public/site/templates/_contact-controller.php(53): ReCaptcha\ReCaptcha->__construct('6LeDkBkUAAAAAHi...')
#1 /home/nginx/domains/expo.0dan.ru/public/site/templates/contact1.php(2): include('/home/nginx/dom...')
#2 /home/nginx/domains/expo.0dan.ru/public/wire/core/TemplateFile.php(268): require('/home/nginx/dom...')
#3 /home/nginx/domains/expo.0dan.ru/public/wire/core/Wire.php(377): ProcessWire\TemplateFile->___render()
#4 /home/nginx/domains/expo.0dan.ru/public/wire/core/WireHooks.php(698): ProcessWire\Wire->_callMethod('___render', Array)
#5 /home/nginx/domains/expo.0dan.ru/public/wire/core/Wire.php(439): ProcessWire\WireHooks->runHooks(Object(ProcessWire\TemplateFile), 'render', Array)
#6 /home/nginx/domains/expo.0dan.ru/public/wire/modules/PageRender.module(514): ProcessWire\Wire->__call (line 74 of /home/nginx/domains/expo.0dan.ru/public/site/templates/library_php/Recaptcha/src/ReCaptcha/ReCaptcha.php) 

This error message was shown because: site is in debug mode. ($config->debug = true; => /site/config.php). Error has been logged.

 

<?php
namespace ProcessWire;

/**
*    here we include Valitron & Google recaptcha libraries
*    make sure the path is correct in your template
*/
include(dirname(__FILE__) . '/library_php/Valitron/src/Valitron/Validator.php');
include(dirname(__FILE__) . '/library_php/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 = 'replaceds';
$googleSecretKey = 'replaced for forum';

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

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

//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!';
        }
    }
}
?>

 

Link to comment
Share on other sites

2 hours ago, danielsl said:

np i installed previous version on live server



Fatal error: Uncaught Error: Class 'ReCaptcha\RequestMethod\Post' not found in /home/nginx/domains/expo.0dan.ru/public/site/templates/library_php/Recaptcha/src/ReCaptcha/ReCaptcha.php:74 Stack trace: #0 /home/nginx/domains/expo.0dan.ru/public/site/templates/_contact-controller.php(53): ReCaptcha\ReCaptcha->__construct('6LeDkBkUAAAAAHi...') #1 /home/nginx/domains/expo.0dan.ru/public/site/templates/contact1.php(2): include('/home/nginx/dom...') #2 /home/nginx/domains/expo.0dan.ru/public/wire/core/TemplateFile.php(268): require('/home/nginx/dom...') #3 /home/nginx/domains/expo.0dan.ru/public/wire/core/Wire.php(377): ProcessWire\TemplateFile->___render() #4 /home/nginx/domains/expo.0dan.ru/public/wire/core/WireHooks.php(698): ProcessWire\Wire->_callMethod('___render', Array) #5 /home/nginx/domains/expo.0dan.ru/public/wire/core/Wire.php(439): ProcessWire\WireHooks->runHooks(Object(ProcessWire\TemplateFile), 'render', Array) #6 /home/nginx/domains/expo.0dan.ru/public/wire/modules/PageRender.module(514): ProcessWire\Wire->__call in /home/nginx/domains/expo.0dan.ru/public/site/templates/library_php/Recaptcha/src/ReCaptcha/ReCaptcha.php on line 74
Error: Uncaught Error: Class 'ReCaptcha\RequestMethod\Post' not found in /home/nginx/domains/expo.0dan.ru/public/site/templates/library_php/Recaptcha/src/ReCaptcha/ReCaptcha.php:74
Stack trace:
#0 /home/nginx/domains/expo.0dan.ru/public/site/templates/_contact-controller.php(53): ReCaptcha\ReCaptcha->__construct('6LeDkBkUAAAAAHi...')
#1 /home/nginx/domains/expo.0dan.ru/public/site/templates/contact1.php(2): include('/home/nginx/dom...')
#2 /home/nginx/domains/expo.0dan.ru/public/wire/core/TemplateFile.php(268): require('/home/nginx/dom...')
#3 /home/nginx/domains/expo.0dan.ru/public/wire/core/Wire.php(377): ProcessWire\TemplateFile->___render()
#4 /home/nginx/domains/expo.0dan.ru/public/wire/core/WireHooks.php(698): ProcessWire\Wire->_callMethod('___render', Array)
#5 /home/nginx/domains/expo.0dan.ru/public/wire/core/Wire.php(439): ProcessWire\WireHooks->runHooks(Object(ProcessWire\TemplateFile), 'render', Array)
#6 /home/nginx/domains/expo.0dan.ru/public/wire/modules/PageRender.module(514): ProcessWire\Wire->__call (line 74 of /home/nginx/domains/expo.0dan.ru/public/site/templates/library_php/Recaptcha/src/ReCaptcha/ReCaptcha.php) 

This error message was shown because: site is in debug mode. ($config->debug = true; => /site/config.php). Error has been logged.

 

Maybe this? http://stackoverflow.com/questions/29056472/google-recaptcha-2-fatal-error-class-recaptcha-requestmethod-post-not-found

I used composer to install my vendor packages so my \site\templates\vendor\ (on win 10) folder looks like this:

autoload.PNG.1057d77f16b789ff7457541c4d13d89f.PNG

I was hesitant at first and thought I could just download from github and put them in the right place. However, it was really quite easy to use composer and was certainly easier than manually managing this (especially with updating the packages).

I then link to the required files in my contact.php like this:

<?php namespace ProcessWire;

// /site/templates/vendor/vlucas/valitron/src/Valitron/Validator.php
wireIncludeFile("./vendor/vlucas/valitron/src/Valitron/Validator.php");
// /site/templates/vendor/google/recaptcha/src/ReCaptcha/ReCaptcha.php
wireIncludeFile("./vendor/google/recaptcha/src/ReCaptcha/ReCaptcha.php");

$googleSiteKey = 'xxxxxx';
$googleSecretKey = 'xxxxxx';

//etc...

I'm still using the version I posted earlier, the whole lot goes in a single contact.php template.

Link to comment
Share on other sites

did as you recommended, its a hell lots of work,

i included autoload.php 

require_once __DIR__ . '/autoload.php';
 

<?php

/**
 * Use to autoload needed classes without Composer.
 *
 * @param string $class The fully-qualified class name.
 * @return void
 */
spl_autoload_register(function ($class) {

    // project-specific namespace prefix
    $prefix = 'ReCaptcha\\';

    // base directory for the namespace prefix
    $base_dir = __DIR__ . '/library_php/Recaptcha/src/ReCaptcha/';

    // does the class use the namespace prefix?
    $len = strlen($prefix);
    if (strncmp($prefix, $class, $len) !== 0) {
        // no, move to the next registered autoloader
        return;
    }

    // get the relative class name
    $relative_class = substr($class, $len);

    // replace the namespace prefix with the base directory, replace namespace
    // separators with directory separators in the relative class name, append
    // with .php
    $file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';

    // if the file exists, require it
    if (file_exists($file)) {
        require $file;
    }
});

but now the form sends but have problem with wiremail and smtp server

 

Error in hnsmtp::send : 553 5.7.1 Sender address rejected: not owned by auth user.

 

pity to say its a buggy solution, so reverting to giannisok  latest version even it need extra recapture module in processwire

--------------------------

no idea how you use it. it has a lot to fix, i just found out that you wiremail call doesnt follow the api

it must be

      wireMail($input->post->email, $contactFormRecipient,  "Contact Form | " . $input->post->name, $message);
      instead of

      wireMail($contactFormRecipient,$input->post->email,  "Contact Form | " . $input->post->name, $message);

so it works, for those willing to skip such hardships, i pass in zip just working file set to use and study SamC version mail form, working one finally in uikit style, it adds itself in the footer of the latest Blog Profile. just add class (grid)to footer in _main.php

        <div id='grid' uk-grid>
 


       

working contact form.7z

Link to comment
Share on other sites

Yeah, I was using:

<?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;?>

...but of course, $resp is undefined (now I'm using the recaptcha module instead). Needs to be:

<?php if($session->flashMessage):?>
<div class="alert <?php echo $session->sent ? 'alert-success' : 'alert-danger'?>" role="alert">
    <?php echo $session->flashMessage;?>
</div>
<?php endif;?>

So, validation works, recaptcha works, but now the mail wont send - "Mail not sent. Error occured."

Anyway, I'll look into it tomorrow, 21:30 here on Friday night, time to chill out for a bit :) 

Link to comment
Share on other sites

Ok, I'm not so good at shutting down and 'turning off' when there's a problem to be solved. So my emails are sending now, I get the success message, but no emails! So I even went as far as messing about in php.ini to enable the sendmail, it's off by default in MAMP (free) but switchable via the UI in MAMP (paid).

So I did this: http://www.blog.tripleroi.com/2012/05/solvedenabling-sendmail-on-localhost.html

Tried again, no luck. Then noticed I had 16 emails in my SPAM folder! Lesson learned. Here's my rendition of contact.php, just a single file, using the MarkupGoogleRecaptcha module, works locally (validates form/validates recaptcha, and sends email correctly):

// contact.php
<?php namespace ProcessWire;

wireIncludeFile("./vendor/vlucas/valitron/src/Valitron/Validator.php");
$captcha = $modules->get("MarkupGoogleRecaptcha");

$contactPageID = '1022';
$contactFormRecipient = 'my_email';

$name = $sanitizer->text($input->post->name);
$email = $sanitizer->email($input->post->email);
$message = $sanitizer->text($input->post->message);

$v = new \Valitron\Validator(array(
    'name' => $name,
    'email' => $email,
    'message' => $message
    )
);

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

if ($input->post->sendMe) {
    if ($v->validate()) {
        if ($captcha->verifyResponse() === true) {

            $message = "
                <html>
                    <body>
                        <p><b>From:</b></p>
                        <p>{$name}</p>
                        <p><b>Email:</b></p>
                        <p>{$email}</p>
                        <p><b>Message:</b></p>
                        <p>{$message}</p>
                    </body>
                </html>
                ";

            $mail = wireMail();

            $mail->to($contactFormRecipient)
            ->from($email)
            ->subject('Contact form submission')
            ->bodyHTML($message)
            ->send();


            if ($mail->send()) {
                $session->flashMessage = "<h2>Thank you for your message! I will get back to you shortly.</h2>";
                $session->sent = true;
                $session->redirect($pages->get($contactPageID)->url);
            }
            else {
                $session->flashMessage = "<h2>Mail not sent. Error occured.</h2>";
            }

        }
        else {
            $session->flashMessage = '<h2>Recaptcha must be complete.</h2>';
        }
    }
    else {
        $session->flashMessage = '<h2>Please fill out the fields correctly.</h2>';
    }
}
?>

<div class="body-row">
    <div class="wrapper">

        <?php if($session->flashMessage):?>
        <div class="alert <?php echo $session->sent ? 'alert-success' : 'alert-danger'?>" role="alert">
            <?php echo $session->flashMessage;?>
        </div>
        <?php endif;?>

        <form id="contact-form" method="post">
            <div class="<?php echo $v->errors('name') ? 'has-error' : ''?>">
                <label for="name">Name (required)</label>
                <input class="form-control" name="name" id="name" type="text" value="<?php echo $sanitizer->text($input->post->name)?>">
            </div>
            <div class="<?php echo $v->errors('email') ? 'has-error' : ''?>">
                <label for="email">Email (required)</label>
                <input class="form-control" name="email" id="email" type="text" value="<?php echo $sanitizer->text($input->post->email)?>">
            </div>
            <div class="<?php echo $v->errors('message') ? 'has-error' : ''?>">
                <label for="message">Message (required)</label>
                <textarea class="form-control" name="message" id="message"><?php echo $sanitizer->text($input->post->message)?></textarea>
            </div>
            <div>
                <!-- Google Recaptcha code START -->
                <?php echo $captcha->render()?>
                <!-- Google Recaptcha code END -->
            </div>

            <div class="centered">
                <button type="submit" name="sendMe" value="1">SEND MESSAGE</button>
            </div>
        </form>

    </div>
</div>

<?php
    $session->remove('flashMessage');
    $session->sent = false;
    echo $captcha->getScript();
?>

Big thanks to @giannisok for the original ideas :)

@danielsl maybe you could try this to see if you have more luck?

It's been a great learning experience so far, so thanks all.

  • Like 1
Link to comment
Share on other sites

  • 5 months later...
  • 1 month later...

Great contact form.

I have a question about it.

When submitting the form and you forget a field it reloads to the beginning of the page.

Is there a way that when reloading/submitting the form, you will go directly to the form section again?

 

For example, i want to put the contact form in the footer. But I get redirected to the top of the page everytime i click submit.

I use iframe for now, but maybe there is also another solution?

 

Thank you!

Link to comment
Share on other sites

16 minutes ago, Missariella said:

Great contact form.

I have a question about it.

When submitting the form and you forget a field it reloads to the beginning of the page.

Is there a way that when reloading/submitting the form, you will go directly to the form section again?

 

For example, i want to put the contact form in the footer. But I get redirected to the top of the page everytime i click submit.

I use iframe for now, but maybe there is also another solution?

 

Thank you!

@Missariella I needed to do this the other day:

Instead of:

$session->redirect($pages->get($contactPageID)->url);

I used:

// above form
<div id="form-top"></div>

// redirect to anchor tag after submit
$session->redirect($pages->get($contactPageID)->url . "#form-top");

Works great, and no need for iframe :)

  • Like 2
Link to comment
Share on other sites

Wow fast answer! Thanks!

After submitting it redirects :)

 

But I also want it to redirect after someone forgot a field.

I used  the same code after the last flashmessage but it works partly.

 

It redirects back but saves the form input only when all is filled out (except for the recaptcha ofcourse).

If one required field is forgotten everything is blank again after redirecting. 

 

Any ideas for that?

Thanks

  • Like 1
Link to comment
Share on other sites

Try putting the sanitized data as the value

Looking at the input fields specifically:

 <input type="email" class="form-control" name="inputEmail" placeholder="Email" value="<?= $email; ?>">

Link to comment
Share on other sites

 Alright, I put the name field in the sessions and show it in the input field

$session->name = $sanitizer->text($input->post->name); 

value="<?php echo $session->name; ?>">

 

It shows again after reload and updates etc.

But it's also visible when refreshing the homepage for example. (i put the contact form in the footer, so it's always visible).

Anyway, It shows the last filled in data, instead of being blank after a normal page refresh.

 

 

Link to comment
Share on other sites

On the phone atm. My post from above doesn't store in session:

// sanitize input field values
    $user = $sanitizer->userName($input->post->inputUsername);

value="<?php echo $user; ?>"

Try without session. My form is only on one page, however, the values don't remain after navigating away them back.

Link to comment
Share on other sites

8 hours ago, Missariella said:

It shows again after reload and updates etc.

That is the expected behavior of the session API variable. ;)

8 hours ago, SamC said:

$user = $sanitizer->userName($input->post->inputUsername);

It would be best not to use the user variable, because it is a reserved variable. Better would be to just name it something like for example $name. If you get the post value of the input field by the same name after submitting the form, the value should only be outputted for only one page load.

  • Like 1
Link to comment
Share on other sites

3 hours ago, AndZyk said:

It would be best not to use the user variable, because it is a reserved variable. Better would be to just name it something like for example $name. If you get the post value of the input field by the same name after submitting the form, the value should only be outputted for only one page load.

Yes, wasn't the best example :P I didn't know it was a reserved word at the time and had changed it since.

@Missariella I'm with you now on your issue. I have the same with the redirect, just never noticed, works fine without it. I tried some jQuery to redirect after form submit but I'm not sure how to do this with PHP tbh. Probably need another member to chime in here.

I tested by:

print_r($v->data()); // Array ( [name] => Sam [email] => [message] => )
$session->flashMessage = 'Please fill out the fields correctly.';

...then:

print_r($v->data()); // no output
$session->flashMessage = 'Please fill out the fields correctly.';
$session->redirect($pages->get($contactPageID)->url . "#form-top");

So I'm stuck too basically.

==EDIT==

Just had a thought. Maybe you could add the sanitized values to the whitelist, then retrieve them from that when required:

https://processwire.com/api/ref/input/whitelist/

I used this to remember values from a bunch of select lists which then had to be displayed after a form submit (which went to a different page).

  • Like 1
Link to comment
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
×
×
  • Create New...