WordPress. Обработка POST-запросов. Часть 1
В процессе загрузки WordPress происходит множество событий. К каждому из этих событий можно привязать функцию, которая выполнит какое-то действие (action
) или изменит данные (filter
). Отправка формы не является исключением — мы можем «прицепить» свою функцию к подходящему хуку и обработать POST-данные.
Кодекс WordPress говорит, что данные формы нужно отправлять на admin-post.php
в директории wp-admin
. А сама форма должна содержать поле action
. Посмотрим на исходный код этого скрипта:
if (!defined('WP_ADMIN')) { define('WP_ADMIN', true); } if (defined('ABSPATH')) { require_once(ABSPATH . 'wp-load.php'); } else { require_once(dirname(dirname(__FILE__)) . '/wp-load.php'); } send_origin_headers(); require_once(ABSPATH . 'wp-admin/includes/admin.php'); nocache_headers(); do_action('admin_init'); $action = empty($_REQUEST['action']) ? '' : $_REQUEST['action']; if (!wp_validate_auth_cookie()) { // если пользователь не авторизован if (empty($action)) { do_action('admin_post_nopriv'); } else { do_action('admin_post_nopriv_'.$action); } } else { // если пользователь авторизован if (empty($action)) { do_action('admin_post'); } else { do_action('admin_post_'.$action); } }
Все очень просто:
- когда пользователь не авторизован
- если
action
не установлен, происходит событиеadmin_post_nopriv
- если
action
установлен, происходит событиеadmin_post_nopriv_{action}
- если
- когда пользователь авторизован
- если
action
не установлен, происходит событиеadmin_post
- если
action
установлен, происходит событиеadmin_post_{action}
- если
Все вышеописанные хуки можно применить и для GET запроса, если адрес примерно такой:
http://www.server.com/wp-admin/admin-post.php?action=some_action&data=some_data
Плагин «Форма обратной связи»
Давайте применим полученные знания на практике и создадим плагин, который позволит добавить на сайт форму обратной связи. Создаем директорию tokmakov-feedback
и внутри нее — файл tokmakov-feedback.php
.
<?php /* Plugin Name: Форма обратной связи Plugin URI: https://tokmakov.msk.ru Description: Регистрирует шорткод [tokmakov-feedback] для формы обратной связи, отправляет сообщения на почту. Version: 1.0 Author: Евгений Токмаков Author URI: https://tokmakov.msk.ru */ register_activation_hook(__FILE__, function() { // проверяем права пользователя на активацию плагинов if (!current_user_can('activate_plugins')) { return; } }); register_deactivation_hook(__FILE__, function() { // проверяем права пользователя на деактивацию плагинов if (!current_user_can('deactivate_plugins')) { return; } });
Для начала зарегистрируем шорткод [tokmakov-feedback]
:
/* * Регистрируем шорткод [tokmakov-feedback], который позволит * вставить форму обратной связи на страницу или запись блога */ add_shortcode('tokmakov-feedback', function () { ob_start(); ?> <div class="tokmakov-feedback"> <div class="response"></div> <form action="<?= admin_url('admin-post.php'); ?>" method="post"> <input type="hidden" name="action" value="tokmakov_feedback" /> <input type="hidden" name="redirect" value="<?= get_permalink(); ?>" /> <label for="name"> <span>Имя</span> <input type="text" name="name" value="" required /> </label> <label for="email"> <span>Email</span> <input type="text" name="email" value="" required /> </label> <label for="phone"> <span>Телефон</span> <input type="text" name="phone" value="" /> </label> <label for="message"> <span>Сообщение</span> <textarea name="message" required></textarea> </label> <input type="submit" value="Отправить" /> </form> </div> <?php return ob_get_clean(); });
У нас есть скрытое поле формы action
со значением tokmakov_feedback
— значит, нам доступны два хука:
admin_post_nopriv_tokmakov_feedback
admin_post_tokmakov_feedback
Форму мы должны обработать независимо от того, залогинился пользователь или нет:
/* * Обрабатываем отправленные данные формы обратной связи */ add_action('admin_post_nopriv_tokmakov_feedback', 'tokmakov_process_feedback_form'); add_action('admin_post_tokmakov_feedback', 'tokmakov_process_feedback_form'); function tokmakov_process_feedback_form() { /* * Здесь уже можно обрабатывать массивы $_POST или $_GET */ }
Что ж, давайте напишем функцию, которая будет обрабатывать данные формы и отправлять письмо администратору:
function tokmakov_process_feedback_form() { /* * Обрабатываем данные, полученные из формы */ $data['name'] = trim(iconv_substr(strip_tags($_POST['name']), 0, 50)); $data['email'] = trim(iconv_substr(strip_tags($_POST['email']), 0, 50)); $data['phone'] = trim(iconv_substr(strip_tags($_POST['phone']), 0, 50)); $data['message'] = trim(iconv_substr(strip_tags($_POST['message']), 0, 1000)); // были допущены ошибки при заполнении формы? if (empty($data['name'])) { $errors[] = 'Не заполнено обязательное поле «Имя»'; } if (empty($data['email'])) { $errors[] = 'Не заполнено обязательное поле «E-mail»'; } if (empty($data['message'])) { $errors[] = 'Не заполнено обязательное поле «Сообщение»'; } if (!empty($errors)) { /* * были допущены ошибки при заполнении формы, сохраняем введенные * пользователем данные, чтобы после редиректа снова показать форму, * заполненную введенными ранее даннными и сообщением об ошибке */ $_SESSION['tokmakov_feedback']['success'] = false; $message = 'При заполнении формы были допущены ошибки'; $_SESSION['tokmakov_feedback']['message'] = $message; $_SESSION['tokmakov_feedback']['errors'] = $errors; $_SESSION['tokmakov_feedback']['data'] = $data; } else { // отправляем письмо администратору if (tokmakov_sendmail($data)) { $_SESSION['tokmakov_feedback']['success'] = true; $message = 'Ваше сообщение успешно отправлено'; $_SESSION['tokmakov_feedback']['message'] = $message; } else { $_SESSION['tokmakov_feedback']['success'] = false; $message = 'Произошла ошибка при отправке письма'; $_SESSION['tokmakov_feedback']['message'] = $message; $_SESSION['tokmakov_feedback']['data'] = $data; } } // после отправки формы делаем редирект, чтобы предотвратить // повторную отправку, если пользователь обновит страницу $redirect = home_url(); if (isset($_POST['redirect'])) { $redirect = $_POST['redirect']; $redirect = wp_validate_redirect($redirect, home_url()); } wp_redirect($redirect); die(); }
function tokmakov_sendmail($data) { $message = 'Имя: ' . $data['name'] . PHP_EOL; $message .= 'E-mail: ' . $data['email'] . PHP_EOL; if (!empty($data['phone'])) { $message .= 'Телефон: ' . $data['phone'] . PHP_EOL; } $message .= PHP_EOL . 'Сообщение: ' . PHP_EOL . $data['message'] . PHP_EOL; $result = wp_mail( get_bloginfo('admin_email'), 'Заполнена форма обратной связи', $message ); return $result; }
Как видите, функция проверяет корректность данных и записывает результат проверки в сессию. Чтобы после редиректа показать результаты проверки пользователю. Если форма содержит ошибки, в сессию будут также записаны введенные пользователем данные. Будет некрасиво, если пользователь потратил время, чтобы написать сообщение, а мы это сообщение потеряем при проверке.
А теперь доработаем функцию, которая регистрирует шорткод. Кроме самой формы, она будет показывать сообщения об ошибках или сообщение об успешной отправке:
/* * Регистрируем шорткод [tokmakov-feedback], который позволит * вставить форму обратной связи на страницу или запись блога */ add_shortcode('tokmakov-feedback', function () { $name = ''; $email = ''; $phone = ''; $message = ''; if (isset($_SESSION['tokmakov_feedback']['data'])) { $name = htmlspecialchars($_SESSION['tokmakov_feedback']['data']['name']); $email = htmlspecialchars($_SESSION['tokmakov_feedback']['data']['email']); $phone = htmlspecialchars($_SESSION['tokmakov_feedback']['data']['phone']); $message = htmlspecialchars($_SESSION['tokmakov_feedback']['data']['message']); } ob_start(); ?> <div class="tokmakov-feedback"> <div class="response"> <?php if (isset($_SESSION['tokmakov_feedback'])): ?> <p><?= $_SESSION['tokmakov_feedback']['message']; ?></p> <?php if (isset($_SESSION['tokmakov_feedback']['errors'])): ?> <ul> <?php foreach ($_SESSION['tokmakov_feedback']['errors'] as $error): ?> <li><?= $error; ?></li> <?php endforeach; ?> </ul> <?php endif; ?> <?php unset($_SESSION['tokmakov_feedback']); ?> <?php endif; ?> </div> <form action="<?= admin_url('admin-post.php'); ?>" method="post"> <input type="hidden" name="action" value="tokmakov_feedback" /> <input type="hidden" name="redirect" value="<?= get_permalink(); ?>" /> <label> <span>Имя</span> <input type="text" name="name" value="<?= $name; ?>" required /> </label> <label> <span>E-mail</span> <input type="text" name="email" value="<?= $email; ?>" required /> </label> <label> <span>Телефон</span> <input type="text" name="phone" value="<?= $phone; ?>" /> </label> <label> <span>Сообщение</span> <textarea name="message" required><?= $message; ?></textarea> </label> <input type="submit" value="Отправить" /> </form> </div> <?php return ob_get_clean(); });
Поскольку мы используем суперглобальный массив $_SESSION
, давайте стартанем сессию при наступлении события init
:
/* * Запускаем сессию, чтобы передавать сообщение о результате * обработки формы обратной связи после перезагрузки страницы */ add_action('init', function () { if (session_id() == '') { session_start(); } });
Если при проверке данных формы были обнаружены ошибки, элемент массива $_SESSION
с ключом tokmakov_feedback
будет содержать вот что:
Array ( [success] => false [message] => При заполнении формы были допущены ошибки [errors] => Array ( [0] => Не заполнено обязательное поле «E-mail» ) [data] => Array ( [name] => Евгений [email] => [phone] => [message] => Какое-то сообщение ) )
Если данные формы были успешно отправлены, этот элемент массива будет таким:
Array ( [success] => true [message] => Ваше сообщение успешно отправлено )
Скачать плагин «Форма обратной связи» можно здесь.
- WordPress. Обработка POST-запросов. Часть 2
- WordPress. Защита формы комментария
- WordPress. Форма комментирования
- WordPress. Фильтр записей по произвольным полям. Часть 3 из 3
- WordPress. Фильтр записей по произвольным полям. Часть 2 из 3
- WordPress. Порядок загрузки страницы
- WordPress. Загрузка файлов. Часть 3 из 3
Поиск: CMS • Hook • POST • Web-разработка • WordPress • Событие • Форма • Обратная связь • Плагин • Plugin • Плагин • Feedback