Formular simplu de contact cu validare a câmpurilor

23 aug. 2016, 17:16:45
Vizualizări: 14.8K
Voturi: 2

Caut să creez un formular simplu de contact pe care să-l pot afișa folosind un shortcode. Am următorul cod, dar nu pare să valideze corect și permite trimiterea formularului fără a completa datele. Poate cineva să explice cum să validez formularul? Aș dori să adaug și o capcană honeypot (honey pot trap) deoarece sunt mai bune decât captcha-urile. Sunt destul de nou în PHP. Orice ajutor ar fi minunat. Mulțumesc.

    function html_form_code() {
    echo '<form action="' . esc_url( $_SERVER['REQUEST_URI'] ) . '" method="post">';
    echo '<p>';
    echo 'Numele tău (obligatoriu) <br />';
    echo '<input type="text" name="cf-name" pattern="[a-zA-Z0-9 ]+" value="' . ( isset( $_POST["cf-name"] ) ? esc_attr( $_POST["cf-name"] ) : '' ) . '" size="40" />';
    echo '</p>';
    echo '<p>';
    echo 'Emailul tău (obligatoriu) <br />';
    echo '<input type="email" name="cf-email" value="' . ( isset( $_POST["cf-email"] ) ? esc_attr( $_POST["cf-email"] ) : '' ) . '" size="40" />';
    echo '</p>';
    echo '<p>';
    echo 'Mesajul tău (obligatoriu) <br />';
    echo '<textarea rows="10" cols="35" name="cf-message">' . ( isset( $_POST["cf-message"] ) ? esc_attr( $_POST["cf-message"] ) : '' ) . '</textarea>';
    echo '</p>';
    echo '<input type="text" name="content" id="content" value="" class="hpot" />'; // Câmp honeypot
    echo '<p><input type="submit" name="cf-submitted" value="Trimite"/></p>';
    echo '</form>';
}

function deliver_mail() {

  $errors = new WP_Error();
if ( isset( $_POST[ 'content' ] ) && $_POST[ 'content' ] !== '' ) {
  $errors->add( 'cheater', 'Scuze, acest câmp nu ar trebui completat. Încerci să trișezi?' );
}
if ( isset( $_POST[ 'cf-name' ] ) && $_POST[ 'cf-name' ] == '' ) {
  $errors->add('error', 'Te rog completează un nume valid.' );
}

if ( isset( $_POST[ 'cf-email' ] ) && $_POST[ 'cf-email' ] == '' ) {
  $errors->add('error', 'Te rog completează un email valid.' );
}

if ( isset( $_POST[ 'cf-message' ] ) && $_POST[ 'cf-message' ] == '' ) {
  $errors->add('error', 'Te rog completează un mesaj valid.' );
}

if ( empty( $errors->errors ) ){
  deliver_mail();
}
else {
  echo 'Te rog completează câmpurile obligatorii';
}


    // dacă butonul de trimitere este apăsat, trimite emailul
    if ( isset( $_POST['cf-submitted'] ) ) {

        // curăță valorile formularului
        $name    = sanitize_text_field( $_POST["cf-name"] );
        $email   = sanitize_email( $_POST["cf-email"] );
        $message = esc_textarea( $_POST["cf-message"] );

        // obține adresa de email a administratorului
        $to = get_option( 'admin_email' );

        $headers = "From: $name <$email>" . "\r\n";

        // Dacă emailul a fost procesat pentru trimitere, afișează un mesaj de succes
        if ( wp_mail( $to, $message, $headers ) ) {
            echo '<div class=cf-success>';
            echo '<p>Mulțumim că ne-ai contactat '. $name .', un membru al echipei noastre va lua legătura cu tine în scurt timp.</p>';
            echo '</div>';
        } else {
            echo '<div class=cf-error>';
            echo '<p>A apărut o eroare neașteptată</p>';
            echo '</div>';
        }
    }
}

function cf_contact_form() {
    ob_start();
    deliver_mail();
    html_form_code();

    return ob_get_clean();
}

add_shortcode( 'contact_form', 'cf_contact_form' );

Deci ar trebui să arate ca mai sus? Mulțumesc.

