Uso de wp_schedule_single_event con argumentos para enviar correos

22 abr 2011, 03:33:02
Vistas: 14.6K
Votos: 10

Estoy intentando programar un trabajo cron pseudo-automático para enviar un correo electrónico después de un tiempo determinado utilizando un plugin de WordPress.

Hasta ahora, he logrado que este código funcione cuando ingreso manualmente la dirección de correo y el mensaje en la función email_about_coupon(). Sin embargo, cuando intento enviar los argumentos a la función, el correo nunca se envía.

Usando el plugin Cron GUI, puedo ver que el trabajo cron se registra incluso con los argumentos. Creo que estoy haciendo algo incorrectamente que no permite que los argumentos se utilicen adecuadamente dentro de la función cuando se ejecuta.

Esto es lo que tengo:

function schedule_email_cron($post_id)
{
    // Obtener el tiempo UNIX para 30 días después
    $thirty_days = time() + 60; // (30 * 24 * 60 * 60)
    $post = get_post($post_id);
    $email = get_the_author_meta('user_email', $post->post_author);
    $args = array('email' => $email, 'title' => $post->post_title);
    wp_schedule_single_event($thirty_days, 'email_about_coupon_action', $args); 
}

add_action('save_post', 'schedule_email_cron', 1, 1);

add_action('email_about_coupon_action', 'email_about_coupon', 1, 1);

function email_about_coupon($args)
{
    // Texto del email
    $text = "<html><body><p>Tu cupón titulado ".$args['title']." está por expirar. Por favor visita <a href=\"\">".get_bloginfo('siteurl')."/registered/</a> ".get_bloginfo('siteurl')."/registered/ para renovar tu cupón.</p></body></html>";

    // Cabeceras del email
    $headers = array(
        'From: '.get_bloginfo('name').' <'.get_bloginfo('admin_email').'>',
        "Content-Type: text/html"
    );
    $h = implode("\r\n",$headers) . "\r\n";

    // Enviar email
    wp_mail($args['email'], '¡Renueva Tu Cupón Ahora!', $text, $h);
}

¡Como siempre, muchas gracias por tu ayuda!

7
Comentarios

¿Qué resulta de poner un print_r($args, true) en algún lugar del cuerpo del correo electrónico?

kovshenin kovshenin
22 abr 2011 13:42:46

Gracias por el comentario. Puedo intentarlo, pero creo que el problema es que el argumento del correo no se está pasando a la función email_about_coupon, por lo tanto si uso print_r() en el cuerpo, nunca obtendré nada de todos modos. ¿Es correcto mi razonamiento? Intentaré codificar manualmente la dirección de correo, agregaré print_r al cuerpo y veré qué sucede. ¡Gracias por la sugerencia!

User User
22 abr 2011 19:07:46

@Sardine, tu razonamiento es correcto, así que sí, coloca tu dirección de correo en el parámetro $to de wp_mail y adelante. ¡Saludos!

kovshenin kovshenin
22 abr 2011 19:21:01

Lo probé y obtengo, curiosamente, que usando print_r muestra la dirección de correo proporcionada en args, pero el título no se muestra. Además, en el texto del correo, cuando uso $args['title'], se muestra como t, cuando el título no es t, ni siquiera contiene t. ¿Alguna idea?

User User
22 abr 2011 19:49:27

Solo para seguir con esto, abandoné la estrategia de intentar enviar args a la función que debería ejecutarse en el cron. En su lugar, utilicé un método para identificar los posts que necesitarían enviar correos a sus autores e hice todo esto dentro de la función email_about_coupons. De esa manera, pude obtener los datos que necesitaba sin enviar nada a la función.

User User
23 abr 2011 04:38:10

@Sardine por favor considera agregar tu solución como respuesta si es lo suficientemente genérica como para ser útil para otros. :)

Rarst Rarst
24 abr 2011 00:58:48

Rarst...esa es una buena idea; sin embargo, es una cantidad considerable de código y no creo que quepa en un comentario y no puedo agregar una respuesta yo mismo. ¿Hay otra forma en que pueda hacerlo?

