1

I need to create validation for dynamically created fields on the checkout page.

class Myclass () 
{

    private $_active_fields;

    public function generate_fields () {
        /** 
        /* Some previous logic to create an $items array based on products in the cart. 
        */

        $items = array(
            "question-7" => array(
                "option 1-1",
                "option 1-2",
            ),
            "question-4" => array(
                "option 2-1",
                "option 2-2",
            ),          
        );

        foreach( $items as $key => $val ) {
            woocommerce_form_field('box_field-'.$key, array(
                'type' => 'radio',
                'options' => $val,
                 ....
                ),
            $checkout->get_value( 'box_field-'.$key ));
            $this->_active_fields[] = 'box_field-'.$key;
        }
        var_dump($this->_active_fields) // lists correctly all added items
    }

    public function add_fields () {
        add_action( 'woocommerce_after_order_notes', array( $this, 'generate_fields' ) );
    }

    public function generate_validation () {
        $fields = $this->_active_fields; 
        var_dump($fields); // Empty array 
    
        foreach ( $fields as $key => $val ) {
            if ( ! $_POST[$val] {
                wc_add_notice( 'Please fill field'.$val, 'error' );
            }
        }

    }

    public function add_validation() {
        add_action( 'woocommerce_checkout_process', array( $this, 'generate_validation' ) );
    }
        
}

So I run the following code

$form = new Myclass();
$form->add_fields();
$form->add_validation();

When I try to access the $_active_fields property within the generate_valiadation() method, it is empty. However if I call var_dump($this->_active_fields) at the end of generate_fields() method, it is listing all generated field keys correctly.

So I guess I'm doing something wrong. Any ideas on how to set $_active_fields inside generate_fields() and get it's values in generate_valiadation()?

  • You init the class and want to receive the value directly after you init it! The hook runs later - I'm sure! So no value available at the time of class init and also when you call the methods directly after it. After the `woocommerce_after_order_notes` hook you can access the value for this instance. All in all I would not use this kind of layout. Why don't you save your custom field in the order meta or session? – Mr. Jo May 22 '21 at 13:20

1 Answers1

0

You may want to look at using a session variable. You're trying to pass vairables between 2 different hooks that run at different times.

I've created an example for simplicity which you can then develop into a more OOP approach. This will allow you to setup a session variable in your first hook callback, then pass that to your second from memory.

Function 1 sets the session variable when you hook is called. Function 2 uses the session variable from memory and kills it once its finished.

You can adapt this easily and pass the session var to a new class. You could even set it in a parent class and then use it as a property in a child class.

/**
 * In your main plugin file
 **/
add_action( 'woocommerce_after_order_notes', 'callback_function_1' );
add_action( 'woocommerce_checkout_process', 'callback_function_2' ) );

/**
 * This function is called first 
 */
function callback_function_1(){

   /**
    * Start a php session
    */
   session_start();

   /**
    * Do what you need to do and set your session var (return value) here
    */  
   $_SESSION['foo'] = 'bar';

}

/**
 * This function is called second 
 */
function callback_function_2 () {

   /**
    * Check to see if the var is set then use it
    */
   if (isset($_SESSION['foo'])) {
    
       print_r($_SESSION['foo']);
       //prints bar

   }  

   session_destroy();
    
}
Alex Knopp
  • 907
  • 1
  • 10
  • 30
  • Thanks man, I tried your example. The `callback_function_2()` is triggered, but the `$_SESSION['foo']` is not set. I downloaded a plugin to debug hooks order. I can see `woocommerce_after_order_notes` hook but the `woocommerce_checkout_process` is not listed there - probably because it gets triggered after ajax call which was messed up by the hook debug plugin. shm.. But if I'm right, it should be triggered after `woocommerce_after_order_notes` if it's not listed by the hook debug plugin yet. – Jakub Voženílek May 22 '21 at 16:23