1

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! :-)

  • 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 Apr 1 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 Apr 2 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 Apr 2 at 0:50
  • I'll try your suggestion in the evening and report back, thanks for the idea. – csaborio Apr 2 at 1:32
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.

  • Thanks for your reply, I think you are understanding my question and what you have explained makes sense. Here is the code of the callback function: public function scorpiotek_filter_function() { $args = array( 'post_type' => $this->get_content_type(), 'post_status' => 'publish', 'orderby' => 'date', // 'order' => $_POST['date'] , ); Each instance has a content_type stored so that when this callback function is called, the correct query parameters are set, however that is not working. – csaborio Apr 2 at 1:26
  • Each instance has the same callback function that will yield different results (in theory) based on their properties. Isn't this enough for AJAX and WordPress to work? That is essentially my 'conditional', in a way, but I think I am missing something here... – csaborio Apr 2 at 1:31
  • "Each instance has the same callback function that will yield different results based on their properties" - yes, but they both are set to be triggered to run every time, so the first one runs, then it tells WordPress to die and the AJAX call is over. The second "correct" one never gets a chance to even run. – tmdesigned Apr 2 at 2:41
  • If the code is the same, it only needs to be registered once -- probably outside of any instance of your class. If the code varies, it may need to be registered separately, but you should vary the name of the ajax call so the correct one can be called. You could do, for instance, add_action("wp_ajax_myfilter_{$content_type_slug}", ... which would create a different hook for each content type slug. – tmdesigned Apr 2 at 2:45
  • That worked! After changing it I was receiving 400 (Bad Request) but then I realised what I needed to change the value attribute in my form to match the corresponding hook - what a relief!!! Thank you! – csaborio Apr 2 at 3:25
0

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!! :-)

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.