dongzhao3040 2019-04-23 15:36
浏览 66
已采纳

如何在我的ajax-php脚本中访问wordpress函数

I'm trying to call a WordPress function ( get_avatar($id) ) from a php script that is being accessed in an ajax referenced call from an enqueued javascript file. (Saying this out load already makes my head hurt).

As a an example, I've created a plugin for WordPress: hmm-test. It is implemented in hmm-test.php. This script enqueues a javascript file: test.js. Within the js I have an xhttprequest call that POSTS to hmm-test.php, which branches on a test for a POST variable.

When hmm-test.php is called as a GET, for example using the WordPress URL for the page where the short-code is embedded, I can call WordPress functions. From the POST branch, I want to be able to call WordPress native functions as well to return that as part of the JSON payload.

So my question is: can I make the 'POST' side branch of hmm-test.php 'wordpress-aware' such that I can call native WP functions from within it?

I'm stuck - not sure what else to try. I tried creating a REST endpoint to call via an Ajax URL early on but kept running into auth problems. If this would work, I can spend time working through it, but I've found the OAuth bits tricky. I had it working for something else, and lost it. If there's a way to do it with a simple POST, that's good enough for my proof of concept.

Here is the plugin PHP script and the enqueued javascript in their entirety:

<?php
/*
Plugin Name:  HMM Test
*/

if (strlen($_POST['action'])) {

        $rv["payload"] = get_avatar(108);
        $rv["payload"] = "This is the payload message";
        $rv["status"]  = 'SUCCESS';
        echo json_encode($rv);

} else {

        function hmm_test_enqueue_scripts() {

                wp_register_script( 'test-js', plugins_url( '/js/test.js', __FILE__ ), '', '1.0', all );

        }

        add_action( 'wp_enqueue_scripts', 'hmm_test_enqueue_scripts' );

        /* ***************************************************************************
         * This is the main page
         * ************************************************************************* */

        add_shortcode( 'test-contents', 'my_test_contents' );

        function my_test_contents() {

                wp_enqueue_script( 'test-js' );

                wp_localize_script('test-js', 'wpVariables', array(
                        'pluginsUrl' => plugins_url(),
                        'pluginDir' => trailingslashit( dirname( plugin_basename( __FILE__ ) ) ),
                        'userID' => 37
                ));

                echo "Wordpress functions test: get_avatar()";
                echo get_avatar( 37 );          # -- This works from the plugin script

                echo '<button type="button" class="test-button">Click to crash</button>';
        }
}

And the JS:

(function () {
        var c = document.getElementsByClassName('test-button');

        for (var i = 0; i < c.length; i++ ) {
                c[i].addEventListener('click', doTest, false);
        }
})();

function doTest() {

        console.log("In doTest()");

        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function() {
                if (this.readyState == 4 && this.status == 200) {
                        console.log("responseText: " + this.responseText);
                }
        };

        var ajaxUrl = wpVariables.pluginsUrl + '/' + wpVariables.pluginDir + 'hmm-test.php';
        var userid  = wpVariables.userID;

        xhttp.open("POST", ajaxUrl, true);
        xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        let arg = "action=update" + "&userid=" + userid;
console.log("Calling URL:" + ajaxUrl + " with arg: " + arg);
        xhttp.send(arg);
}

When I place the shortcode [hmm-test] in a Wordpress page, it loads fine, and I get the expected 'Wordpress functions test...', the proper avatar image for user 37 (hard-coded in this example), and a button to click to make things crash (for now!).

Clicking the button, I see this is the console window:

In doTest() test.js?ver=1.0:40 Calling URL:https://not-my-real-url.com/wp-content/plugins/hmm-test/hmm-test.php with arg: action=update&userid=37 test.js?ver=1.0:30 responseText: Fatal error: Call to undefined function get_avatar() in /home4/mifydnu/public_html/wp-content/plugins/hmm-test/hmm-test.php on line 8

