我正在尝试从PHP脚本调用WordPress函数(get_avatar($ id)),该PHP脚本正在从排队的javascript文件的ajax引用调用中访问。 (说这种负荷已经使我的头部受伤了。)
作为一个例子,我为WordPress创建了一个插件:hmm-test。它在hmm-test.php中实现。该脚本排队一个javascript文件:test.js。在js内,我有一个xhttprequest调用,该调用将POSTS发送到hmm-test.php,该分支会基于POST变量的测试。
当hmm-test.php作为GET调用时,例如,使用嵌入了短代码的页面的WordPress URL,我可以调用WordPress函数。在POST分支中,我还希望能够调用WordPress本机函数,并将其作为JSON有效负载的一部分返回。
所以我的问题是:我可以将hmm-test.php的'POST'分支设为'wordpress-aware'以便可以在其中调用本地WP函数吗?
我被卡住了-不知道还能尝试什么。我尝试尽早创建一个REST端点以通过Ajax URL进行调用,但一直遇到身份验证问题。如果这行得通,我可以花一些时间来完成它,但是我发现OAuth有点棘手。我让它为别的东西工作,但失去了它。如果有一种方法可以通过简单的POST完成,那对我的概念证明就足够了。
这是插件PHP脚本和排队的javascript的全部内容:
<?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>';
}
}
还有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);
}
当我将简短代码[hmm-test]放在Wordpress页面中时,它加载正常,并且得到了预期的'Wordpress functions test ...',这是用户37的正确头像图片(在此示例中为硬编码) ),然后单击使事情崩溃的按钮(暂时!)。
单击按钮,我看到这是控制台窗口:
在doTest()test.js?ver = 1.0:40中调用 网址:https://not-my-real-url.com/wp-content/plugins/hmm-test/hmm-test.php 带有arg:action = update&userid = 37 test.js?ver = 1.0:30 responseText:致命错误:调用未定义函数get_avatar() /home4/mifydnu/public_html/wp-content/plugins/hmm-test/hmm-test.php 在第 8
行
显然,也许并不奇怪,关于get_avatar()函数一无所知。这很有意义-我只是通过URL调用一些PHP脚本。脚本位于某个地方的Wordpress目录中没有任何区别。但是我为如何解决这个问题而感到困惑。
谢谢您的建议!
答案 0 :(得分:0)
您需要使用Wordpress的ajax脚本。它涉及将代码编写为函数,并使用WordPress挂钩将其附加到WP ajax脚本。参见{{3}}。
这样做的一个很大好处是,某些站点具有适当的安全设置,将不允许直接访问插件中的php文件,除非您使用此内置方法,否则这将破坏AJAX。在我们新的安全性插件破解它之后,我不得不转换一个非常大的插件才能使用此方法。结果实际上为我减少了很多编码,并提高了稳定性和更好的性能。
答案 1 :(得分:0)
由于您将POST
请求直接发送到PHP脚本(而不是使用AJAX API或REST API),因此基本上绕过了整个WordPress核心,因此它的所有功能都无法使用脚本,因此您现在看到的“调用未定义函数”错误。
这是重构的代码,因此它使用AJAX API,因此所有WP函数都可用于您的脚本:
主插件文件:
<?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
现在变为:
(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);
}
重要:没有任何验证(安全随机数,$ _ POST变量检查等)应添加到代码中,以使其更加可靠/安全。