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 易语言把MYSQL数据库中的数据添加至组合框
  • ¥20 求数据集和代码#有偿答复
  • ¥15 关于下拉菜单选项关联的问题
  • ¥20 java-OJ-健康体检
  • ¥15 rs485的上拉下拉,不会对a-b<-200mv有影响吗,就是接受时,对判断逻辑0有影响吗
  • ¥15 使用phpstudy在云服务器上搭建个人网站
  • ¥15 应该如何判断含间隙的曲柄摇杆机构,轴与轴承是否发生了碰撞?
  • ¥15 vue3+express部署到nginx
  • ¥20 搭建pt1000三线制高精度测温电路
  • ¥15 使用Jdk8自带的算法,和Jdk11自带的加密结果会一样吗,不一样的话有什么解决方案,Jdk不能升级的情况