Использование wp_schedule_single_event с аргументами для отправки email

22 апр. 2011 г., 03:33:02
Просмотры: 14.6K
Голосов: 10

Я пытаюсь запланировать псевдо-cron задачу для отправки email через определенное время с использованием плагина WordPress.

Пока мне удалось заставить этот код работать, когда я жестко прописываю email и сообщение прямо в функции email_about_coupon(). Однако при попытке передать аргументы в функцию email никогда не отправляется.

С помощью плагина Cron GUI я вижу, что cron-задача регистрируется даже с аргументами. Я предполагаю, что делаю что-то неправильно, из-за чего аргументы не передаются должным образом в функцию во время ее выполнения.

Вот мой код:

function schedule_email_cron($post_id)
{
    // Получаем UNIX-время через 30 дней от текущего момента
    $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 = "<html><body><p>Ваш купон с названием ".$args['title']." скоро истекает. Пожалуйста, посетите <a href=\"\">".get_bloginfo('siteurl')."/registered/</a> ".get_bloginfo('siteurl')."/registered/ чтобы продлить ваш купон.</p></body></html>";

    // Заголовки email
    $headers = array(
        'From: '.get_bloginfo('name').' <'.get_bloginfo('admin_email').'>',
        "Content-Type: text/html"
    );
    $h = implode("\r\n",$headers) . "\r\n";

    // Отправка email
    wp_mail($args['email'], 'Продлите ваш купон сейчас!', $text, $h);
}

Как всегда, огромное спасибо за помощь!

7
Комментарии

Что выведет print_r($args, true), если использовать его где-нибудь в теле письма?

kovshenin kovshenin
22 апр. 2011 г. 13:42:46

Спасибо за комментарий. Я могу попробовать, но думаю, проблема в том, что аргумент email не передается в функцию email_about_coupon, поэтому если я использую print_r() в теле письма, я все равно ничего не получу. Я правильно понимаю? Я попробую жестко прописать email-адрес, добавить print_r в тело письма и посмотреть, что получится. Спасибо за совет!

User User
22 апр. 2011 г. 19:07:46

@Sardine, ты правильно понимаешь, так что да, укажи свой email-адрес в параметре $to функции wp_mail и пробуй. Удачи!

kovshenin kovshenin
22 апр. 2011 г. 19:21:01

Я попробовал это сделать и получил интересный результат: при использовании print_r выводится указанный email из args, но заголовок не выводится. Кроме того, в тексте письма, когда я использую $args['title'], выводится просто t, хотя заголовок не "t" и даже не содержит букву "t". Какие могут быть мысли по этому поводу?

User User
22 апр. 2011 г. 19:49:27

Продолжая эту тему, я отказался от стратегии передачи args в функцию, которая должна выполняться по cron. Вместо этого я использовал метод идентификации постов, для которых нужно отправить письма их авторам, и сделал всё это внутри функции email_about_coupons. Таким образом, я смог получить нужные данные без передачи чего-либо в функцию.

User User
23 апр. 2011 г. 04:38:10

@Sardine пожалуйста, рассмотрите возможность добавить ваше решение в качестве ответа, если оно достаточно универсально, чтобы быть полезным для других. :)

Rarst Rarst
24 апр. 2011 г. 00:58:48

Rarst... это хорошая идея; однако, это довольно большой объем кода, и я не думаю, что он поместится в комментарии, а сам я не могу добавить ответ. Есть ли другой способ, которым я могу это сделать?

tollmanz tollmanz
24 апр. 2011 г. 01:05:01
Показать остальные 2 комментариев
Все ответы на вопрос 2
3
19

Спасибо Rarst, теперь всё стало намного понятнее. Поэтому я обновил этот пост, чтобы подробнее объяснить различия, о которых упомянул Rarst, и плюсанул его ответ за то, что он пролил свет на этот вопрос ; )

По сути, wp_schedule_single_event передает аргументы в вашу функцию через переменную args, как показано в codex. Эта переменная "args" должна быть массивом, потому что каждое значение в массиве будет сопоставлено с аргументом в вашей callback-функции.

Пример:

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 пойдет в $a, 1 — в $b, а 3 — в $c. Однако передача трех переменных возможна только благодаря этой строке:

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

Если посмотреть codex для add_action, то видно, что четвертый аргумент, 3, определяет, сколько аргументов будет передано в callback-функцию. По умолчанию значение равно 1.

Поэтому этот пример также работает:

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

function example($a)
{

}

Здесь массив array(2, 1, 3) просто присваивается переменной $a.

Таким образом, проблему Sardine можно решить одной строкой, заменив строку 7:

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

На это:

$args = array(array('email' => $email, 'title' => $post->post_title));
12 мая 2011 г. 00:54:27
Комментарии

Это не хак и не баг. Первое работает именно так, как и должно. Для второго вам нужно изменить вызов add_action(), чтобы передавалось больше аргументов вместо одного по умолчанию.

Rarst Rarst
12 мая 2011 г. 01:38:41

Спасибо, Thirlan! Ответ Rarst определенно дал старт решению, а твой помог мне понять его лучше. Я поставил тебе плюс, но отметил ответ Rarst как принятый. Также, мне нужно изменить строку, которую ты предложил, но разве мне не нужно также изменить add_action('email_about_coupon_action', 'email_about_coupon', 1, 1); на add_action('email_about_coupon_action', 'email_about_coupon', 1, 3);, чтобы принималось правильное количество аргументов?

tollmanz tollmanz
14 мая 2011 г. 22:20:14

Нет, не обязательно. $args = array(array( передает все как есть, в данном случае это одна переменная массива.

Thirlan Thirlan
16 мая 2011 г. 12:05:19
2
14

Я думаю, у вас есть несоответствие в том, как вы передаете аргументы и как ожидаете их работу. Вы передаете массив аргументов в расписание и ожидаете, что ваша подключенная функция получит идентичный массив аргументов. Но это не так.

События Cron обрабатываются функцией do_action_ref_array(), которая в свою очередь передает аргументы через call_user_func_array().

Таким образом, ваша подключенная функция не получает массив аргументов - она получает несколько аргументов, по одному для каждого элемента в вашем массиве.

Поэтому вам нужно либо обернуть массив аргументов в массив еще раз, либо изменить свою функцию для обработки нескольких аргументов. Обратите внимание, что для второго варианта вам также потребуется изменить вызов add_action(), чтобы передавалось необходимое количество аргументов, а не только один.

12 мая 2011 г. 01:35:03
Комментарии

Спасибо, Rarst! Это очень помогло! Значит ли это, что все вызовы add_action работают таким образом при передаче массивов значений? Удивительно, что за все время работы с WordPress мне приходилось иметь дело только с передачей отдельных аргументов в функции через вызовы add_action.

tollmanz tollmanz
14 мая 2011 г. 22:21:37

@Sardine Действие может быть выполнено либо через do_action(), либо через do_action_ref_array(), и разница заключается в способе передачи аргументов. Но у вас всегда есть полный набор аргументов, передаваемых в фактически подключенную функцию.

Rarst Rarst
14 мая 2011 г. 23:23:46