Php 无法访问WordPress函数的线程

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

管理员或编辑可以通过我们为个人定制的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'

您正在使用
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 );
        });
    });
});