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="[email protected]|Information générales">Information générales</option>
    <option value="[email protected]|Problèmes liés au site">Problèmes liés au site</option>
  <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'>

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 = ''; 
  • And where is the code that handles the request in PHP?
    – jgraup
    Commented Nov 10, 2016 at 12:58
  • Added in the question.
    – drake035
    Commented Nov 10, 2016 at 14:43
  • codex.wordpress.org/Function_Reference/wp_parse_args will help clean up your default values.
    – jgraup
    Commented Nov 10, 2016 at 23:13
  • 1
    Can you var_dump($_POST); and post the results?
    – jgraup
    Commented Nov 10, 2016 at 23:14
  • 1
    and var_dump($_REQUEST); ?
    – jgraup
    Commented Nov 11, 2016 at 13:37

3 Answers 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/

  • 1
    The nonce is not strictly necessary, but almost always a good idea.
    – haz
    Commented Nov 14, 2016 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
    Commented Nov 16, 2016 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
    Commented Nov 22, 2016 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
    Commented Nov 22, 2016 at 13:19

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:


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' ] : '';


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/

  • Just replaced RewriteRule ^(.*) example.fr/$1 [QSA,L,R=301] with RewriteRule ^(.*) /$1 [QSA,L,R], as instructed. Problem persists.
    – drake035
    Commented Nov 14, 2016 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
    Commented Nov 14, 2016 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
    Commented Nov 14, 2016 at 23:06

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/'); ?>"
  • 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
    Commented Nov 10, 2016 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
    Commented Nov 10, 2016 at 20:42
  • Just tried, doesn't change anything.
    – drake035
    Commented Nov 11, 2016 at 16:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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