Как исправить тайм-аут при добавлении записи CPT?

Ссылка скопирована
1 ответ

Здравствуйте!
Столкнулся в тайм-аутом при добавлении записи c произвольными полями кастомного типа
Даже переписывал функцию сохранения.. не помогло. Как поправить, что не так делаю?
save_profi_meta_data v 1.0

unction save_profi_meta_data($post_id) {      if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return $post_id;     if (!isset($_POST['post_type'])) {    return $post_id;}      // Создаем массив данных для обновления     $order_num = sanitize_text_field($_POST['order_num']);     $order_title = sanitize_text_field($_POST['order_title']);      // Создаем новый заголовок     $new_title = "Заказ № {$order_num} - {$order_title}";     $new_permalink = "order_{$order_num}";      $post_data = array(         'ID' => $post_id,         'post_title' => $new_title,         'post_content' => sanitize_textarea_field($_POST['order_description']),         'post_name' => $new_permalink,      );      // Добавляем произвольные поля в массив данных     $post_data['meta_input'] = array(         'order_title' => sanitize_text_field($_POST['order_title']),         'order_num' => sanitize_text_field($_POST['order_num']),         'profi_link' => sanitize_text_field($_POST['profi_link']),         'incoming_date' => sanitize_text_field($_POST['incoming_date']),         'deadline' => sanitize_text_field($_POST['deadline']),         'order_description' => sanitize_textarea_field($_POST['order_description']),         'order_sources' => sanitize_text_field($_POST['order_sources']),         'client_name' => sanitize_textarea_field($_POST['client_name']),         'client_contacts' => sanitize_textarea_field($_POST['client_contacts']),         'order_status' => sanitize_text_field($_POST['order_status']),         'current_task' => sanitize_textarea_field($_POST['current_task']),         'order_price' => sanitize_text_field($_POST['order_price']),         'profi_commission' => sanitize_text_field($_POST['profi_commission']),         'self_employed' => isset($_POST['self_employed']) && $_POST['self_employed'] === 'on' ? true : false,     );     wp_update_post($post_data);

unction save_profi_meta_data($post_id) { if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return $post_id; if (!isset($_POST['post_type'])) { return $post_id;} // Создаем массив данных для обновления $order_num = sanitize_text_field($_POST['order_num']); $order_title = sanitize_text_field($_POST['order_title']); // Создаем новый заголовок $new_title = "Заказ № {$order_num} - {$order_title}"; $new_permalink = "order_{$order_num}"; $post_data = array( 'ID' => $post_id, 'post_title' => $new_title, 'post_content' => sanitize_textarea_field($_POST['order_description']), 'post_name' => $new_permalink, ); // Добавляем произвольные поля в массив данных $post_data['meta_input'] = array( 'order_title' => sanitize_text_field($_POST['order_title']), 'order_num' => sanitize_text_field($_POST['order_num']), 'profi_link' => sanitize_text_field($_POST['profi_link']), 'incoming_date' => sanitize_text_field($_POST['incoming_date']), 'deadline' => sanitize_text_field($_POST['deadline']), 'order_description' => sanitize_textarea_field($_POST['order_description']), 'order_sources' => sanitize_text_field($_POST['order_sources']), 'client_name' => sanitize_textarea_field($_POST['client_name']), 'client_contacts' => sanitize_textarea_field($_POST['client_contacts']), 'order_status' => sanitize_text_field($_POST['order_status']), 'current_task' => sanitize_textarea_field($_POST['current_task']), 'order_price' => sanitize_text_field($_POST['order_price']), 'profi_commission' => sanitize_text_field($_POST['profi_commission']), 'self_employed' => isset($_POST['self_employed']) && $_POST['self_employed'] === 'on' ? true : false, ); wp_update_post($post_data);

save_profi_meta_data v 1.1

function save_profi_meta_data($post_id) {     // Проверяем, что это не автосохранение и что тип записи - "profi"     if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return $post_id;     if ('profi' !== get_post_type($post_id)) return $post_id;      // Массив полей для сохранения     $fields_to_save = array(         'order_title',         'order_num',         'profi_link',         'incoming_date',         'deadline',         'order_description',         'order_sources',         'client_name',         'client_contacts',         'order_status',         'current_task',         'order_price',         'profi_commission',     );      $meta_input = array();      foreach ($fields_to_save as $field) {         if (isset($_POST[$field])) {             $meta_input[$field] = sanitize_text_field($_POST[$field]);         }     }      // Обновляем заголовок и ссылку на запись     $order_num = isset($_POST['order_num']) ? sanitize_text_field($_POST['order_num']) : '';     $order_title = isset($_POST['order_title']) ? sanitize_text_field($_POST['order_title']) : '';     $new_title = "Заказ № {$order_num} - {$order_title}";     $new_permalink = "order_{$order_num}";      // Обновляем данные записи     $updated_post_data = array(         'ID' => $post_id,         'post_title' => $new_title,         'post_content' => sanitize_textarea_field($_POST['order_description']),         'post_name' => $new_permalink,     );      // Добавляем произвольные поля в массив данных     $updated_post_data['meta_input'] = $meta_input;      // Обновляем запись     wp_update_post($updated_post_data); }  // Вызываем функцию сохранения мета-полей при сохранении поста add_action('save_post', 'save_profi_meta_data');

function save_profi_meta_data($post_id) { // Проверяем, что это не автосохранение и что тип записи - "profi" if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return $post_id; if ('profi' !== get_post_type($post_id)) return $post_id; // Массив полей для сохранения $fields_to_save = array( 'order_title', 'order_num', 'profi_link', 'incoming_date', 'deadline', 'order_description', 'order_sources', 'client_name', 'client_contacts', 'order_status', 'current_task', 'order_price', 'profi_commission', ); $meta_input = array(); foreach ($fields_to_save as $field) { if (isset($_POST[$field])) { $meta_input[$field] = sanitize_text_field($_POST[$field]); } } // Обновляем заголовок и ссылку на запись $order_num = isset($_POST['order_num']) ? sanitize_text_field($_POST['order_num']) : ''; $order_title = isset($_POST['order_title']) ? sanitize_text_field($_POST['order_title']) : ''; $new_title = "Заказ № {$order_num} - {$order_title}"; $new_permalink = "order_{$order_num}"; // Обновляем данные записи $updated_post_data = array( 'ID' => $post_id, 'post_title' => $new_title, 'post_content' => sanitize_textarea_field($_POST['order_description']), 'post_name' => $new_permalink, ); // Добавляем произвольные поля в массив данных $updated_post_data['meta_input'] = $meta_input; // Обновляем запись wp_update_post($updated_post_data); } // Вызываем функцию сохранения мета-полей при сохранении поста add_action('save_post', 'save_profi_meta_data');

Дополнительно:

Нужно решить такую задачу?

Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

Заказать помощь
Лучший ответ
1
Павел Админов Ответ

Тайм-аут при сохранении CPT часто появляется из-за рекурсии в хуке сохранения. Если внутри save_post Вы вызываете wp_update_post(), WordPress снова запускает save_post, функция снова вызывает wp_update_post(), и так по кругу до тайм-аута или превышения памяти.

Если нужно менять заголовок/slug при сохранении, временно снимайте хук перед wp_update_post(), а потом возвращайте:

add_action('save_post_profi', 'save_profi_meta_data', 20, 2);
 
function save_profi_meta_data($post_id, $post) {
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
        return;
    }
 
    if (!current_user_can('edit_post', $post_id)) {
        return;
    }
 
    $order_num = sanitize_text_field($_POST['order_num'] ?? '');
    $order_title = sanitize_text_field($_POST['order_title'] ?? '');
 
    if (!$order_num || !$order_title) {
        return;
    }
 
    update_post_meta($post_id, 'order_num', $order_num);
    update_post_meta($post_id, 'order_title', $order_title);
 
    remove_action('save_post_profi', 'save_profi_meta_data', 20);
 
    wp_update_post([
        'ID'         => $post_id,
        'post_title' => 'Заказ № ' . $order_num . ' - ' . $order_title,
        'post_name'  => 'order-' . sanitize_title($order_num),
    ]);
 
    add_action('save_post_profi', 'save_profi_meta_data', 20, 2);
}

add_action('save_post_profi', 'save_profi_meta_data', 20, 2); function save_profi_meta_data($post_id, $post) { if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return; } if (!current_user_can('edit_post', $post_id)) { return; } $order_num = sanitize_text_field($_POST['order_num'] ?? ''); $order_title = sanitize_text_field($_POST['order_title'] ?? ''); if (!$order_num || !$order_title) { return; } update_post_meta($post_id, 'order_num', $order_num); update_post_meta($post_id, 'order_title', $order_title); remove_action('save_post_profi', 'save_profi_meta_data', 20); wp_update_post([ 'ID' => $post_id, 'post_title' => 'Заказ № ' . $order_num . ' - ' . $order_title, 'post_name' => 'order-' . sanitize_title($order_num), ]); add_action('save_post_profi', 'save_profi_meta_data', 20, 2); }

Также не забывайте nonce-проверку, если поля свои. И не обрабатывайте все post types через общий save_post, если нужен только один CPT. Используйте save_post_{post_type} — это снижает риск конфликтов и лишних запусков.

Ещё одна причина тайм-аута — тяжёлая обработка всех полей без проверки nonce и post type. WordPress вызывает сохранение при автосохранении, ревизиях, quick edit и других действиях. Если функция каждый раз пересчитывает заголовок, пишет десятки meta-полей или делает внешние запросы, админка начинает зависать.

Сделайте логирование времени и временно закомментируйте части функции. Если после удаления wp_update_post() тайм-аут исчезает, причина почти точно в рекурсии. Если нет — смотрите медленные операции внутри сохранения: API-запросы, большие циклы, генерацию файлов, пересчёт связанных записей.

Хорошая практика: в save_post только сохранить данные, а тяжёлые действия складывать в очередь или запускать cron-задачей.

Другие ответы (0)

Пока нет других ответов. Будьте первым, кто поможет автору.

Ответить на вопрос

комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Вам также может быть интересно