Как лучше всего обрабатывать действия на страницах пользовательского плагина?

26 февр. 2011 г., 02:44:19
Просмотры: 33.5K
Голосов: 26

Я постоянно сталкиваюсь с одной и той же проблемой, поэтому хотел бы узнать, есть ли какие-то идеи или опыт решения...

Я создал плагин, который использует свою собственную страницу администратора. Это необходимо. Теперь, когда я разобрался с WP_List_Table(), должен сказать, что это здорово... но...

Пользовательские страницы плагина всегда загружаются как admin.php?page=..., если только я не хочу загружать их напрямую из директории плагина, чего я не хочу. Теперь, если я выполняю 'action' с этой страницы, мне нужно как-то обработать это и затем перенаправить обратно на страницу без параметра action. Неважно, использую ли я GET или POST.

На всех своих внутренних страницах WP делает это на той же странице - проверяет, есть ли действие, если да, обрабатывает его и затем перенаправляет на себя без действия. Это возможно, потому что на этих страницах admin-header еще не загружен.

Если же вы попытаетесь сделать это на своей странице, половина интерфейса администратора уже отправлена в браузер, поэтому перенаправление уже невозможно. Очевидно, решение заключается в том, чтобы отправлять POST/GET напрямую на другую страницу, загрузить фреймворк WP там, выполнить обработку и затем перенаправить обратно на исходную страницу... но... это немного раздражает, потому что... моя исходная страница загружается через callback, поэтому она выполняется внутри метода моего класса. Это прекрасно.

Если я загружаю отдельную страницу, мне нужно вручную подключать wp-load.php и находиться вне моего класса, что раздражает, и в моем конкретном случае особенно беспокоит, потому что я создаю экземпляр моего класса плагина анонимно, чтобы никто не мог получить к нему доступ извне.

Итак, после этой длинной истории... кто-нибудь нашел хорошее решение для загрузки другой страницы через callback без предварительной настройки всего интерфейса администратора вокруг неё?

(Я знаю об обходном пути... я могу подключить функцию к load-...., которая проверяет параметр action и выполняет обработку и перенаправление. Но мне интересно, есть ли способ лучше.)

Спасибо.

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

Почему здесь стоит тег [plugin-wp-pagenavi]? [plugin-development] здесь определенно уместен.

Jan Fabry Jan Fabry
28 февр. 2011 г. 23:10:04

@Jan Fabry: Не уверен, для чего нужен plugin-wp-pagenavi... Я предположил, что он относится к взаимосвязи плагинов и меню админки. Поскольку мой вопрос касается этого, я выбрал этот тег.

wyrfel wyrfel
1 мар. 2011 г. 00:11:43

WP-PageNavi — это плагин с расширенной навигацией по страницам для фронтенда. Можно было бы использовать [admin-menu], но я не думаю, что это действительно связано с вопросом. Я изменил теги на более подходящие, но вы можете снова их отредактировать.

Jan Fabry Jan Fabry
1 мар. 2011 г. 10:12:11

@Jan Fabry: Спасибо за перепроставление тегов... пока не очень хорошо знаком со всем пулом тегов (что вполне очевидно).

wyrfel wyrfel
1 мар. 2011 г. 11:52:10
Все ответы на вопрос 3
7
32

Как правило, следует использовать POST-запрос для большинства действий, чтобы убедиться, что они не выполняются случайно. Также хорошей практикой является перенаправление на обычную страницу после POST-запроса, чтобы предотвратить повторное выполнение при обновлении страницы пользователем.

Таким образом, процесс выглядит следующим образом:

  1. Страница вашего плагина с POST-формой, которая отправляет данные на
  2. Страницу, обрабатывающую запрос, которая перенаправляет на
  3. Страницу вашего плагина, которая отображает результат выполнения действия

Промежуточная страница не обязательно должна быть страницей вашего плагина. Это означает, что вы можете использовать "универсальный обработчик POST-запросов", который был добавлен три года назад, хук 'admin_action_' . $_REQUEST['action'] в admin.php.

Примером использования является плагин Akismet. Если вы хотите использовать его надежно, необходимо отправлять данные напрямую в admin.php, а не на другую страницу, которая включает в себя admin.php.

Вот очень простой пример того, как это можно использовать:

add_action( 'admin_action_wpse10500', 'wpse10500_admin_action' );
function wpse10500_admin_action()
{
    // Здесь выполняются необходимые действия

    wp_redirect( $_SERVER['HTTP_REFERER'] );
    exit();
}

