10

I'm trying to schedule a pseudo cron job to send an email after a set amount of time utilizing a WordPress plugin.

So far, I've been able to make this code run when I hard code the email address and message into the email_about_coupon() function. However, when I try to send the arguments to the function, the email is never sent.

By using the Cron GUI plugin, I'm able to see that the cron job is registered even with the arguments. I believe that I'm doing something incorrectly that does not allow the arguments to be used properly within the function at the time that it is run.

Here's what I have:

function schedule_email_cron($post_id)
{
    // Get the UNIX 30 days from now time
    $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)
{
    // Email text
    $text = "<html><body><p>Your coupon titled, ".$args['title']." is expiring soon. Please visit <a href=\"\">".get_bloginfo('siteurl')."/registered/</a> ".get_bloginfo('siteurl')."/registered/ to renew your coupon.</p></body></html>";

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

    // Send email
    wp_mail($args['email'], 'Renew Your Coupon Now!', $text, $h);
}

As always, thanks so much for your help!

7
  • What does a print_r($args, true) somewhere in the e-mail body result in?
    – kovshenin
    Apr 22, 2011 at 10:42
  • Thanks for the comment. I can try it, but I think the issue is that the email argument isn't being passed to the email_about_coupon function, therefore if I use print_r() in the body, I'll never get anything anyway. Is my thinking correct? I'll try hardcoding the email address, adding print_r to the body and see what happens. Thanks for the suggestion!
    – Sardine
    Apr 22, 2011 at 16:07
  • @Sardine, your thinking is correct, so yeh, put your e-mail address into the $to parameter of wp_mail and go for it. Cheers!
    – kovshenin
    Apr 22, 2011 at 16:21
  • I tried it and get, and interestingly, using print_r prints out the email address provided in args, but title does not print out. Also, in the text of the email, when I use $args['title'], it prints out as t, when the title is not t, not does it even contain t. Any thoughts?
    – Sardine
    Apr 22, 2011 at 16:49
  • Just to follow up on this, I ditched the strategy of trying to send args to the function that should run on the cron. Instead, I utilized a method of identifying posts that would need emails sent to their authors and did all of this within the email_about_coupons function. That way, I could get the data I need without sending anything to the function.
    – Sardine
    Apr 23, 2011 at 1:38

2 Answers 2

14

I think you have mismatch in how you pass arguments and how you expect it to work. You pass array of arguments to schedule and expect your hooked function to receive identical array of arguments. This is not the case.

Cron events are processed by do_action_ref_array(), which in turn passes arguments via call_user_func_array().

So your hooked function does not receive array of arguments, it receives multiple arguments - one for each element in your array.

So you need to either wrap array of arguments in array one more time or modify your function to process multiple arguments. Note that for letter you will also need to modify your add_action() call so that required number of arguments is passed instead of just one.

2
  • Thanks Rarst! It helped a lot! Is this how all add_action calls work when sending arrays of values. Surprisingly, with all of the WP work I've done, I've really only dealt with sending single arguments to functions via add_action calls.
    – tollmanz
    May 14, 2011 at 19:21
  • @Sardine action can be performed either by do_action() or by do_action_ref_array() and the difference is the way arguments are accepted by them. But you always have full set of arguments passed to actual hooked function.
    – Rarst
    May 14, 2011 at 20:23
19

Thanks to Rarst this makes a hell of a lot more sense now. So I've updated this post to elaborate the differences Rarst mentioned and upvoted his for shedding light on this ; )

Basically wp_schedule_single_event passes the arguments to your function through the variable args as shown in the codex. This variable "args" must be an array because each value in the array will be mapped to an argument in your call back function.

Example:

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 will go to $a, 1 will go to $b and 3 will go to $c. However passing three variables is only possible because of this line,

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

Looking at the codex for add_action you see that the fourth argument, 3, is what controls how many arguments are passed to the call back function. The default is 1.

So this example also works:

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

function example($a)
{

}

So here the array( 2, 1, 3) is assigned to just $a.

So Sardine's issue could be resolved with one line change where line 7,

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

becomes this instead,

$args = array(array('email' => $email, 'title' => $post->post_title));
3
  • This is neither hacky or bug. Former works exactly as it's supposed to. For latter you will need to modify your add_action() call so more arguments are passed instead of default one.
    – Rarst
    May 11, 2011 at 22:38
  • Thanks Thirlan! Rarst's answer definitely got the ball rolling and yours helped me further understand it. I upvoted you, but gave Rarst the accept for the answer. Also, I would need to modify the line that you suggested, but wouldn't I also need to add_action('email_about_coupon_action', 'email_about_coupon', 1, 1); to add_action('email_about_coupon_action', 'email_about_coupon', 1, 3); in order for the right number of arguments to be accepted?
    – tollmanz
    May 14, 2011 at 19:20
  • 1
    No you don't have to. $args = array(array( passes everything as a is a single array variable in this case.
    – Thirlan
    May 16, 2011 at 9:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.