tollmanz tollmanz
24 abr 2011 01:05:01
Mostrar los 2 comentarios restantes
Todas las respuestas a la pregunta 2
3
19

Gracias a Rarst, esto ahora tiene mucho más sentido. Así que he actualizado esta publicación para elaborar las diferencias que mencionó Rarst y he votado positivamente su respuesta por arrojar luz sobre esto ;)

Básicamente, wp_schedule_single_event pasa los argumentos a tu función a través de la variable args como se muestra en el codex. Esta variable "args" debe ser un array porque cada valor en el array se mapeará a un argumento en tu función de callback.

Ejemplo:

add_action('example_action', 'example', 1, 3);
$args = array ( 2, 1, 3 );
wp_schedule_single_event(time(), 'example_action', $args);

function example($a, $b, $c)
{

}

2 irá a $a, 1 irá a $b y 3 irá a $c. Sin embargo, pasar tres variables solo es posible gracias a esta línea:

add_action('example_action', 'example', 1, 3);

Si miras el codex para add_action, verás que el cuarto argumento, 3, es lo que controla cuántos argumentos se pasan a la función de callback. El valor predeterminado es 1.

Así que este ejemplo también funciona:

add_action('example_action', 'example');
$args = array ( array( 2, 1, 3 ) );
wp_schedule_single_event(time(), 'example_action', $args);

function example($a)
{

}

Aquí, el array( 2, 1, 3) se asigna solo a $a.

Por lo tanto, el problema de Sardine podría resolverse con un cambio en la línea 7, donde:

$args = array('email' => $email, 'title' => $post->post_title);

se convierte en esto:

$args = array(array('email' => $email, 'title' => $post->post_title));
12 may 2011 00:54:27
Comentarios

Esto no es un truco ni un error. El primero funciona exactamente como se supone que debe. Para el segundo, necesitarás modificar tu llamada a add_action() para que se pasen más argumentos en lugar del predeterminado.

Rarst Rarst
12 may 2011 01:38:41

¡Gracias Thirlan! La respuesta de Rarst definitivamente puso las cosas en marcha y la tuya me ayudó a entenderlo mejor. Te di un voto positivo, pero le di a Rarst la aceptación por la respuesta. Además, necesitaría modificar la línea que sugeriste, pero ¿no tendría que cambiar también add_action('email_about_coupon_action', 'email_about_coupon', 1, 1); a add_action('email_about_coupon_action', 'email_about_coupon', 1, 3); para que se acepte el número correcto de argumentos?

tollmanz tollmanz
14 may 2011 22:20:14

No es necesario. $args = array(array( pasa todo como una única variable de matriz en este caso.

Thirlan Thirlan
16 may 2011 12:05:19
2
14

Creo que tienes una discrepancia en cómo pasas los argumentos y cómo esperas que funcione. Pasas un array de argumentos para programar y esperas que tu función enganchada reciba el mismo array de argumentos. Este no es el caso.

Los eventos Cron son procesados por do_action_ref_array(), que a su vez pasa los argumentos a través de call_user_func_array().

Así que tu función enganchada no recibe un array de argumentos, recibe múltiples argumentos - uno por cada elemento en tu array.

Por lo tanto, necesitas envolver el array de argumentos en otro array o modificar tu función para procesar múltiples argumentos. Ten en cuenta que para lo último también necesitarás modificar tu llamada a add_action() para que se pase el número requerido de argumentos en lugar de solo uno.

12 may 2011 01:35:03
Comentarios

¡Gracias Rarst! ¡Fue de gran ayuda! ¿Es así como funcionan todas las llamadas add_action cuando se envían arrays de valores? Sorprendentemente, con todo el trabajo que he hecho en WP, realmente solo he trabajado con el envío de argumentos individuales a funciones mediante llamadas add_action.

tollmanz tollmanz
14 may 2011 22:21:37

@Sardine la acción puede ejecutarse mediante do_action() o mediante do_action_ref_array() y la diferencia está en la forma en que aceptan los argumentos. Pero siempre tienes el conjunto completo de argumentos pasados a la función enganchada real.

Rarst Rarst
14 may 2011 23:23:46