Obviously, and perhaps unsurprisingly, nothing is known about the get_avatar() function. This makes sense - I'm just calling some PHP script via a URL. Makes no difference that the script is sitting in a Wordpress directory somewhere. But I am stumped at how to get around this.

Thanks for any advice!

  • 写回答

2条回答 默认 最新

  • doumi9618 2019-04-23 16:14
    关注

    Since you're sending your POST request directly to your PHP script -instead of using the AJAX API or the REST API- you're basically bypassing the entire WordPress core and so none of its functions are available to the script, hence the "Call to undefined function" error you're seeing now.

    Here's your code refactored so it uses the AJAX API instead so all WP functions are available to your script:

    Main plugin file:

    <?php
    /**
     * Plugin Name:  HMM Test
     */
    
    /**
     * Registers scripts and stylesheets.
     */
    function hmm_test_enqueue_scripts() {
        wp_register_script( 'test-js', plugins_url( '/js/test.js', __FILE__ ), array(), '1.0', true );
        wp_localize_script('test-js', 'wpVariables', array(
            'ajaxurl' => admin_url( 'admin-ajax.php' ),
            'userID' => 37
        ));
        wp_enqueue_script( 'test-js' );
    }
    add_action( 'wp_enqueue_scripts', 'hmm_test_enqueue_scripts' );
    
    /**
     * Registers the shortcode.
     */
    function my_test_contents() {
        echo "Wordpress functions test: get_avatar()";
        echo get_avatar( 37 );          # -- This works from the plugin script
    
        echo '<button type="button" class="test-button">Click to crash</button>';
    }
    add_shortcode( 'test-contents', 'my_test_contents' );
    
    /**
     * Handles the AJAX request.
     */
    function my_action() {
        $rv["payload"] = get_avatar(108);
        $rv["payload"] = "This is the payload message";
        $rv["status"]  = 'SUCCESS';
        echo json_encode($rv);
    
        wp_die(); // this is required to terminate immediately and return a proper response
    }
    add_action( 'wp_ajax_my_action', 'my_action' );
    

    test.js now becomes:

    (function () {
        var c = document.getElementsByClassName('test-button');
    
        for (var i = 0; i < c.length; i++ ) {
                c[i].addEventListener('click', doTest, false);
        }
    })();
    
    function doTest() {
    
        console.log("In doTest()");
    
        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 200) {
                console.log("responseText: " + this.responseText);
            }
        };
    
        var ajaxUrl = wpVariables.ajaxurl;
        var userid  = wpVariables.userID;
    
        xhttp.open("POST", ajaxUrl, true);
        xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    
        // The "action" parameter is the name of the (pardon the redundancy) "action" 
        // registered with "wp_ajax_" (see main plugin file for reference)
        //
        // You can name this whatever you want but make sure it's unique
        // to your plugin to avoid name collisions.
        let arg = "action=my_action" + "&userid=" + userid;
    
        console.log("Calling URL:" + ajaxUrl + " with arg: " + arg);
    
        xhttp.send(arg);
    
    }
    

    Important: There are no validations whatsoever (security nonces, $_POST variable checks, etc) which you should add to your code to make it more reliable/secure.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥50 永磁型步进电机PID算法
  • ¥15 sqlite 附加(attach database)加密数据库时,返回26是什么原因呢?
  • ¥88 找成都本地经验丰富懂小程序开发的技术大咖
  • ¥15 如何处理复杂数据表格的除法运算
  • ¥15 如何用stc8h1k08的片子做485数据透传的功能?(关键词-串口)
  • ¥15 有兄弟姐妹会用word插图功能制作类似citespace的图片吗?
  • ¥200 uniapp长期运行卡死问题解决
  • ¥15 latex怎么处理论文引理引用参考文献
  • ¥15 请教:如何用postman调用本地虚拟机区块链接上的合约?
  • ¥15 为什么使用javacv转封装rtsp为rtmp时出现如下问题:[h264 @ 000000004faf7500]no frame?