管理员或编辑可以通过我们为个人定制的WordPress插件向用户发送电子邮件,以便电子邮件单独发送,这可以使页面等待一段时间以完成邮件处理。计划是多线程将用户返回到页面并让电子邮件继续在服务器上发送。问题似乎是缺少从线程的run()函数访问WordPress的'wp_mail()函数。调用wp-load.php似乎无法访问WordPress函数。
以下是线程邮件的简化版本。我们如何使用Test_Mailer线程中的wp-mail()函数?
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'
答案 0 :(得分:1)
您正在使用require( '../../../wp-load.php' );
重新加载WordPress。这就是Ajax的用途。
以下示例的内容是操作wp_ajax_
(已记录的用户)和wp_ajax_nopriv_
(未记录的用户)。这些是通过JavaScript调用执行的PHP操作,在您的情况下为wp_mail()
。
您必须将JS文件排入正确的页面,并通过wp_localize_script
(Ajax URL,安全现时,自定义内容)传递一些变量。
它会创建一个管理页面,其中包含提示输入电子邮件的链接。该地址将传递给发送电子邮件的Ajax函数,并根据true
结果返回false
或wp_mail()
。
<?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 );
});
});
});
答案 1 :(得分:1)
在创建新线程时,pthreads将复制当前环境中可用的所有函数(以及类,接口,特征等)(除非在Thread::start
中使用了选择性继承标志,课程)。这意味着如果您已经包含wp-load.php
文件,那么您不需要在新线程(Thread::run
)内再次包含它。 (如果你还没有包含这个文件,那么你所做的很好。)
查看示例代码,您将构造函数中的$emails
参数分配给$this->emails
属性。但是,foreach
正在尝试迭代$this->email_array
属性,该属性只是null
。因此,至少从您的示例代码来看,问题在于您正在访问的属性,而不是wp_mail
函数无法访问。
尽管如此,看起来你似乎试图在Web服务器环境中使用pthread。这有其自身的影响,简直是一个坏主意。你最好排队这些任务(通过RabbitMQ或其他东西)在其他地方处理它们。
更新(来自您的更新):
简要介绍一下WordPress代码库,我可以看到线程在这里根本不起作用。代码库对这种并发技术非常不友好。
update_option
函数不起作用,因为它依赖于全局数据库连接。此连接不能在不同的上下文(线程)中使用 - 相反,必须为每个线程创建一个新连接。
wp_mail
函数使用get_bloginfo
函数,后者又使用get_option
函数,该函数又具有全局数据库访问权限。因此,您将遇到与上述相同的问题。
鉴于WordPress代码库中全局变量无处不在,线程在这里根本不起作用......