De asemenea, primesc această eroare când încerc să rulez verificările câmpurilor.

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 262144 bytes) in /Applications/MAMP/htdocs/centenary-framework/wp-content/themes/cent_framework/assets/inc/core/contact-form.php on line 147

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 262144 bytes) in /Applications/MAMP/htdocs/centenary-framework/wp-includes/load.php on line 671

Nu sunt sigur ce înseamnă asta. =(

EDIT

Aceste probleme au fost rezolvate. Postez codul funcțional mai jos în speranța că va ajuta pe cineva în viitor. Mulțumesc tuturor care au ajutat!!

// Markup formular
 function html_form_code()
 {
     ?>

 <form action="<?php esc_url($_SERVER['REQUEST_URI']);
     ?>" method="post">
   <p>Numele tău (obligatoriu)<br />
     <input type="text" name="cf-name" pattern="[a-zA-Z0-9 ]+" value="<?php isset($_POST['cf-name']) ? esc_attr($_POST['cf-name']) : '';
     ?>" size="40" />
   </p>
   <p>Emailul tău (obligatoriu)<br />
     <input type="email" name="cf-email" value="<?php isset($_POST['cf-email']) ? esc_attr($_POST['cf-email']) : '';
     ?>" size="40" />
   </p>
   <p>Mesajul tău (obligatoriu)<br />
     <textarea rows="10" cols="35" name="cf-message"><?php isset($_POST['cf-message']) ? esc_attr($_POST['cf-message']) : '';
     ?></textarea>
   </p>
   <p><input type="submit" name="cf-submitted" value="Trimite"/></p>
 </form>

 <?php

 }

// Validare formular
 function my_validate_form()
 {
     $errors = new WP_Error();

     if (isset($_POST[ 'content' ]) && $_POST[ 'content' ] !== '') {
         $errors->add('cheater', 'Scuze, acest câmp nu ar trebui completat. Încerci să trișezi?');
     }

     if (isset($_POST[ 'cf-name' ]) && $_POST[ 'cf-name' ] == '') {
         $errors->add('name_error', 'Te rog completează un nume valid.');
     }

     if (isset($_POST[ 'cf-email' ]) && $_POST[ 'cf-email' ] == '') {
         $errors->add('email_error', 'Te rog completează un email valid.');
     }

     if (isset($_POST[ 'cf-message' ]) && $_POST[ 'cf-message' ] == '') {
         $errors->add('message_error', 'Te rog completează un mesaj valid.');
     }

     return $errors;
 }

// Trimitere formular
 function deliver_mail($args = array())
 {

  // Acest array $default este o modalitate de a inițializa niște valori implicite care vor fi suprascrise de array-ul nostru $args.
  // Putem adăuga mai multe chei după cum considerăm și este o modalitate bună de a vedea ce parametri utilizăm în funcția noastră.
  // Va fi suprascris doar cu valorile din array-ul nostru $args dacă cheile sunt prezente în $args.
  // Aceasta utilizează funcția wp_parse_args() din WP.
  $defaults = array(
    'name' => '',
    'email' => '',
    'message' => '',
    'to' => get_option('admin_email'), // obține adresa de email a administratorului
  );

     $args = wp_parse_args($args, $defaults);

     $headers = "From: {$args['name']}  <{$args['email']}>"."\r\n";

  // Trimite emailul returnează true la succes, false în caz contrar
  if (wp_mail($args['to'], $args['message'], $headers)) {
      return;
  } else {
      return false;
  }
 }

// Curățare câmpuri
function my_sanitize_field($input)
{
    return trim(stripslashes(sanitize_text_field($input)));
}

// Mesaj succes formular
function my_form_message()
{
    global $errors;
    if (is_wp_error($errors) && empty($errors->errors)) {
        echo '<div class="cf-success">';
        echo '<p>Mulțumim că ne-ai contactat '.$_POST['cf-name'].', un membru al echipei noastre va lua legătura cu tine în scurt timp.</p>';
        echo '</div>';

    // Golire $_POST pentru că am trimis deja emailul
    $_POST = '';
    } else {
        if (is_wp_error($errors) && !empty($errors->errors)) {
            $error_messages = $errors->get_error_messages();
            foreach ($error_messages as $k => $message) {
                echo '<div class="cf-error '.$k.'">';
                echo '<p>'.$message.'</p>';
                echo '</div>';
            }
        }
    }
}

// Shortcode formular
add_shortcode('contact_form', 'cf_contact_form');
function cf_contact_form()
{
    ob_start();

    my_form_message();
    html_form_code();

    return ob_get_clean();
}

// Validare erori
add_action('init', 'my_cf_form');
function my_cf_form()
{
    if (isset($_POST['cf-submitted'])) {
        global $errors;
        $errors = my_validate_form();
        if (empty($errors->errors)) {
            $args = array(
         'name' => my_sanitize_field($_POST['cf-name']),
         'email' => my_sanitize_field($_POST['cf-email']),
         'message' => my_sanitize_field($_POST['cf-message']),
       );
            deliver_mail($args);
        } else {
            return $errors;
        }
    }
}
0
Toate răspunsurile la întrebare 2
10

Nu aveți niciun mecanism de validare.

Logica ar trebui să funcționeze aproximativ astfel:

  • Trimiteți formularul
  • Verificați câmpurile trimise ($_POST) în funcție de valorile așteptate
  • Dacă totul este în regulă, trimiteți
  • Dacă ceva nu este conform așteptărilor, înregistrați eroarea (puteți folosi WP_Error()) și reconstruiți formularul afișând mesajul de eroare (și eventual repopulând câmpurile cu valorile anterioare "corecte").

Tot ce văd aici este că sanitizați intrările, dar nu validați dacă intrările au valorile pe care le așteptați (de ex. email valid, telefon, lungimea numelui, etc.).

Trimiteți emailul indiferent dacă câmpurile au valorile așteptate. else dvs. va afișa o eroare DOAR dacă wp_mail() eșuează, nu dacă câmpurile au valori validate sau nu.

Pentru a adăuga un honey pot, trebuie doar să adăugați un câmp ascuns în formularul dvs. pe care vă așteptați să fie gol.

De exemplu, în HTML-ul dvs.

<input type="text" name="content" id="content" value="" class="hpot" />

Apoi când validați intrările formularului, vă așteptați ca acel câmp să fie gol.

folosind clasa WP_Error puteți adăuga erori la obiect pentru a le folosi ulterior pentru a informa utilizatorul sau altele.

$errors = new WP_Error();
if ( isset( $_POST[ 'content' ] ) && $_POST[ 'content' ] !== '' ) {
  $errors->add( 'cheater', 'Ne pare rău, acest câmp nu ar trebui să fie completat. Încercați să trișați?' );
}

Deci verificarea PHP de mai sus este o metodă pe care o puteți folosi pentru a valida formularul. Pur și simplu adăugați niște instrucțiuni if cu valorile așteptate ale formularului (desigur, acest lucru poate fi extins la funcții care validează intrările). Apoi, dacă folosiți clasa WP_Error, adăugând la obiect dacă sunt găsite erori, trebuie doar să faceți o verificare finală înainte de a trimite.

if ( empty( $errors->errors ) ){
  deliver_mail();
}
else {
  // Aici puteți folosi variabila $_POST pentru a repopula formularul cu valorile acceptate 
  // (ar trebui să actualizați funcția html_form_code() pentru a accepta un argument) 
  // sau doar să reîncărcați pagina de contact afișând un mesaj de eroare.
}

EDIT

Ok, deci iată un exemplu mai complet

CSS

adăugați acest cod în CSS pentru ca câmpul să nu fie afișat în browser

.hpot {
  display: none;
}

PHP

Iată un alt mod de a scrie funcția html, este mai ușor de citit

function html_form_code() { ?>

<form action="<?php esc_url( $_SERVER['REQUEST_URI'] ); ?>" method="post">
  <p>Numele tău (obligatoriu)<br />
    <input type="text" name="cf-name" pattern="[a-zA-Z0-9 ]+" value="<?php isset( $_POST["cf-name"] ) ? esc_attr( $_POST["cf-name"] ) : ''; ?>" size="40" />
  </p>
  <p>Emailul tău (obligatoriu)<br />
    <input type="email" name="cf-email" value="<?php isset( $_POST["cf-email"] ) ? esc_attr( $_POST["cf-email"] ) : ''; ?>" size="40" />
  </p>
  <p>Mesajul tău (obligatoriu)<br />
    <textarea rows="10" cols="35" name="cf-message"><?php isset( $_POST["cf-message"] ) ? esc_attr( $_POST["cf-message"] ) : ''; ?></textarea>
  </p>
  <p><input type="submit" name="cf-submitted" value="Trimite"/></p>
</form>

<?php } 

Funcția deliver_mail nu ar trebui să asculte pentru $_POST și nu ar trebui să sanitizeze. Ca o observație secundară, folosirea emailului utilizatorului ca antet from ar putea cauza probleme cu unele ISP-uri, deoarece emailul este trimis din domeniul dvs. și acum un email este trimis din domeniul dvs. dar cu un domeniu care nu se potrivește în antetul from (ar putea fi considerat spam). Folosiți o adresă de email din domeniul dvs. aici (cum ar fi no-reply@example.com) și setați emailul utilizatorului în corpul emailului (în mesaj). Puteți să-l setați și ca un câmp reply-to pentru comoditate.

function deliver_mail( $args = array() ) {

  // Acest array $default este o modalitate de a inițializa niște valori implicite care vor fi suprascrise de array-ul nostru $args.
  // Putem adăuga mai multe chei după cum considerăm și este o modalitate bună de a vedea ce parametri folosim în funcția noastră.
  // Va fi suprascris doar cu valorile din array-ul nostru $args dacă cheile sunt prezente în $args.
  // Aceasta utilizează funcția wp_parse_args() din WordPress.
  $defaults = array(
    'name'    => '',
    'email'   => '',
    'message' => '',
    'to'      => get_option( 'admin_email' ), // obține adresa de email a administratorului
  );

  $args = wp_parse_args( $args, $defaults );

  $headers = "From: {$args['name']} <{$args['email']}>" . "\r\n";

  // Trimite emailul și returnează true la succes, false în caz contrar
  if( wp_mail( $args['to'], $args['message'], $headers ) ) {
    return;
  }
  else {
    return false;
  }
}

Funcția de validare

function my_validate_form() {

  $errors = new WP_Error();

  if ( isset( $_POST[ 'content' ] ) && $_POST[ 'content' ] !== '' ) {
    $errors->add( 'cheater', 'Ne pare rău, acest câmp nu ar trebui să fie completat. Încercați să trișați?' );
  }

  if ( isset( $_POST[ 'cf-name' ] ) && $_POST[ 'cf-name' ] == '' ) {
    $errors->add('name_error', 'Vă rugăm să completați un nume valid.' );
  }

  if ( isset( $_POST[ 'cf-email' ] ) && $_POST[ 'cf-email' ] == '' ) {
    $errors->add('email_error', 'Vă rugăm să completați un email valid.' );
  }

  if ( isset( $_POST[ 'cf-message' ] ) && $_POST[ 'cf-message' ] == '' ) {
    $errors->add('message_error', 'Vă rugăm să completați un mesaj valid.' );
  }

  return $errors;
}

Funcția de sanitizare. Iată o funcție generală de sanitizare care elimină spațiile albe și escapează HTML, dar aceasta ar putea fi mai complexă în funcție de câmpurile de intrare pe care le aveți. Dar cred că pentru scopul dvs. este suficient.

function my_sanitize_field( $input ){

  return trim( stripslashes( sanitize_text_field ( $input ) ) );

}

Pentru afișarea mesajelor de succes/eroare, puteți folosi această funcție pentru a obține obiectul WP_Error

function my_form_message(){

  global $errors;
  if( is_wp_errors( $errors ) && empty( $errors->errors ) ){

    echo '<div class="cf-success">';
    echo '<p>Vă mulțumim că ne-ați contactat '. $_POST['cf-name'] .', un membru al echipei noastre vă va contacta în curând.</p>';
    echo '</div>';

    //Goliți $_POST pentru că am trimis deja emailul
    $_POST = '';

  }
  else {

  if( is_wp_errors( $errors ) && ! empty( $errors->errors ) ){

    $error_messages = $errors->get_error_messages(); 
    foreach( $error_messages as $k => $message ){
        echo '<div class="cf-error ' . $k . '">';
        echo '<p>' . $message . '</p>';
        echo '</div>';

    }

  }

}

În final, funcția shortcode

add_shortcode( 'contact_form', 'cf_contact_form' );
function cf_contact_form() {

  ob_start();

  my_form_message();
  html_form_code();

  return ob_get_clean();
}

Și conectarea la init pentru a asculta pentru $_POST înainte de a afișa formularul și a afișa $errors dacă găsim unele sau trimitem dacă totul este în regulă.

add_action( 'init', 'my_cf_form');
function my_cf_form(){

  if( isset( $_POST['cf-submitted'] ) ) {

    global $errors;
    $errors = my_validate_form(); 
    if( empty( $errors->errors ) ){

       $args = array(
         'name'    => my_sanitize_field( $_POST['cf-name'] ),
         'email'   => my_sanitize_field( $_POST['cf-email'] ),
         'message' => my_sanitize_field( $_POST['cf-message'] ),
       );
       deliver_mail( $args );
    }
    else {
      return $errors;
    } 
  }
}

Amintiți-vă să prefixați întotdeauna funcțiile pentru a nu intra în conflict cu numele de funcții ale altor plugin-uri.

23 aug. 2016 17:53:34
Comentarii

Scuze că sunt prost, unde rulez verificările mele? Mulțumesc

user53340 user53340
23 aug. 2016 18:12:03

Dacă ești nou în PHP, nu ești prost, doar trebuie să înveți aceste lucruri :P - În ceea ce privește unde faci verificarea, trebuie să modifici funcția ta deliver_mail(). Nu asculți acolo pentru $_POST. De fapt, funcția ta ar trebui să facă doar un singur lucru (sau să aibă o singură logică), deci dacă funcția ta este folosită pentru a trimite email-uri, atunci nu verifici conținutul acolo (are sens?) Așadar, poți verifica $_POST chiar înainte să validezi formularul. Voi actualiza răspunsul meu cu niște cod.

bynicolas bynicolas
23 aug. 2016 18:21:11

Am actualizat codul meu conform presupunerilor mele despre cum ar trebui să fie, dar cred că tot nu e bine pentru că încă nu funcționează. lol Am primit și o eroare de memorie când am trimis formularul și am reîncărcat pagina, așa că presupun că nu închid codul cum trebuie sau ceva de genul?

user53340 user53340
23 aug. 2016 18:25:53

De asemenea, când pagina se reîmprospătează după trimiterea formularului, câmpurile sunt încă completate cu informațiile, este corect? Înțelegerea mea era că sanitarizarea formularului ar trebui să elimine datele introduse de utilizator în câmpuri. Sau înțeleg greșit scopul funcției de sanitarizare?

user53340 user53340
23 aug. 2016 18:30:27

Ok, asta s-a dovedit a fi o editare mai lungă decât anticipasem, dar cred că poate fi o referință bună pentru tine. Reține că nu a fost testată, așa că dacă găsești vreun bug, spune-mi și vom încerca să-l rezolvăm. Verific-o și spune-mi ce părere ai. Legat de faptul că câmpurile rămân completate după trimitere, asta se întâmplă pentru că nu cureți variabila ta $_POST și o folosești pentru a popula formularul. Codul meu ar trebui să rezolve asta.

bynicolas bynicolas
23 aug. 2016 19:51:32

Wow! Asta e un răspuns solid dacă am văzut vreunul. Cred că ai dreptate, cu siguranță va fi foarte benefic pentru alții care vor da peste el. Mulțumesc pentru tot timpul petrecut cu asta! E cu adevărat util. Am o întrebare, ce face variabila $k? Mulțumesc din nou!

user53340 user53340
23 aug. 2016 20:59:39

$k este cheia din array-ul $errors->errors, cunoscută și sub numele de slug pentru eroare. Amintiți-vă când ați setat mesajul de eroare $errors->add('name_error', 'Te rog completează un nume valid.' );, în acest caz, $k ar fi name_error. De fapt, acesta este codul de eroare atribuit pentru acea eroare specifică. L-am adăugat ca clasă HTML pentru a putea fi mai ușor de stilizat diferit fiecare eroare, dacă va fi nevoie. Mă bucur că acest răspuns a putut ajuta.

bynicolas bynicolas
23 aug. 2016 21:23:05

Îmi cer scuze că te deranjez din nou. Primesc o eroare de sintaxă pentru $headers, care spune că așteaptă un șir de caractere sau o variabilă, dar a găsit un spațiu neașteptat. Am eliminat ghilimelele simple din jurul numelui și emailului, dar apoi primesc o eroare de sfârșit neașteptat al fișierului, cred din cauză că funcția my_form_message() nu este închisă. Așa că am închis-o și am primit o eroare fatală din cauza lui is_wp_errors și acum sunt destul de confuz =S

user53340 user53340
24 aug. 2016 12:02:49

este greu de spus de aici, dar observ ceva neînregulă la definirea variabilei tale $headers. Deoarece folosești un nume de variabilă (array) în interiorul șirului tău, trebuie să anunți explicit parserul PHP unde se termină variabila, folosind acoladele { }. Așadar, încearcă asta și ar trebui să fie ok: $headers = "From: {$args['name']} <{$args['email']}>\r\n";

bynicolas bynicolas
24 aug. 2016 17:34:33

Mulțumesc că ai revenit. Au fost câteva probleme care acum au fost rezolvate. Am actualizat codul meu mai sus. Mulțumesc din nou pentru toată ajutorul oferit în legătură cu aceasta!

user53340 user53340
24 aug. 2016 17:40:08
Arată celelalte 5 comentarii
5

Deoarece ești relativ nou în PHP, iată un exemplu frumos de honeypot simplu pe partea de server.

Ceea ce vei face este să configurezi un câmp text ascuns în formularul tău și să verifici dacă nu este gol pentru a prinde spamul.

HTML pentru Formular

<label for="honeypot" class="bot">Lasă gol dacă ești om</label>
<input type="text" id="honeypot" name="honeypot" class="bot" />

CSS

.bot { display:none }

PHP (simplificat)

 if ( $_POST() ) {
    $name = strip_tags(urldecode(trim($_POST['name'])));
    // SAU
    $name = test_input($_POST['name']); 
    $honeypot = $_POST('honeypot');
    // Verifică DOAR dacă există ceva în el.
    if ($honeypot){
      $msg = "Ești un bot";
    } else {
      $msg = "Succes";
      // Procesare suplimentară
      if ($name){
          mail(...)
      }
    }
    echo $msg;
 }

După o scurtă căutare, am găsit și această funcție pe care ai putea-o folosi.

function test_input($data) {
  $data = trim($data);
  $data = stripslashes($data);
  $data = htmlspecialchars($data);
  return $data;
}
23 aug. 2016 17:40:58
Comentarii

Mulțumesc pentru mesajul tău. Este cu siguranță util, principala mea problemă este lipsa validării formularului. În prezent, îmi permite să trimit formularul indiferent dacă completez ceva sau nu. Și sunt îngrijorat că nu verifică pentru injecții de cod etc. Acesta este principalul lucru pe care îl caut. Ar fi un caz de a urma același principiu ca pentru honey pot? Mulțumesc din nou.

user53340 user53340
23 aug. 2016 17:44:31

Voi actualiza PHP-ul cu teste suplimentare de validare, dar nu ar trebui să ai încredere niciodată în datele introduse de utilizator și ar trebui să le sanitizezi/validezi în orice mod posibil.

Greg McMullen Greg McMullen
23 aug. 2016 17:47:20

Mulțumesc. Vreau să-l fac cât se poate de sigur, dar, după cum am spus, sunt destul de nou în PHP, așa că sunt conștient de aceste lucruri, dar nu am nicio idee cum să implementez măsurile de siguranță. Știu că poți interoga câmpurile de introducere pentru a opri pe cineva care încearcă să hackuiască formularul etc., dar nu știu cum ai face asta. Mulțumesc din nou pentru ajutor.

user53340 user53340
23 aug. 2016 17:50:07

Încarci asta într-o bază de date sau doar primești prin email? Din postarea originală, se pare că faci doar ultimul.

Greg McMullen Greg McMullen
23 aug. 2016 17:54:27

Da, vreau doar să primesc prin email. Nu ar trebui să intre în baza de date, dar nici nu vreau să fac site-ul vulnerabil. Am pățit asta cu Gravity Forms acum ceva timp. Mulțumesc pentru actualizare!

user53340 user53340
23 aug. 2016 17:59:29