skip to Main Content

I want to add custom validation for Email and tel fields. I’m having two fields Email and Phone, Initially two fields should be mandatory, if the user filled any one of the field and submits the form it should be submitted.

I’ve added this code but it is now working.

add_filter('wpcf7_validate', 'custom_cf7_validation', 20, 2);

function custom_cf7_validation($result, $tags)
{
    // Get the values of the two fields
    $field1_value = isset($_POST['your-email']) ? sanitize_email_field($_POST['your-email']) : '';
    $field2_value = isset($_POST['your-phone']) ? sanitize_text_field($_POST['your-phone']) : '';

    // If either field has a value, make the other field not required
    if (!empty($field1_value) || !empty($field2_value)) {
        $field1 = $tags[0];
        $field2 = $tags[1];

        $field1->set_properties(array('required' => false));
        $field2->set_properties(array('required' => false));
    }

    return $result;
}

Above code showing the below error:

POST https://example.com/wp-json/contact-form-7/v1/contact-forms/524/feedback 500
Response {type: 'basic', url: 'https://example.com/wp-json/contact-form-7/v1/contact-forms/524/feedback', redirected: false, status: 500, ok: false, …}

2

Answers


  1. There were some parts missing from CF7, so here is a code that should work:

    add_filter('wpcf7_posted_data', 'custom_cf7_validation');
    function custom_cf7_validation($posted_data)
    {
        $email_value = isset($posted_data['your-email']) ? sanitize_email($posted_data['your-email']) : '';
        $phone_value = isset($posted_data['your-phone']) ? sanitize_text_field($posted_data['your-phone']) : '';
    
        // If either email or phone has a value, remove the other from the required validation
        if (!empty($email_value) || !empty($phone_value)) {
            if (!empty($email_value)) {
                unset($posted_data['your-phone']);
            } else {
                unset($posted_data['your-email']);
            }
        }
    
        return $posted_data;
    }
    

    Just make sure to replace 'your-email' and 'your-phone' with the correct names of your email and phone fields in the CF7 form.

    Login or Signup to reply.
  2. This is actually quite complex to achieve in CF7 because the plugin isn’t designed for complex validation.

    The reason why your approach fails is that the wpcf7_validate fires after CF7 has validated the submission and filled in the $result object with the error msgs.

    Therefore, you need to rebuilt the $result object and return that instead. There is a plugin that will do this automatically for you, the Smart Grid-layout extension for CF7 allows you to validate fields based on other submissions, so the simplest way to achieve this with that plugin enabled is using the following hook,

    add_filter( 'cf7sg_validate_submission','validate_field_submission',10,3);
    function validate_field_submission($validation_errors, $submission, $cf7_key){
      /* $submission an array of <field-name>=>$value pairs one for each submitted field.
       if a value is not valid, return a <field-name>=><error message string> pair in the $validation_errors array. The sbumission process will be cancelled and teh user required to correct the field before re-submitting.
      $cf7_key unique form key to identify your form, $cf7_id is its post_id.
      */
      if('my-form'==$cf7_key ){
        //$validation_errors is an array of field-names=>error messages.
        //these include the simple validation exposed in the CF7 plugin for required fields/special field formats.
        
        if(!empty($submission['your-email']) || !empty($submission['your-phone']){
          $validation_errors['your-email']='';
          $validation_errors['your-phone']=''; //simply clear any error msg logged by the CF7 plugin.
        }
      }
      return $validation_errors;
    }
    

    This is the simple solution.

    Now, if you want to do it the hard way, this is what you need to do:

    add_filter('wpcf7_validate', 'custom_cf7_validation', 20, 2);
    
    function custom_cf7_validation($result, $tags){
      //step 1 retain any invalidations from other fields,
      $invalids = $result->get_invalid_fields();
      //step 2 build a new validation object
      if(class_exists('WPCF7_Validation')){ //make sure it exists.
        $result = new WPCF7_Validation();
      }else{
        return $result;
      }
      //step 3 custom validation
      $field1_value = isset($_POST['your-email']) ? sanitize_email_field($_POST['your-email']) : '';
      $field2_value = isset($_POST['your-phone']) ? sanitize_text_field($_POST['your-phone']) : '';
    
      // If either field has a value, make the other field not required
      $is_valid = false;
      if (!empty($field1_value) || !empty($field2_value)) $is_valid=true;
      foreach($tags as $tag){
        $err_msg = '';
        if(isset($invalids[$tag['name']]) $err_msg = $invalids[$tag['name']]['reason'];
        switch($tag['name']){
          case  'your-email':
          case  'your-phone':
            $err_msg = $is_valid ? '': $err_msg ;
            break;
        }
        //rebuild the validaiton object.
        if(!empty($err_msg)) $result->invalidate($tag, $err_msg);
      }
      return $result;
    }
    

    NOTE: haven’t tested the above code, but it gives you the basic idea of that is required.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search