2

My code was checked and seems OK so maybe the problem lies in the htaccess file whose content on my online server is:

SetEnv PHP_VER 5_4
Options -Indexes
ErrorDocument 404 /index.php
RewriteEngine on 
RewriteCond %{HTTP_HOST} !^www.example.fr$
RewriteRule ^(.*)   http://www.example.fr/$1  [QSA,L,R=301] 

Any reason why this htaccess would prevent forms from submitting correctly on my site?

Just in case here's my code:

<form id='contact_form_mmt' action='<?php echo bloginfo("wpurl"); ?>/contact' method='post'>
  <input type='text' name='contact_nom' placeholder='Votre nom *' data-validation='length' data-validation-length='min3' data-validation-error-msg='<?php echo $text_too_short_or_empty; ?>'>  
  <input type='text' name='contact_prenom' placeholder='Votre prénom *' data-validation='length' data-validation-length='min3' data-validation-error-msg='<?php echo $text_too_short_or_empty; ?>'>
  <input type='text' name='contact_mail' placeholder='Votre mail *' data-validation='email' data-validation-length='min3' data-validation-error-msg='<?php echo $email_valid; ?>'>
  <select name='contact_destinataire'>
    <option value="contact@example.com|Information générales">Information générales</option>
    <option value="webmaster@example.fr|Problèmes liés au site">Problèmes liés au site</option>
  </select>
  <textarea name='contact_message' placeholder='Message *'data-validation='length' data-validation-length='min3' data-validation-error-msg='<?php echo $text_too_short_or_empty; ?>'></textarea>  
  <input type='hidden' name='sub' value='1'>  
  <input type='submit' value='envoyer'>
</form>

