Додати перевірку та обробку помилок під час збереження спеціальних полів?


27

У мене є функція, яка визначає спеціальне поле для типу публікації. Скажіть, що поле "підзаголовок".

Коли повідомлення збережено, я хочу зробити деяку перевірку на вході та, якщо потрібно, відобразити повідомлення про помилку на екрані редагування публікації. Щось на зразок:

// 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 і повернути його, він не буде дотриманий будь-яким механізмом, який вигадує помилки на сторінці редагування публікації.

Наразі у моєму користувальницькому мета-вікні є повідомлення про помилку на сторінці, але це менше, ніж ідеально - я б швидше мав велику, червону помилку вгорі, як, наприклад, WP.

Будь-які ідеї?

ОНОВЛЕННЯ:

На основі відповіді @Denis я спробував кілька різних речей. Збереження помилок як глобальних не спрацювало, тому що Wordpress виконує перенаправлення під час процесу save_post, який вбиває глобальну інформацію, перш ніж ви зможете її відобразити.

Я закінчив зберігати їх у метаполі. Проблема в цьому полягає в тому, що вам потрібно їх очистити, інакше вони не зникнуть, коли ви перейдете на іншу сторінку, тому мені довелося додати ще одну функцію, приєднану до адмін_фотера, що просто очищає помилки.

Я б не очікував, що обробка помилок для чогось такого поширеного (оновлення дописів) буде цим незграбним. Я пропускаю щось очевидне чи це найкращий підхід?

// 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' );

Гарне питання. Я думаю, ви могли б позбутися admin_footerгачка, якщо ви очистите помилки наприкінці функції обробника повідомлень. Просто спрощує речі.
Геерт

Як ви маєте справу з репопуляцією полів форми (з можливими недійсними даними)?
Геерт

У мене основне питання. У якому файлі Wordpress php це?

@Karen Це буде у власному файлі плагінів або у ваших function.php.
MathSmath

Можливо, я б пропустив щось очевидне, але чи було б трохи ефективніше запустити update_option('my_admin_errors', false);одразу після оператора if в кінці wpse_5102_admin_notice_handler()?
Андрій Одрі

Відповіді:


6

Зберігайте помилки у своєму класі або як глобальний, можливо, в перехідному або мета-режимі та відображайте їх у повідомленнях адміністратора на POST-запити. WP не має жодного обробника флеш-повідомлень.


Дякую, що вказали на мене в цьому напрямку! У кінцевому підсумку я використовував мета для зберігання помилок, тому що у мене виникли проблеми при спробі зробити це як глобальний або властивість. Я зараз оновлюю свою відповідь, щоб пояснити, як я це роблю ... Будь ласка, дайте мені знати, чи це така річ, яку ви пропонували, чи є кращий спосіб, який я не отримую.
MathSmath

Така річ, так. Можливо, зберігайте його в сесійній змінній, на другій думці. Це для того, щоб дозволити декільком авторам редагувати публікації одночасно. :-) Крім того, я вважаю, що не можна зберігати помилку в опції. Замість цього зберігайте порожній рядок.
Денис де Бернарді

6

Я пропоную використовувати сеанси, оскільки це не створить дивних ефектів при одночасному редагуванні двох користувачів. Отже, це я роблю:

Сеанси не починаються за допомогою wordpress. Тому вам потрібно почати сеанс у вашому плагіні, function.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' );

виправити версію сеансу: при першому використанні змінної сесії не використовуйте. = тільки = якщо ви включите налагодження, ви можете перевірити, чому ...

3
Я теж робив це, але якщо ви випустите плагін для такої широкої аудиторії, що люди, нарешті, ненавиджу вас за це. Wordpress не створює сеанси, оскільки він розроблений так, щоб вони не мали статусу і не потребували їх, а деякі дивні налаштування сервера порушують це. Використовуйте API перехідних процесів - codex.wordpress.org/Transients_API замість сесій, і ви збережете сумісність. Просто подумав, що варто позначити причину, чому не робити цього тут.
pospi

@pospi Це, мабуть, має подібні проблеми, як і оригінальне використання функцій get_option та update_option. Тож я думаю, що рішенням було б додати ідентифікатор поточного користувача до ключа?
Газiльйон

