Добавить проверку и обработку ошибок при сохранении пользовательских полей?

wordpress.stackexchange https://wordpress.stackexchange.com/questions/5102

Вопрос

У меня есть функция, которая определяет пользовательское поле на типе поста. Скажем, поле "подзаголовок".

Когда сообщение сохраняется, я хочу сделать некоторую проверку на вводе и при необходимости отобразить сообщение об ошибке на экране редактирования 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.phpS. 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, который он предоставляет для создания любых пользовательских полей, требуемых также с помощью настраиваемого сообщения об ошибке и функции проверки. По умолчанию по умолчанию проверяет, является ли поле пустым или нет.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с wordpress.stackexchange
scroll top