PHP (I know the syntax is ugly, I'll improve that):

if ( isset($_POST['sub']) ) $sub = $_POST['sub']; else $sub = ''; 
if ( isset($_POST['contact_nom']) ) $contact_nom = $_POST['contact_nom']; else $contact_nom = ''; 
if ( isset($_POST['contact_prenom']) ) $contact_prenom = $_POST['contact_prenom' ]; else $contact_prenom = ''; 
if ( isset($_POST['contact_mail']) ) $contact_mail = $_POST['contact_mail']; else $contact_mail = ''; 
if ( isset($_POST['contact_sujet']) ) $contact_sujet = $_POST['contact_sujet']; else $contact_sujet = ''; 
if ( isset($_POST['contact_destinataire']) ) $contact_destinataire = $_POST['contact_destinataire']; else $contact_destinataire = ''; 
if ( isset($_POST['contact_message']) ) $contact_message = $_POST['contact_message']; else $contact_message = ''; 
3

The best way to deal with Form Posts in Wordpress is to use a special endpoint, /wp-admin/admin-post.php.

POST data can be messed up, both by the WP Query call, and by any redirects that happen.

So you set up your form with this action:

<form action="<?= admin_url('admin-post.php') ?>" method="post">
<input type="hidden" name="action" value="special_action">
<?php wp_nonce_field('special_action_nonce', 'special_action_nonce'); ?>

Then you can handle the form by adding an action to your theme or plugin:

add_action('admin_post_nopriv_special_action', ['My\Plugins\FormController', 'specialAction']);
add_action('admin_post_special_action', ['My\Plugins\FormController', 'specialAction']);

Note that Wordpress constructs a special action, based on the action value in the form, admin_post_no_priv_special_action (if you're logged out) and admin_post_special_action (if you're logged in). You can point these in different locations.

These action endpoints will always have access to POST, and will never trigger a redirect (which is often what Wordpress does for pretty routes... it often routes: site.com/about to site.com/?pageName=about).

Once you've handled the form as you want, you can do a wp_redirect() to get to where you need it to be. This is also helpful because an accidental page refresh will not re-send the form.

Much lengthier doco can be found here: https://www.sitepoint.com/handling-post-requests-the-wordpress-way/

| improve this answer | |
  • 1
    The nonce is not strictly necessary, but almost always a good idea. – haz Nov 14 '16 at 23:46
  • I tried this and it seems to solve the problem of lost POST data. However how can I display a confirmation message once the user gets redirected back to the contact page? – drake035 Nov 16 '16 at 13:45
  • For us it's easy because someone wrote a custom Status Message class that stores a feedback message in the Session, and then read it in the Session. Of course there's nothing to stop you writing to $_SESSION; but you need to make sure you clear it once you've viewed it. – haz Nov 22 '16 at 6:33
  • Argh, I honestly wanted to award the bounty to you today as I planned to come back to the issue and finish it, but bounty is gone. Why is the award delay so short? Anything I can do about this? – drake035 Nov 22 '16 at 13:19
3
+25

The problem is with your htaccess in that you are redirecting to another URL, causing the POST data to no longer be available.

RewriteRule ^(.*)   http://www.example.fr/$1 [QSA,L,R=301] 

Should be

RewriteRule ^(.*)   /$1 [QSA,L,R]

You could also set it to not redirect on a POST as well:

RewriteCond %{REQUEST_METHOD} !POST [NC]

OR, use a 307 redirect, which will preserve the POST data https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#3xx_Redirection


You can also use PHP shorthand IF statements, and recommend using array_key_exists over isset when you're checking an array

$sub = array_key_exists( 'sub', $_POST ) ? $_POST[ 'sub' ] : '';
$contact_nom = array_key_exists( 'contact_nom', $_POST ) ? $_POST[ 'contact_nom' ] : '';
$contact_prenom = array_key_exists( 'contact_prenom', $_POST ) ? $_POST[ 'contact_prenom' ] : '';
$contact_mail = array_key_exists( 'contact_mail', $_POST ) ? $_POST[ 'contact_mail' ] : '';
$contact_sujet = array_key_exists( 'contact_sujet', $_POST ) ? $_POST[ 'contact_sujet' ] : '';
$contact_destinataire = array_key_exists( 'contact_destinataire', $_POST ) ? $_POST[ 'contact_destinataire' ] : '';
$contact_message = array_key_exists( 'contact_message', $_POST ) ? $_POST[ 'contact_message' ] : '';

https://davidwalsh.name/php-ternary-examples

You should also be sanitizing the data that is coming in from frontend facing forms, to prevent any possible security vulnerabilities.
WordPress has plenty of these built in that you can use: https://codex.wordpress.org/Validating_Sanitizing_and_Escaping_User_Data


And why not just use something like Caldera Forms which will handle all of this for you? https://wordpress.org/plugins/caldera-forms/

| improve this answer | |
  • Just replaced RewriteRule ^(.*) example.fr/$1 [QSA,L,R=301] with RewriteRule ^(.*) /$1 [QSA,L,R], as instructed. Problem persists. – drake035 Nov 14 '16 at 18:15
  • Sounds like the problem is not due to your htaccess but something else. Check with your hosting company and see if they have mod_security enabled on your account. Have you checked to make sure you're even sending the POST to the right URL? – sMyles Nov 14 '16 at 23:03
  • When/how are you checking for the POST values? You didn't provide much of any details as to when the code to check for values is being ran? Make sure when viewing the source of the site the URL is correct (in action) ... and are you sure your code to get the POST vals is actually running when the POST is submitted? – sMyles Nov 14 '16 at 23:06
1

You may need to use bloginfo('url') aka home_url() (displayed site) instead of bloginfo('wpurl') aka site_url() (wordpress files location) in your action, for instance:

action="<?php echo home_url('/contact/'); ?>"
| improve this answer | |
  • Wouldn't it fail to work both locally and online if that was the issue, and wouldn't the page loading upon submit would be a different page from the form page? – drake035 Nov 10 '16 at 20:33
  • Normally I'd say yes but it depends on how your local installation is set up. Can you try switching it and see if it works with this code locally? – Michelle Nov 10 '16 at 20:42
  • Just tried, doesn't change anything. – drake035 Nov 11 '16 at 16:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.