add_action( 'admin_menu', 'wpse10500_admin_menu' );
function wpse10500_admin_menu()
{
    add_management_page( 'WPSE 10500 Test page', 'WPSE 10500 Test page', 'administrator', 'wpse10500', 'wpse10500_do_page' );
}

function wpse10500_do_page()
{
?>
<form method="POST" action="<?php echo admin_url( 'admin.php' ); ?>">
    <input type="hidden" name="action" value="wpse10500" />
    <input type="submit" value="Сделать это!" />
</form>
<?php
}
28 февр. 2011 г. 23:08:50
Комментарии

Привет, я еще раз взгляну на код, я явно этого не заметил, но просто для подтверждения... ты говоришь, что если вызвать admin.php напрямую без параметра page, он пропускает загрузку всех страниц и просто выполняет некоторую инициализацию и запускает хук? Это было бы круто... вроде как (я все еще не понимаю, почему они не поместили хук перед загрузкой страницы).

wyrfel wyrfel
1 мар. 2011 г. 00:27:51

@wyrfel: Да, вызов admin.php напрямую — это "трюк", которому меня научил исходный код Akismet. Ты прав, когда отображаешь форму и хочешь показать ее снова в случае ошибок: тогда было бы удобно, если целью является страница твоего плагина, но хук находится где-то в начале (так ты мог бы перенаправить при успехе или снова отобразить форму с сообщениями об ошибках, если что-то пошло не так). Может, предложить это в тикете Trac?

Jan Fabry Jan Fabry
1 мар. 2011 г. 10:14:22

Я создам тикет. В качестве временного решения я обнаружил, что работает хук 'load-<pagehook>'... он вызывается перед загрузкой страницы... но концепция admin_action_... кажется гораздо приятнее и конкретнее. Также, замечу, что сообщения об ошибках все еще проблематичны, если делаешь POST-запросы и не хочешь повторной отправки при перезагрузке, но это уже другая тема.

wyrfel wyrfel
1 мар. 2011 г. 11:50:03

@wyrfel: Почему сообщения об ошибках всё ещё могут быть проблемой? Если есть сообщение об ошибке, оставайтесь на странице и снова отобразите форму с сообщениями (конечно, обновление страницы здесь не имеет особого смысла — но это и не навредит, так как ошибки всё равно останутся, и никакое действие не будет выполнено). Если ошибок нет, выполните действие и перенаправьте на "безопасную" страницу обзора. Это сработает — если хук admin_action_ будет перемещён перед загрузчиком страницы плагина.

Jan Fabry Jan Fabry
1 мар. 2011 г. 12:23:12

Ок... я слишком усложнил.

wyrfel wyrfel
1 мар. 2011 г. 12:57:14

Я расширил эту публикацию и включил возможность вызова этих же методов 'admin-action' из URL 'post-row-action'. Решение использует Jquery для сопоставления GET URL с POST запросом FORM, который рассматривается в этом ответе. http://wordpress.stackexchange.com/questions/82761/how-can-i-link-post-row-actions-with-a-custom-action-function

emeraldjava emeraldjava
28 мар. 2014 г. 19:13:31

Для обеспечения безопасности вы должны сгенерировать nonce в форме с помощью wp_nonce_field и проверить его в обработчике действия, используя wp_verify_nonce.

Flimm Flimm
2 сент. 2020 г. 16:25:17
Показать остальные 2 комментариев
1

Я подошел к этому немного иначе, просто добавив noheader=true к URL действия на странице, где пользователь отправляет форму.

Мой обработчик затем выполняет действие (например, добавление, обновление или удаление) и завершается вызовом wp_redirect() для перехода к следующему действию (например, страница добавления -> страница редактирования, страница удаления -> страница списка, страница редактирования -> страница редактирования). Я также передаю сообщение в URL, чтобы можно было отобразить статус, например "успешно обновлено" или "ошибка".

Такой подход позволяет сохранить все действия: список, добавление, редактирование, удаление, массовое удаление и т.д. в одном классе и с одним административным slug'ом, что делает код простым в поддержке и понимании.

29 авг. 2011 г. 15:22:57
Комментарии

Чувак, ты гений! Я два дня бился над этим, а оказалось, что мне просто не хватало части "noheader=true". Спасибо!

roman roman
9 апр. 2014 г. 13:37:43
0

Другой альтернативный подход — просто добавить скрытое поле ввода в форму:

<input type="hidden" name="page" value="your-page-slug" />

Таким образом, WordPress автоматически обрабатывает перенаправление.

16 янв. 2015 г. 18:02:23