Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I have a theme which has a page to display a keyword taxonomy called taxonomy-keyword.php. From this page I instantiate a sort of ViewModel called KeywordPage. It looks like this:

namespace MyTheme\ViewModels;
class KeywordPage {
    __construct() {
        wp_enqueue_script(
            'keywordpage_script',
            get_stylesheet_directory_uri() . '_inc/js/KeywordPage.js',
            array('jquery'),
            '');
        add_action('wp_ajax_get_more_posts', array(__CLASS__, 'get_more_posts_async'));
        add_action('wp_ajax_nopriv_get_more_posts', array(__CLASS__, 'get_more_posts_async'));

        // other initialization
    }

    public static function get_more_posts_async() {
        // Process AJAX
    }
}

The issue I'm having is that the AJAX response is always 0. This appears to indicate that the callback to the action could not be found by wordpress.

Now, I barely understand AJAX, let alone the subtleties of how wordpress handles it, but I know the KeywordPage script works just fine and get_more_posts_async() processes and responds to the AJAX call appropriately because if I place the function and the add_action() calls in functions.php it all works as intended.

What I can't figure out is why when the actions are in the constructor does wordpress not seem able to call the appropriate callback? I don't want to pollute the global namespace with out-of-context functions and actions by just placing this stuff in functions.php. Even though I already know it works, I want to make the theme as maintainable as I can.

Thanks in advance for your input, your help, and your guidance.

share|improve this question
    
is your class definition within the taxonomy-keyword.php template file? that would be your problem right there. –  Milo Apr 23 '13 at 3:08
    
My class definition is within it's own file KeywordPageVM.php. If I try using require_once 'viewmodels/KeywordPageVM.php' in functions.php it still yields a 0. –  josaphatv Apr 23 '13 at 3:15
    
do you create the instance from the template page? –  Milo Apr 23 '13 at 3:17
    
I do. It's where I use the instance. –  josaphatv Apr 23 '13 at 3:19
    
I think I've figured it out... but I guess I was hoping wordpress was smarter than this. I've moved the actions into their own static method and added a require statement to functions.php followed by a call to the static method. I guess there's no avoiding functions.php, is there? –  josaphatv Apr 23 '13 at 3:51
add comment

1 Answer 1

up vote 0 down vote accepted

Your constructor runs on the request from which you make the AJAX request, but not within the request that processes that AJAX request. The request that initially loads the page, and the AJAX request are two separate requests with no preservation of state between the two. This is not unique to WordPress, this is how AJAX typically works. When the AJAX request happens, your template file isn't loaded, so the class is never instantiated. In this case, you have to move things to functions.php, as that's the only theme file loaded in an AJAX request.

share|improve this answer
    
Hm... I can roll with this but I still don't like it. Is there a way to do AJAX with WordPress such that requests are routed to the 'page template' whence the request was referred? I'd like to have all of the AJAX for the page be with the page and not in the nebulous functions.php file. I figured WordPress would be able to read the referrer of the AJAX request and route it to the appropriate page template. It already acts like a Controller, why shouldn't it actually be one? –  josaphatv Apr 23 '13 at 4:11
    
I suppose you could try to request the same page from which the AJAX call is being made with some extra GET parameters to return what you need instead of the default page view markup. I think it makes more sense to do the opposite though- move everything out of page templates that's not strictly presentational. WordPress has a hook or action for just about everything it does, so you can override template behavior from a central location outside the template. –  Milo Apr 23 '13 at 21:54
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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