От автора: хорошему интерактивному сайту необходимо взаимодействовать с данными, которые вводит пользователь. Данные вводятся в специальных формах, которые являются частью вида. И WordPress в этом случае не исключение. За один день на сайте происходит масса различных форм взаимодействия пользователей с сервером. К примеру, подписка на рассылку новостей, сообщение владельцу сайта из формы обратной связи или заполнение формы заказа. Все это выполняется через POST запросы. И в данной статье мы рассмотри обработку WordPress POST запросов
В этой статье мы рассмотрим простой пример обработки POST запроса из контактной формы. Чтобы правильно вытянуть данные будем использовать встроенный хук WordPress’а. Полученные данные соответственно будем обрабатывать и перенаправлять пользователя на заготовленную страницу.
Данная статья рассчитана на тех, кто знаком с основами WordPress Plugin API. Если же вы совсем не работали с этим API, лучше просмотрите страницу кодекса WordPress перед тем, как продолжить. Также мы предлагаем наш курс, посвященный работе с API WordPress, и созданию собственных плагинов.
Предыстория
В основе WordPress лежит событийно-ориентированная архитектура. Это значит, что в ядре WordPress хранятся различные действия и фильтры, которые определенным образом изменяют работу программы или контент. Примерами действий запускаемых одновременно со стартом CMS являются init, wp, template_redirect и wp_head. Множество плагинов используют эти действия и фильтры для модификации работы системы.
Мы хотим добиться примерно того же. Нам всего лишь нужно знать правильные хуки для POST запросов и изменить код. Сделать это можно, разместив все формы в отдельном файле admin-post.php в директории wp-admin. Если вы уже работали с WordPress internal AJAX API, то должны заметить, что структура admin-post.php не сильно отличается от файла admin-ajax.php.
Анатомия admin-post.php
Если брать только самые основы, то в файле admin-post.php всего 71 строка кода. Сначала задается константа WP_ADMIN и подключается сам WordPress с помощью файла wp-load.php. После этого отсылаются заголовки и запускается admin_init. Ниже строка, выполняющая то, что мы сказали выше:
1 |
$action = empty( $_REQUEST['action'] ) ? '' : $_REQUEST['action']; |
Несмотря на имя admin-post.php, данный файл обрабатывает как POST, так и GET запросы. Тем не менее нас будут интересовать только POST запросы.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
if ( ! wp_validate_auth_cookie() ) { if ( empty( $action ) ) { /** * Fires on a non-authenticated admin post request where no action was supplied. * * @since 2.6.0 */ do_action( 'admin_post_nopriv' ); } else { /** * Fires on a non-authenticated admin post request for the given action. * * The dynamic portion of the hook name, `$action`, refers to the given * request action. * * @since 2.6.0 */ do_action( "admin_post_nopriv_{$action}" ); } } else { if ( empty( $action ) ) { /** * Fires on an authenticated admin post request where no action was supplied. * * @since 2.6.0 */ do_action( 'admin_post' ); } else { /** * Fires on an authenticated admin post request for the given action. * * The dynamic portion of the hook name, `$action`, refers to the given * request action. * * @since 2.6.0 */ do_action( "admin_post_{$action}" ); } } |
Как видно два разных хука срабатывают в зависимости от статуса пользователя, залогинился он или нет. Для залогиненных пользователей используется admin_post, а для незалогиненных admin_post_nopriv. Если же нужно обработать данные только из вашего запроса, можно воспользоваться другим действием admin_post_nopriv_{$action} или admin_post_{$action}, которые тоже основаны на статусе польозвателя.
Скажем, у нашего POST запроса action со значением foobar. Если пользователь не зашел под своими данными, то выполнятся два экшена:
admin_post_nopriv
admin_post_nopriv_foobar
Если вы залогинитесь, выполнятся два других экшена:
admin_post
admin_post_foobar
Все вышеописанные хуки можно применить и для GET запроса, если адрес примерно такой: //www.example.com/wp-admin/admin-post.php?action=foobar&data=test
Зная это, можно работать с данными из POST запроса напрямую, избегая шаблонов формы представления.
Испытание концепции
Для примера возьмем контактную форму. Самый простой способ это создать форму в файле page.php самому (не рекомендуется), закодировать форму и обрабатывать данные POST запроса в этом же файле. Примерно вот так это работает:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<?php /* * Template Name: Contact Page */ get_header(); if ( ! empty( $_POST ) ) { // Сканируем POST // генерируем текст для письма // Отсылаем письмо } ?> <div id="content"> <form action="" method="post"> <label for="fullname">Full Name</label> <input type="text" name="fullname" id="fullname" required> <label for="email">Email Address</label> <input type="email" name="email" id="email" required> <label for="message">Your Message</label> <textarea name="message" id="message"></textarea> <input type="submit" value="Send My Message"> </form> </div> <?php get_footer(); |
В таком виде концепция полностью работает, и нет никаких намеков на то, что в будущем что-то сломается. С точки зрения производительности и удобства работы с формой она ужасна. Если нужно продублировать такую форму, то придется повторять обработку.
Для того, чтобы избавиться от этой проблемы и полностью задействовать событийно-ориентированную природу WordPress нам понадобится файл admin-post.php. С его помощью можно конвертировать существующую форму, чтобы она стала совместима с файлом admin-post.php, и сделать это довольно просто. Сперва, замените эту строку:
1 |
<form action="" method="post"> |
На:
1 |
<form action="<?php echo esc_url( admin_url('admin-post.php') ); ?>" method="post"> |
Для генерации правильной ссылки, которая будет вести на файл admin-post.php мы используем встроенную функцию admin_url. Таким образом, мы обеспечим надежный редирект на наш сайт. Также нам необходимо добавить скрытый action к форме, а для этого нам понадобится еще один хук. Укажем name=»action», value=»contact_form». И добавим эту строку между тегов формы.
1 |
<input type="hidden" name="action" value="contact_form"> |
Теперь наш шаблон страницы выглядит так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<?php /* * Template Name: Contact Page */ get_header(); ?> <div id="content"> <form action="<?php echo esc_url( admin_url('admin-post.php') ); ?>" method="post"> <label for="fullname">Full Name</label> <input type="text" name="fullname" id="fullname" required> <label for="email">Email Address</label> <input type="email" name="email" id="email" required> <label for="message">Your Message</label> <textarea name="message" id="message"></textarea> <input type="hidden" name="action" value="contact_form"> <input type="submit" value="Send My Message"> </form> </div> <?php get_footer(); |
Заметьте, что мы удалили функцию обработки POST запроса из верхней части шаблона, мы вызовем ее позже.
Обработка POST запроса
На этом этапе у нас есть два варианта, и оба рабочие. Можно запустить action admin_post_* через functions.php в нашей теме, или создать простой плагин обработки контактной формы. Для простоты будем записывать все в functions.php. Вспомним, что у нас есть наш action contact_form, а значит, нам доступны четыре хука:
admin_post_nopriv
admin_post_nopriv_contact_form
admin_post
admin_post_contact_form
Откройте functions.php текущей темы и добавьте эти строки:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
function prefix_send_email_to_admin() { /** * Отсюда уже можно использовать $_GET/$_POST * * Можно начать обработку */ // Проверяем POST // Генерируем текст письма // Отсылаем по email } add_action( 'admin_post_nopriv_contact_form', 'prefix_send_email_to_admin' ); add_action( 'admin_post_contact_form', 'prefix_send_email_to_admin' ); |
Так как нам надо обработать форму независимо от того, залогинился пользователь или нет, мы запускаем функцию как для admin_post_nopriv_contact_form, так и для admin_post_contact_form. prefix_send_email_to_admin – основная функция, где происходит обработка данных.
Заключение
Файл admin-post.php крайне полезен, этакая жемчужина, сокрытая в глубине ядра WordPress. С его помощью можно четко разделить файлы представления от кода, который занимается обработкой запросов.
Автор: Firdaus Zahari
Источник: //www.sitepoint.com/
Редакция: Команда webformyself.
Комментарии (3)