web-dev-qa-db-fra.com

Comment empêcher la nouvelle soumission de la page lors de l'actualisation lorsque l'avertissement "Impossible de modifier les informations d'en-tête - en-têtes" s'affiche

Je sais qu'il y a beaucoup de doublons possibles mais je continue à recevoir cette erreur à chaque fois

Je travaille actuellement sur un formulaire de contact WordPress, créé sous forme de plugin. J'ai besoin après avoir soumis le formulaire pour rediriger vers la même page avec un nouveau formulaire vierge. Le problème est que si je mets en-tête ("location ...) il me montre le message

Avertissement: Impossible de modifier les informations d'en-tête - les en-têtes déjà envoyés par (sortie démarrée à C:\xampp\htdocs\WP\contenu\themes\group-test\header.php: 13) dans C:\xampp\htdocs\WP\wp-content\plugins\exemple-de-forme\exemple-de-forme.php à la ligne 84

Le formulaire fonctionne correctement et envoie un e-mail après avoir appuyé sur le bouton d'envoi. Le problème est qu'il conserve les anciennes valeurs d'entrée et qu'il les renvoie après chaque rechargement ou envoi en appuyant, même si le formulaire est vide ... La meilleure décision pour moi serait de ne pas recharger la page mais seulement d'afficher un message après avoir appuyé sur "Soumettre" et de vider les valeurs d'entrée du formulaire comme les autres WP fonctionnalité des formulaires (Contact 7, etc.), mais je sais qu'Ajax est nécessaire ... Mais premièrement, je serai heureux si quelqu'un me montre où je me trompe.

<?php
/*
 Plugin Name: Example Contact Form
 Plugin URI: http://jd.com
 Description: Contact Form
 Version: 1.0
 Author: JD
 Author URI: http://jd.com
 */
function html_form_code() {    
    ?> 
<form action="<?php esc_url( $_SERVER['REQUEST_URI'] )?>" method="post" class="contact-form" id="newsletterform">
    <div class=header-contact>
        <p><h2>Contact Form</h2></p>
        <hr>
    </div>

    <div class=input-containers>
        <input type="text" id="name" name="cf-name" pattern="[a-zA-Z0-9 ]+" value="" size="40" placeholder="Име и фамилия"/>
    </div>
    <div class=input-containers>
        <input type="email" name="cf-email" value="" size="40" placeholder="Поща"/>
    </div>
    <div class=input-containers>
        <input type="text" name="cf-subject" pattern="[a-zA-Z ]+" value="" size="40" placeholder="Относно"/>
    </div>
    <div class=input-containers>
        <textarea rows="10" cols="35" name="cf-message" placeholder="Текст"></textarea>
    </div>
    <div class=input-containers>
        <input type="submit" name="cf-submitted" value="Send" >
    </div>
</form>
<?php
}
//function to generate response

function deliver_mail() {
    require_once "wp-includes/class-phpmailer.php";
    $verificationMessages = array();

    // if the submit button is clicked, send the email
    if ( isset( $_POST['cf-submitted'] ) ) {    
        // sanitize form values
        $name    = sanitize_text_field( $_POST["cf-name"] );
        $email   = sanitize_email( $_POST["cf-email"] );
        $subject = sanitize_text_field( $_POST["cf-subject"] );
        $message = esc_textarea( $_POST["cf-message"] );

        $headers = "From: $name <$email>" . "\r\n";
        // Localhost
        $mail = new PHPMailer(true);
        $mail->IsSMTP(); // telling the class to use SMTP
        $mail->CharSet = 'UTF-8';

        $mail->SMTPDebug = 0;                     // enables SMTP debug information (for testing)
        $mail->SMTPAuth = true;                  // enable SMTP authentication
        $mail->SMTPSecure = "ssl";                 // sets the prefix to the servier
        $mail->Host = "mail.gmx.com";      // sets GMX as the SMTP server for example: mail.gmx.com
        $mail->Port = 465;                 // set the SMTP port for the GMX server


        $mail->Username = $email;
        $mail->Password = 'pass';

        $mail->SetFrom($email, $name);
        $mail->AddAddress($email);

        $mail->Subject = $subject;
        $mail->MsgHTML($message);

        $headers .= "Content-Type: text/html; charset=utf-8";
        $headers .= "Content-Transfer-Encoding: 8bit";

        try {
            $mail->send();
            $msg = "An email has been sent for verfication.";
            $msgType = "success";
            array_Push($verificationMessages, "Check your email to activate your account");
            header("location: http://localhost/wp/");

        } catch (Exception $ex) {
            $msg = $ex->getMessage();
            $msgType = "warning"; 
            array_Push($verificationMessages, "Wrong");
            header("location: http://localhost/wp/");
        }      
    }
}

function cf_shortcode() {
    ob_start();

    deliver_mail();
    html_form_code();

    ob_end_flush(); 
    //return ob_get_clean();
}
add_shortcode( 'sitepoint_contact_form', 'cf_shortcode' );
1
J.D.

Le problème fondamental est donc d’envoyer des en-têtes, plus précisément le timing .

Les pages Web ont des en-têtes http, et les en-têtes http viennent avant le contenu. Les en-têtes indiquent au navigateur ce qu'il reçoit, et ils doivent être envoyés en premier.

Lorsque PHP génère des éléments, il doit indiquer au navigateur d'attendre une sortie. Ainsi, dès qu'un caractère est généré, PHP envoie des en-têtes HTTP indiquant au navigateur d'attendre une sortie.

Une fois qu'ils sont envoyés, ils sont envoyés. Le cheval est sorti de l'écurie, les chats sortis du sac, ils ne peuvent pas être changés.

Donc, au moment où votre site atteint votre shortcode, il produit déjà un élément html, un en-tête et un titre, etc., il est trop tard pour envoyer un en-tête de redirection!

En conséquence, nous pouvons conclure que la redirection à l'intérieur d'un shortcode n'est pas possible. Une autre solution est nécessaire

Le problème fondamental est que vous essayez de faire les choses dans un shortcode. Afficher la sortie dans le shortcode est une bonne chose, mais ce n’est pas bon pour un traitement réel.

Au lieu de cela, ajoutons une entrée masquée au formulaire que nous pouvons utiliser pour extraire la soumission du formulaire:

<input type="hidden" name="form_submitted" value="true" />

Puis recherchez cette valeur sur le hook init:

add_action( 'init', function() {
    if ( ! empty( $_POST['form_submitted'] ) ) {
        deliver_email();
    }
}

Et enfin, corrigez le shortcode cassé qui génère directement au lieu de renvoyer une chaîne HTML:

function cf_shortcode() {
    ob_start();

    html_form_code();

    return ob_get_clean();
}

Notes complémentaires:

  • préfixez tout, mais choisissez-en un plus que cf
  • Vous n'avez pas besoin d'inclure les fichiers PHPMailer, wp_mail et ses filtres feront l'affaire.
  • Il n'y a pas d'instruction exit après votre redirection d'en-tête
  • Utilisez wp_safe_redirect au lieu de header
  • Ne codez pas l’URL en dur, il existe des fonctions pour cela, par exemple. home_url() etc
1
Tom J Nowell