Php 无法访问WordPress函数的线程
管理员或编辑可以通过我们为个人定制的WordPress插件向用户发送电子邮件,以便单独发送电子邮件,这会使页面等待一段时间,等待邮件处理完成。计划是通过多线程将用户返回页面,并让电子邮件在服务器上继续发送。问题似乎是无法从线程的run()函数访问WordPress的wp_mail()函数。调用wp-load.php似乎无法访问WordPress函数 下面是线程邮件程序的简化版本。如何使用Test_Mailer线程中的wp-mail()函数Php 无法访问WordPress函数的线程,php,wordpress,pthreads,Php,Wordpress,Pthreads,管理员或编辑可以通过我们为个人定制的WordPress插件向用户发送电子邮件,以便单独发送电子邮件,这会使页面等待一段时间,等待邮件处理完成。计划是通过多线程将用户返回页面,并让电子邮件在服务器上继续发送。问题似乎是无法从线程的run()函数访问WordPress的wp_mail()函数。调用wp-load.php似乎无法访问WordPress函数 下面是线程邮件程序的简化版本。如何使用Test_Mailer线程中的wp-mail()函数 class Test_Mailer extends Th
class Test_Mailer extends Thread {
private $email;
public function __construct($emails, $subject, $message) {
$this->emails = $emails;
$this->subject = $subject;
$this->message = $message;
}
public function run() {
require( '../../../wp-load.php' );
foreach($this->emails as $email)
wp_mail( $email, $this->subject, $this->message);
}
}
$test_mailer = new test_mailer(array('test@test.com'), 'Subject', 'Message');
$test_mailer->start();
编辑:如果我尝试访问WordPress函数,没有发生如下所示的任何事情,这使我认为WP没有加载,但我在PHP错误日志中没有得到任何错误
class Test_Thread extends Thread {
public function run() {
update_option('test', 'two');
}
}
update_option('test', 'one');
$test_thread = new test_mailer();
$test_thread->start();
// test option is set to 'one'
您正在使用
require('../../../wp load.php')重新加载WordPress代码>。这就是为什么
以下示例的主要内容是操作wp\u ajax\uu
(已登录用户)和wp\u ajax\u nopriv\uu
(未登录用户)。在您的例子中,这些是通过JavaScript调用执行的PHP操作wp\u mail()
您必须将JS文件排列在正确的页面中,并通过wp\u localize\u script
(Ajax URL、安全性nonce、自定义内容)传递一些变量
它创建了一个管理员页面,其中包含一个提示输入电子邮件的链接。地址被传递给发送电子邮件的Ajax函数,并根据wp_mail()
结果返回true
或false
插件示例:
创建新线程时,pthreads将使当前环境中的所有函数(以及类、接口、特征等)的副本可用(当然,除非在thread::start
中使用了选择性继承标志)。这意味着,如果您已经包含了wp load.php
文件,则不需要在新线程中再次包含它(在thread::run
中)。(如果您尚未包含此文件,那么您所做的就可以了。)
查看示例代码,您正在将构造函数中的$emails
参数分配给$this->emails
属性。但是,foreach
正在尝试迭代$this->email\u数组
属性,该属性将为null
。因此,至少从您的示例代码来看,问题似乎在于您正在访问的属性,而不是wp\u mail
函数无法访问
综上所述,看起来您确实在尝试在web服务器环境中使用pthreads。这有其自身的影响,只是一个坏主意。您最好将此类任务排队(通过RabbitMQ或其他方式)以便在其他地方处理它们
更新(来自您的更新):
简单地浏览一下WordPress代码库,我可以看出线程在这里根本不起作用。代码库对这种并发技术非常不友好
update\u选项
功能将不起作用,因为它依赖于全局数据库连接。此连接不能跨不同的上下文(线程)使用-相反,必须为每个线程创建一个新连接
wp\u mail
函数使用get\u bloginfo
函数,该函数反过来使用get\u选项
函数,该函数反过来具有全局数据库访问权限。所以你会遇到和上面一样的问题
鉴于globals在WordPress代码库中无处不在,线程在这里根本不起作用……我把$email\u数组这件事搞错了,我简化了代码,在这里发布。当运行线程WordPress已经加载,但线程无法调用WP函数时,我添加了一个编辑,带有一个我刚刚尝试过的测试线程,它调用线程中的update_选项,而该选项没有进行它应该进行的更改。删除第一个update_选项时,DB中的值保持不变。我想问题是线程看不到WP函数,因为它的小线程WP没有加载,也许我错了。@PeterBushnell我已经根据你的更新更新了我的答案。谢谢你的澄清。我热衷于使用已过滤的wp_邮件,将取消订阅链接添加到每封电子邮件中。我将使用更传统的解决方案,如AJAX,并更新页面,以向管理员显示工作正在进行中,而不是离开页面。
<?php
/**
* Plugin Name: (B5F) Test Email
* Version: 1.0
* Author: brasofilo
*/
add_action('admin_menu', 'add_menu_43678305');
add_action( 'wp_ajax_mail_43678305', 'mail_43678305' );
add_action( 'wp_ajax_nopriv_mail_43678305', 'mail_43678305' );
function add_menu_43678305() {
$page = add_menu_page(
'sendMail',
'<span style="color:#d00;">Send Mail</span>',
'read',
'send-mail',
'menu_page_43678305',
'http://i.imgur.com/Vk42k.png',
6 // position, just after Posts
);
add_action( "admin_print_scripts-$page", 'enqueue_scripts_43678305' );
}
function enqueue_scripts_43678305(){
wp_enqueue_script(
'ajax_script',
plugins_url('/ajax_43678305.js',__FILE__),
array('jquery'),
TRUE
);
wp_localize_script(
'ajax_script',
'myAjax',
array(
'url' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( "nonce_43678305" ),
)
);
}
function menu_page_43678305() {
echo '<h4><a href="#" id="send-mail">TEST AJAX</a></h4>';
}
function mail_43678305(){
check_ajax_referer( 'nonce_43678305', 'nonce' );
if( true ) { // Dummy test
$sent = wp_mail( $_POST['email'], "Subject", "message" );
wp_send_json_success( $sent );
}
else
wp_send_json_error( array( 'error' => $custom_error ) );
}
jQuery(document).ready(function($) {
$('#send-mail').click(function(e) {
e.preventDefault();
var email = window.prompt('Email?');
if ( email === '' || email === null )
return;
var data = {
action: 'mail_43678305', // Ajax PHP function
nonce: myAjax.nonce, // security, passed via wp_localize_script
email: email
};
$.post( myAjax.url, data, function( response ) {
$('#send-mail').html( response.data );
});
});
});