1

Im developing an plugin that uses AJAX, but im having trouble controling the codeflow.

I want to hook functions after running conditionals. My hooks wont fire when adding them inside a control structure, but outside they fire.

I also have an event that fires an AJAX request, this can only happen after the user has triggered the event with an click, after all DOM is loaded. The AJAX request tells an PHP function to then set a cookie. It sets the cookie, but when reading the PHP docs about cookies, i see that they can only be set after any output is sent, but yet i managed to do this?

Ive read about the WordPress initialization sequence, but that didnt help me to solve this problem.

Heres my code:

add_action('wp_head', 'Init_');

function Init_(){
    if(isset($_COOKIE['user_opt'])){
        $user_opt = $_COOKIE['user_opt'];
        if($user_opt === 'out'){
            function user_checkout(){
                $ch_script_url = plugins_url('/js/check_out.js', __FILE__);
                wp_enqueue_script('checkout', $ch_script_url); 
            }
            add_action('wp_enqueue_scripts', 'user_checkout'); // load this if the cookie is set
        }
    } else { // run this otherwise
        function user_opt_handler(){
            $opt_script_url = plugins_url('/js/opt_handler.js', __FILE__);
            wp_enqueue_script('opt_handler', $opt_script_url, array('jquery'), TRUE);
            $nonce = wp_create_nonce('my_nonce');
            $ajax_url = admin_url('admin-ajax.php');

            wp_localize_script(
                'opt_handler',
                'options',
                array(
                    'check' => $nonce,
                    'ajax_url' => $ajax_url
                )
                );
        }

        function opt_box_html(){ ?>
        <div id="user-opt-box">
        <button id="user-choice-yes">Yes</button> <!-- the AJAX in the "opt_handler" script will fire when an click event for this button happens -->
        </div>
        <?php }

        function user_handler(){
            if(is_admin() === TRUE){
            check_ajax_referer('my_nonce');
            setcookie('user_opt', 'out');
            wp_die();
        }
    }
    add_action('wp_enqueue_scripts', 'user_opt_handler');
    add_action('wp_footer', 'opt_box_html', 100);
    add_action('wp_ajax_user_handler','user_handler');
    add_action('wp_ajax_nopriv_user_handler', 'user_handler'); 
  }
}

Ive also noticed that, when using php variables with normal (outside all functions) scope, hooked functions dont have access to this.

For example, when trying to do this:

$a = "hello world";

function my_func(){
echo $a;
}

add_action('wp_footer', 'my_func');

This will output NULL. Is this because wordpress hooks only have access to variables declared inside them?

2

During page request, Wordpress actions are triggered in a sequence, therefore you have to register them in time. In your case, wp_head comes after wp_enqueue_scripts, so as a solution, i would all remove them from the wp_head and register them all in a condition, outside of any other action:

if ( isset( $_COOKIE['user_opt'] ) ) {
    add_action('wp_enqueue_scripts', 'user_checkout');
    // ...
    // add relevant actions here if isset $_COOKIE['user_opt']
} else {
    add_action('wp_enqueue_scripts', 'user_opt_handler');
    // ...
    // add relevant actions here if not set
}

About the cookies. They are part of HTTP header, therefore they must be set before any output (not after as you stated above).

As for your second question. That's nothing specific to Wordpress, that's standard behavior of callable. Please note, that callable might be specified differently:

// It might be anonymous function (closure)
add_action('wp_footer', function() {});

// A function
add_action('wp_footer', 'my_custom_function');

// Method call
add_action('wp_footer', [$obj, 'my_object_method']);

// and more...

And as you can see in the method call, that would be a way to get your context work with the function (assigning whatever values you want to $obj). As in $obj->a = 'hello world';

  • Thanks for your answer! I did however benefit from knowing the wordpress initialization sequence. Regardless, i did find another way to solve this problem. For the cookies i register a value in the database, to indicate that the cookies have been set, then if they are expired, the indicating value in the database will also be deleted. But now im facing an issue with the AJAX call giving me an 500 error, when using a for/while loop in the PHP handler for the ajax call. – abobakrdy Mar 18 at 21:22
  • error 500 is typically suppressed PHP fatal error, try enabling WP_DEBUG and see your error to get an idea – rozklad Mar 18 at 22:18
  • You are right, It was a wrong named function (get_optionS, and not get_option which is correct), that caused the error. However, if you dont mind, do you know if there is any way to get the option id with an simple api function call, or must this be done through an custom db query, and can I or shouldnt i use the options id as an id for a user? This might be slighty off topic, but i couldnt find any other questions for this, and neither any info in the wp docs. – abobakrdy Mar 19 at 20:48
  • There is an api call for getting options - it's /wp/v2/settings and it's documented here developer.wordpress.org/rest-api/reference/settings - however it is authorized. See if that works for you, if not you can make a custom api endpoint using register_rest_route() - developer.wordpress.org/reference/functions/register_rest_route – rozklad Mar 20 at 7:16
  • Not quite sure how an REST API is more beneficial to use compared to just an database query in this case. But I decided to not make the plugin afterall, so i dont need any more help on this. But i assume the question and answers are stil valuable to others. Regardless, thanks for your answers. – abobakrdy Mar 20 at 22:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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