Вопрос или проблема
У меня есть следующий код, который должен выполняться при первом опубликовании нового поста, проверять, есть ли данные в пользовательском поле ‘specific_users’ (это использует Advanced Custom Fields), и если да, отправить электронное письмо каждому из выбранных пользователей.
/**
* Отправить пользователям уведомление о новых постах фермеров
*/
function notify_growers($post) {
// Уведомлять только для постов фермеров
if ( $post->post_type != 'grower_posts' ) return;
$post_id = $post->ID;
// ...выполнять код один раз
if ( !get_post_meta( $post_id, 'emailsent', $single = true ) ) {
$specific_users = get_field('specific_users',$post_id);
if(isset($specific_users) && is_array($specific_users)) {
foreach($specific_users as $specific_user) {
$to = $specific_user['user_email'];
$subject="Новости фермеров: " . get_the_title($post_id);
$message="";
$message .= '' . get_the_excerpt($post_id) . '…
';
$message .= '';
wp_mail($to, $subject, $message );
}
unset($specific_user);
} else { return; }
// Убедитесь, что это не выполнится снова
update_post_meta( $post_id, 'emailsent', true );
}
}
add_action( 'draft_to_publish', 'notify_growers' );
add_action( 'new_to_publish', 'notify_growers' );
Письма не отправляются, и я не уверен, как это отладить.
Дополнительный вопрос: является ли отправка электронного письма в цикле foreach лучшим способом сделать это? Или мне следует сделать это сразу с помощью BCC каким-то образом?
Спасибо,
Ангус
Вы знаете, работает ли ваша функция wp_mail()
вообще?
Знаете ли вы, не терпит ли неудачу ваша функция выше по цепочке?
Я бы переписал функцию так, что это немного упростит чтение и также немного повысит эффективность, поскольку мы выполняем только те функции, которые нам абсолютно необходимы при выполнении определенного условия.
Также я убрал вызов функции get_field()
, который является всего лишь оберткой для get_post_meta()
.
Сохранение $post_id = $post->ID
также было удалено, поскольку на этом этапе нет необходимости манипулировать или кэшировать ID по какой-либо конкретной причине, так что это немного упрощает код.
Если вы знаете, что ваш вызов к пользовательскому полю specific_users
возвращает сериализованный массив, то вы можете добавить параметр true
после meta_key
, чтобы получить несериализованный массив, в противном случае опустите значение true
.
isset
вернет true, даже если массив пуст, и ЕСЛИ в массиве нет результатов, WordPress фактически вернет пустой массив, если только параметр true
не установлен, в этом случае он вернет пустую строку, поэтому вызов isset
был удален и заменен на !empty($array)
.
С этого момента вы можете немного легче отладить функцию…
function notify_growers($post) {
//если НЕ тип поста 'grower_posts', выходите;
if ( $post->post_type != 'grower_posts' )
return;
//если электронное письмо уже отправлено, выходите.
if ( get_post_meta( $post->ID, 'emailsent', true ) )
return;
//если письмо не отправлено, то получите массив пользователей для отправки письма
$specific_users = get_post_meta($post->ID, 'specific_users');
//если $specific_users является массивом и не пустой, то отправьте электронное письмо.
if(is_array($specific_users) && !empty($specific_users)) {
foreach($specific_users as $specific_user) {
//добавить логику почты здесь, $to, $subject, $message
wp_mail($to, $subject, $message );
}
unset($specific_user);
//предотвратить отправку писем, обновив метаполе поста
update_post_meta( $post->ID, 'emailsent', true );
}
}
add_action( 'draft_to_publish', 'notify_growers' );
add_action( 'new_to_publish', 'notify_growers' );
Вы также можете отлаживать внутри вашей функции. Запишите данные переменных во временное хранилище с помощью стандартных функций WordPress, таких как set_transient()
или отлаживайте в консоли вашего браузера. Вы можете использовать плагин Debug Objects для записи из php в консоль Webinspector в Chrome.
Возможно, хорошая идея добавить exit();
перед закрывающими скобками функции, чтобы создать вывод через возможности php, такие как var_dump()
и остановить функцию для удобочитаемости на экране.
Вы найдете больше подсказок на источнике в этом файле плагина, используйте функцию wp_mail()
также для работы с информацией о постах. Возможно, это небольшая подсказка, как это возможно.
Ответ или решение
Отправка уведомлений пользователям при публикации постов в WordPress
Ваша задача заключается в отправке уведомлений по электронной почте определенным пользователям при публикации новых постов типа ‘grower_posts’. Давайте разберем вашу реализацию кода и предложим корректировки для улучшения его работы.
Проблемы в исходном коде
-
Проверка отправки email: Ваша логика проверки на предмет уже отправленных писем с использованием мета-поля
'emailsent'
в целом правильная, но вы не используете стандартные функции WordPress в оптимальном порядке. -
Получение списка пользователей: Обращение к пользовательскому полю
'specific_users'
не совсем корректно. Если это массив, важно убедиться, что он существует и не пуст. -
Отправка писем: Использование функции
wp_mail()
внутри циклаforeach
является приемлемым, но в случае большого количества пользователей это может вызвать проблемы с производительностью и временем выполнения скрипта. -
Отладка: Не хватает механизма для отслеживания ошибок и состояния выполнения.
Улучшенный код функции
Вот улучшенная версия вашей функции с учетом вышеперечисленных моментов:
/**
* Уведомление пользователей о новых публикациях постов о производителях
*/
function notify_growers($post) {
// Проверка типа поста
if ($post->post_type != 'grower_posts') {
return;
}
// Проверка, было ли уже отправлено уведомление
if (get_post_meta($post->ID, 'emailsent', true)) {
return;
}
// Получение массива пользователей
$specific_users = get_post_meta($post->ID, 'specific_users', true); // Используем параметр true для получения правильного формата
// Проверка на пустоту массива
if (!empty($specific_users) && is_array($specific_users)) {
$to = [];
foreach ($specific_users as $specific_user) {
// Предполагаем, что $specific_user — это массив с ключом 'user_email'
if (!empty($specific_user['user_email'])) {
$to[] = $specific_user['user_email'];
}
}
if (!empty($to)) {
$subject = "Grower News: " . get_the_title($post->ID);
$message = "<p>" . get_the_excerpt($post->ID) . "…</p>";
$message .= "<p><a href=\"" . get_permalink($post->ID) . "\"><strong>Continue Reading »</strong></a></p>";
// Отправка email с использованием BCC
wp_mail(implode(',', $to), $subject, $message);
}
// Обновление мета-поля, чтобы не отправлять повторно
update_post_meta($post->ID, 'emailsent', true);
}
}
add_action('draft_to_publish', 'notify_growers');
add_action('new_to_publish', 'notify_growers');
Рекомендации по оптимизации email-отправки
-
Использование BCC: Объединение всех адресов электронной почты в одну строку с использованием запятых (как в примере выше) эффективно обрабатывает рассылку одним вызовом
wp_mail()
. -
Логи для отладки: Рассмотрите возможность добавления логирования, чтобы отслеживать, какие действия выполняются. Вы можете использовать функцию
error_log()
для записи сообщений в файл журнала ошибок вашего сервера. -
Отладка через
var_dump()
илиset_transient()
: Вы можете использовать функциюset_transient()
для временного сохранения данных и последующего их просмотра, что может быть полезно для отладки.
Заключение
Приведенный выше код более структурирован и исправлен. Он учитывает все важные аспекты работы с WordPress и должен помочь вам в отправке уведомлений пользователям при публикации новых постов. Если проблемы сохраняются, обратите внимание на возможные ошибки в серверных логах или проверьте, работает ли функция wp_mail()
корректно на вашем сервере.