Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

174
Vistas
Thread without access to WordPress functions

An Admin or Editor can send out emails to users via our WordPress Plugin customised to the individual so the emails are sent individually, this can make the page wait a while for the mailing process to finish. The plan is to multithreaded to return the user to the page and let the emails carry on sending on the server. The problem seems to be lack of access to WordPress' wp_mail() function from the thread's run() function. Calling wp-load.php does not seem to give access to WordPress functions.

Below is a simplified version of the threaded mailer. How do we use the wp-mail() function from the Test_Mailer thread?

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();

EDIT: If I try accessing a WordPress function nothing happens as shown below, which makes me think that WP is not loaded, but I do not get any errors in the PHP error log.

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'
over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

You're loading WordPress all over again with that require( '../../../wp-load.php' );. That's what Ajax is for.

The meat of the following example are the actions wp_ajax_ (logged users) and wp_ajax_nopriv_ (non logged users). These are the PHP actions to execute by a JavaScript call, in your case wp_mail().

You have to enqueue the JS file in the correct page and pass some variables via wp_localize_script (Ajax URL, security nonce, custom stuff).

It creates an admin page with a link that prompts for an email. The address is passed to the Ajax function that sends the email and returns true or false depending on wp_mail() result.

Example plugin:

<?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 ) );
}

JS file:

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 );
        });
    });
});
over 4 years ago · Santiago Trujillo Denunciar

0

When creating a new thread, pthreads will make a copy of all functions (as well as classes, interfaces, traits, etc) available from the current environment (unless selective inheritance flags have been used in Thread::start, of course). This means that if you have already included the wp-load.php file, then you do not need to include it again inside of the new thread (in Thread::run). (If you haven't included this file yet, then what you've done is fine.)

Looking at your example code, you are assigning the $emails parameter from the constructor to the $this->emails property. However, the foreach is attempting to iterate over the $this->email_array property, which will simply be null. So from your example code at least, it looks like the problem is with what property you're accessing, rather than the wp_mail function not being accessible.

With all that said, it does look like you're attempting to use pthreads in a web server environment. This has its own ramifications and is simply a bad idea. You'd be better off queueing such tasks (via RabbitMQ or something) to handle them elsewhere.

UPDATE (from your update):

Having a brief look through the WordPress codebase, I can see that threading simply isn't going to work here. The codebase is just incredibly unfriendly to such concurrency techniques.

The update_option function will not work because it relies upon a global DB connection. This connection cannot be used across different contexts (threads) - instead, a new connection must be created per thread.

The wp_mail function uses the get_bloginfo function, which in turn uses the get_option function, which in turn has a global for DB access. So you're going to have the same problem there as above.

Given the ubiquity of globals in the WordPress codebase, threading is simply not going to work here...

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda