Добавить проверку и обработку ошибок при сохранении пользовательских полей?
-
16-10-2019 - |
Вопрос
У меня есть функция, которая определяет пользовательское поле на типе поста. Скажем, поле "подзаголовок".
Когда сообщение сохраняется, я хочу сделать некоторую проверку на вводе и при необходимости отобразить сообщение об ошибке на экране редактирования Post. Что-то типа:
// Handle post updating
function wpse_update_post_custom_values($post_id, $post) {
// Do some checking...
if($_POST['subhead'] != 'value i expect') {
// Add an error here
$errors->add('oops', 'There was an error.');
}
return $errors;
}
add_action('save_post','wpse_update_post_custom_values',1,2);
Я пытаюсь подключить это к действию save_post, но я не могу понять, как обрабатывать ошибки. По -видимому, нет объекта ошибки, передаваемого в функцию, и если я создаю свой собственный wp_error obj и верю его, его не уважают, какой механизм выплевывает ошибки на странице редактирования Post.
В настоящее время у меня есть сообщение об ошибке на странице внутри моего пользовательского мета-коробки, но это не идеально-у меня скорее есть большая, красная ошибка, как обычно отображается WP.
Любые идеи?
ОБНОВИТЬ:
Основываясь на ответе @Denis, я попробовал несколько разных вещей. Хранение ошибок в качестве глобального не сработало, потому что WordPress делает перенаправление во время процесса Save_post, что убивает глобальную, прежде чем вы сможете его отобразить.
Я закончил тем, что сохранил их в мета -поле. Проблема в том, что вам нужно их очистить, или они не уйдут, когда вы перейдете на другую страницу, поэтому мне пришлось добавить еще одну функцию, прикрепленную к Admin_footer, которая просто очищает ошибки.
Я бы не ожидал, что обработка ошибок для чего -то настолько распространенного (обновление сообщений) будет таким неуклюжим. Я упускаю что -то очевидное или это лучший подход?
// Handle post updating
function wpse_5102_update_post_custom_values($post_id, $post) {
// To keep the errors in
$errors = false;
// Do some validation...
if($_POST['subhead'] != 'value i expect') {
// Add an error here
$errors .= 'whoops...there was an error.';
}
update_option('my_admin_errors', $errors);
return;
}
add_action('save_post','wpse_5102_update_post_custom_values',1,2);
// Display any errors
function wpse_5102_admin_notice_handler() {
$errors = get_option('my_admin_errors');
if($errors) {
echo '<div class="error"><p>' . $errors . '</p></div>';
}
}
add_action( 'admin_notices', 'wpse_5102_admin_notice_handler' );
// Clear any errors
function wpse_5102__clear_errors() {
update_option('my_admin_errors', false);
}
add_action( 'admin_footer', 'wpse_5102_clear_errors' );
Решение
Храните ошибки в вашем классе или в качестве глобального, возможно, в переходной или мета, и отображать их в уведомлениях администратора по запросам. WP не имеет какого -либо обработчика флэш -сообщений.
Другие советы
Я предлагаю использовать сеансы, так как это не создаст странных эффектов, когда два пользователя редактируют одновременно. Итак, это то, что я делаю:
Сессии не начинаются WordPress. Так что вам нужно начать сеанс В вашем плагине, functions.php или даже wp-config.php:
if (!session_id())
session_start();
При сохранении сообщения добавьте ошибки и уведомления к сеансу:
function my_save_post($post_id, $post) {
if($something_went_wrong) {
//Append error notice if something went wrong
$_SESSION['my_admin_notices'] .= '<div class="error"><p>This or that went wrong</p></div>';
return false; //might stop processing here
}
if($somthing_to_notice) { //i.e. successful saving
//Append notice if something went wrong
$_SESSION['my_admin_notices'] .= '<div class="updated"><p>Post updated</p></div>';
}
return true;
}
add_action('save_post','my_save_post');
Распечатать уведомления и ошибки, а затем очистите сообщения в сеансе:
function my_admin_notices(){
if(!empty($_SESSION['my_admin_notices'])) print $_SESSION['my_admin_notices'];
unset ($_SESSION['my_admin_notices']);
}
add_action( 'admin_notices', 'my_admin_notices' );
На основе ПоспиS. предложение использовать переходные процессы, Я придумал следующее. Единственная проблема в том, что нет крючка, чтобы поместить сообщение ниже h2
Куда идут другие сообщения, поэтому мне пришлось сделать хакер jQuery, чтобы получить его туда.
Во -первых, сохранить сообщение об ошибке, чтобы дать свой save_post
(или аналогичный) обработчик. Я даю ему короткую жизнь 60 секунд, так что это достаточно долго, чтобы перенаправление произошло.
if($has_error)
{
set_transient( "acme_plugin_error_msg_$post_id", $error_msg, 60 );
}
Затем просто возьмите это сообщение об ошибке на следующей странице загрузите и отобразите его. Я также удаляю его, чтобы он не был отображаться дважды.
add_action('admin_notices', 'acme_plugin_show_messages');
function acme_plugin_show_messages()
{
global $post;
if ( false !== ( $msg = get_transient( "acme_plugin_error_msg_{$post->ID}" ) ) && $msg) {
delete_transient( "acme_plugin_error_msg_{$post->ID}" );
echo "<div id=\"acme-plugin-message\" class=\"error below-h2\"><p>$msg</p></div>";
}
}
С admin_notices
Пожары до создания контента основной страницы, уведомление не является тем, где идут другие сообщения от редактирования, поэтому мне пришлось использовать этот jQuery, чтобы переместить его туда:
jQuery('h2').after(jQuery('#acme-plugin-message'));
Поскольку идентификатор POST является частью переходного имени, это должно работать в большинстве многопользовательских сред, за исключением случаев, когда несколько пользователей одновременно редактируют один и тот же пост.
Когда save_post
Запускается, он уже сохранил сообщение в базе данных.
Изучать код ядра WordPress, более конкретно на wp-includes/post.php
S. update_post()
Функция, нет встроенного способа перехвата запроса, прежде чем он будет сохранен в базе данных.
Тем не менее, мы можем зацепить pre_post_update
и использовать header()
а также get_post_edit_link()
чтобы предотвратить сохранение поста.
<?php
/**
* Performs validation before saving/inserting custom post type
*/
function custom_post_site_save($post_id, $post_data) {
// If this is just a revision, don't do anything.
if (wp_is_post_revision($post_id))
return;
if ($post_data['post_type'] == 'my_custom_post_type') {
// Deny post titles with less than 5 characters
if (strlen($post_data['post_title'] < 5)) {
header('Location: '.get_edit_post_link($post_id, 'redirect'));
exit;
}
}
}
add_action( 'pre_post_update', 'custom_post_site_save', 10, 2);
Если вы уведомили пользователя, что пошло не так, проверьте эту суть: https://gist.github.com/luc45/09f2f9d0c0e574c0285051b288a0f935
Почему бы вам не проверить свое поле с помощью какого -то JavaScript? Я думаю, что это был бы лучший подход для этого.
Пытаясь использовать сценарий выше, я столкнулся со странной проблемой. Два сообщения отображаются на экране редактирования, после обновления сообщения. Один из них показывает состояние контента из предыдущего сохранения, а другой - от текущего. Например, если я правильно сохраняю пост, а затем сделаю ошибку, сначала - «ошибка», а второй - «ОК» - в целом они генерируются в одно и то же время. Если я изменю сценарий и добавляю только одно сообщение (например, «Ошибка»), инициирую одно обновление с «ошибкой», а после этого другое с сообщением «Ошибка» остается («Ошибка» (отображается во второй раз). Я должен сохранить с «ОК» еще раз, чтобы избавиться от этого. Я действительно не знаю, что случилось, я проверил это на трех разных местных серверах, и на каждом из них есть такая же проблема. Если у кого -то есть идеи или предложение, пожалуйста, помогите!
Я записал плагин, который добавляет в обработку ошибок вспышки для экранов для редактирования Post и предотвращает публикацию сообщений, пока не будут заполнены необходимые поля:
https://github.com/interconnectit/required-fields
Это позволяет вам сделать любые поля поля обязательными, но вы можете использовать API, который он предоставляет для создания любых пользовательских полей, требуемых также с помощью настраиваемого сообщения об ошибке и функции проверки. По умолчанию по умолчанию проверяет, является ли поле пустым или нет.