Так, це б повністю спрацювало! Поки ви додасте щось для унікальної ідентифікації користувача, ви уникнете змішування повідомлень між зареєстрованими користувачами (:
pospi

5

На основі pospi «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'));

Оскільки ідентифікатор публікації є частиною імені перехідного періоду, це має працювати в більшості середовищ для багатьох користувачів, за винятком випадків, коли декілька користувачів одночасно редагують одну і ту ж посаду.


Не могли б ви детальніше розглянути "Оскільки ідентифікатор повідомлення є частиною перехідного імені"? Я створив клас для обробки повідомлень про помилки за допомогою цієї методики, але мені потрібно, щоб мій конструктор передав user_ID. Чи перехідний API використовує user_id під час хешування ключа? (Я прошу, бо кодекс, мабуть, не згадує про це)
Gazillion

Ні, але ви можете додати це вручну. У коді, який я розмістив вище, назва перехідного періоду acme_plugin_error_msg_POSTID. Ви можете просто додати ідентифікатор користувача до подібного acme_plugin_error_msg_POSTID_USERID.
Джошуа Коаді

2

Під час save_postзапуску він уже зберег публікацію в базі даних.

Розглядаючи основний код WordPress, точніше на функцію wp-includes/post.php' 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


Дякую за це, прекрасно обробляє перевірку, будь то публікація вперше або оновлення публікації. Ви просто заощадили мені багато часу та сил.
Зад

1

Чому ви не перевіряєте своє поле за допомогою Javascript? Я думаю, що це був би найкращий підхід для цього.


Дякую за пропозицію! Що я не залишав під питанням (для простоти), це те, що я намагаюся обробляти помилки завантаження файлів, тому це має бути на стороні сервера. Дякую за пропозицію, хоча!
MathSmath

Перевірка javascript не перешкоджає деяких атак, перевірка на сервері є єдиною захищеною. Крім того, wordpress пропонує кілька хороших інструментів для перевірки даних користувачів. Але ви маєте рацію, якщо він просто перевірить деякі значення, перш ніж надсилати дані на сервер, ви можете заощадити деякий час на низькому сервері ^^
nderambure

1

Намагаючись використовувати сценарій вище, я зіткнувся з дивною проблемою. Після оновлення публікації на екрані редагування відображаються два повідомлення. Один показує стан вмісту з попереднього збереження, а інший - з поточного. Наприклад, якщо я правильно збережу посаду, а потім помиляюся, перше - "помилка", а друге - "добре" - хоча вони створюються в один і той же час. Якщо я зміню сценарій і додаю лише одне повідомлення (наприклад, "помилка"), ініціюю одне оновлення з "помилкою", а після цього інше з повідомленням "нормально", "помилка" залишається (відображається вдруге). Я мушу ще раз заощадити "ок", щоб позбутися від нього. Я дійсно не знаю, що не так, я перевірив це на трьох різних локальних серверах, і на кожному з них є одна і та ж проблема.


Я зробив ще кілька тестів спрощеної, другої версії скрипту, про яку я згадував вище, і, схоже, якщо повідомлення про помилку дійсно додається до масиву сеансу, воно відображається на екрані редагування. Якщо немає повідомлення (все "добре"), і попереднє повідомлення було помилкою, воно з'являється на екрані. Що дивно, він генерується під час збереження (не кешований) - я перевірив це за допомогою дати () в тілі повідомлення про помилку. Зараз я зовсім розгублений.
jlub

Гаразд, на випадок, коли хтось витягає волосся з голови - виявилося, що проблема перегляду системи Wordpress (певна помилка?). Я його відключив і зараз все просто добре.

0

Я написав плагін, який додає флеш-обробки помилок на екрани редагування публікацій і запобігає публікації публікацій, поки не заповнюються необхідні поля:

https://github.com/interconnectit/required-fields

Це дозволяє зробити будь-які поля публікації обов'язковими, але ви можете використовувати API, який він надає, щоб також зробити будь-які власні поля, необхідні за допомогою налаштовуваного повідомлення про помилку та функції перевірки. Він за замовчуванням перевіряє, чи поле порожнє чи ні.


Не соромтеся додавати будь-які проблеми на Github, якщо ви стикаєтесь з ними. Мені потрібно ще трохи задокументувати API, оскільки є деякі додаткові фільтри, які ви можете використовувати.
sanchothefat
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.