最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

plugins - Why is an action callback function from an instance of a class always invoking the same function from an instance?

matteradmin5PV0评论

I have a class whose constructor is the following:

public function __construct( $content_type, $filter_fields, $meta_query = '', $taxonomy = '') {
        if ( !empty ( $content_type ) ) {
          add_action('wp_ajax_myfilter', array($this, 'filter_function'));
          add_action('wp_ajax_nopriv_myfilter', array($this, 'filter_function));
...

I create two instances of the class as follows (filter_list is an array that contains the properties which are not relevant for this purpose)

    global $filter_builder;

    foreach ($filter_list as $filter ) {
        $filter_builder[$filter['content_type']] = new FilterBuilder( 
            $filter[ 'content_type' ], $filter[ 'filter_fields' ], $filter['meta_query'], $filter['taxonomy']
        );
    }

The instances are created correctly and everything shows fine until the ajax call is made and the callback function, 'filter_function', is invoked. In theory, each instance has their own callback function when they were created, however, every time that ajax call is made, the function the first instance of the global array is called.

The global array has two instances and when I try and debug the callback, it seems like the same callback is invoked for both instances.

Even though the callbacks have the same name, it should not make a difference. I have created an anonymous function and this odd behaviour continues.

Is there something I am missing? The callback function depends on the content type when it is invoked, and it's always defaulting to the post type that is defined first in the array.

Here is the instance creation simplified in case it helps:

    $filter_list = array(
        array(
            'content_type' => 'event',
            'filter_fields' => array(
                // Text to Display => Field Name
                'Suburb' => 'city',
                'Postal Code' => 'zip',
            ),
            'meta_query' => '',
            'taxonomy' => '',
        ),
        array(
            'content_type' => 'contact_center',
            'filter_fields' => array(
                // Text to Display => Field Name
                'Suburb' => 'suburb',
                'Postal Code' => 'postal_code',
            ),
            'meta_query' => '',
            'taxonomy' => '',
        ),
    );

If you get this far, I thank you, and if you can help, I thank you even more! :-)

I have a class whose constructor is the following:

public function __construct( $content_type, $filter_fields, $meta_query = '', $taxonomy = '') {
        if ( !empty ( $content_type ) ) {
          add_action('wp_ajax_myfilter', array($this, 'filter_function'));
          add_action('wp_ajax_nopriv_myfilter', array($this, 'filter_function));
...

I create two instances of the class as follows (filter_list is an array that contains the properties which are not relevant for this purpose)

    global $filter_builder;

    foreach ($filter_list as $filter ) {
        $filter_builder[$filter['content_type']] = new FilterBuilder( 
            $filter[ 'content_type' ], $filter[ 'filter_fields' ], $filter['meta_query'], $filter['taxonomy']
        );
    }

The instances are created correctly and everything shows fine until the ajax call is made and the callback function, 'filter_function', is invoked. In theory, each instance has their own callback function when they were created, however, every time that ajax call is made, the function the first instance of the global array is called.

The global array has two instances and when I try and debug the callback, it seems like the same callback is invoked for both instances.

Even though the callbacks have the same name, it should not make a difference. I have created an anonymous function and this odd behaviour continues.

Is there something I am missing? The callback function depends on the content type when it is invoked, and it's always defaulting to the post type that is defined first in the array.

Here is the instance creation simplified in case it helps:

    $filter_list = array(
        array(
            'content_type' => 'event',
            'filter_fields' => array(
                // Text to Display => Field Name
                'Suburb' => 'city',
                'Postal Code' => 'zip',
            ),
            'meta_query' => '',
            'taxonomy' => '',
        ),
        array(
            'content_type' => 'contact_center',
            'filter_fields' => array(
                // Text to Display => Field Name
                'Suburb' => 'suburb',
                'Postal Code' => 'postal_code',
            ),
            'meta_query' => '',
            'taxonomy' => '',
        ),
    );

If you get this far, I thank you, and if you can help, I thank you even more! :-)

Share Improve this question asked Apr 1, 2019 at 23:09 csaboriocsaborio 1122 silver badges13 bronze badges 4
  • 1 Are wp_ajax_myfilter and wp_ajax_nopriv_myfilter the same for both classes? Or is the myfilter part different for each class? – czerspalace Commented Apr 1, 2019 at 23:36
  • Thanks for reply, both (wp_ajax_myfilter and wp_ajax_nopriv_myfilter) have the same callback function. The callback function is different for every instance. Does that make sense? – csaborio Commented Apr 2, 2019 at 0:43
  • Hi, sorry, I meant are the actions named wp_ajax_myfilter and wp_ajax_nopriv_myfilter in both classes. The callback is ok, but if the action name is the same for both, the ajax call will only go to one of them. What happens if you name them wp_ajax_nopriv_myfilter1 and wp_ajax_nopriv_myfilter2? – czerspalace Commented Apr 2, 2019 at 0:50
  • I'll try your suggestion in the evening and report back, thanks for the idea. – csaborio Commented Apr 2, 2019 at 1:32
Add a comment  | 

2 Answers 2

Reset to default 2

It's possible I'm misunderstanding your question, but the way it is written it seems as though every instance of your FilterBuilder class will always get called.

Each instance of your class has in its constructor:

add_action('wp_ajax_myfilter', array($this, 'filter_function'));

(as well as the non-logged-in-user version)

There is no conditional here telling it when to run based on which "content type" or class instance you have. WordPress is literally being told, "Every time you get an ajax request for 'myfilter', run this instance's filter_function function." And since there are 2 instances in your example, and thus 2 constructors, WordPress is being told that twice (once for each).

WP AJAX functions are generally written to return data and die. (Grim maybe, but true :) So if your's is written as such, only the first registered action will run.

So, in short, it is true that each of your registered hooks is tied to its respective object ($this), and that their similar names is not a hindrance. However, you haven't given WordPress or your AJAX workflow anything to know which instance it should load.

As czerspalace & tmdesigned pointed out, the ajax call needed to be different for each instance. The action registration now looks like this:

            add_action("wp_ajax_myfilter_{$content_type}", array( $this, 'scorpiotek_filter_function' ) );
            add_action("wp_ajax_nopriv_myfilter_{$content_type}", array( $this, 'scorpiotek_filter_function' ) );

And I had to match the value filter of my hidden action input to reflect this change:

<input type="hidden" name="action" value="myfilter_<?php echo $this->get_content_type(); ?>">

Thanks both!! :-)

Articles related to this article

Post a comment

comment list (0)

  1. No comments so far