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条)

报告相同问题?

悬赏问题

  • ¥15 网站出现错误跳转问题
  • ¥15 Docker容器里已经安装了ssh,但打包迁移到新机器一直容器一直提示unrecognized service。
  • ¥15 综合布线实例设计,就好看好看不恐怖可好滤镜好聚
  • ¥15 使用moviepy库视频合并时出错
  • ¥30 FLUENT液固传质UDF
  • ¥15 怎么看梯度直方图以,怎么判断梯度消失/爆炸,怎么解决
  • ¥15 aspnetdll文件访问拒绝
  • ¥15 wpf中在模版中寻找元素
  • ¥15 MFC平台生成指定圆
  • ¥15 jmeter出现403