Как создать массивный импорт курсов в WordPress с помощью AJAX и REST API

На сайте с большим количеством образовательных курсов часто возникает задача массового импорта данных. Ручное добавление каждого курса через админку WordPress — неэффективно и занимает много времени. В этой статье разберём, как создать надёжный и масштабируемый импорт курсов с использованием AJAX и REST API WordPress.

Особенности массового импорта курсов в WordPress

Перед тем как приступить к технической реализации, важно понять, с какими проблемами можно столкнуться при импорте большого объёма данных:

  • Временные ограничения PHP и сервера. Импорт больших файлов за один запрос может привести к тайм-аутам.
  • Нагрузка на базу данных. Многочисленные операции вставки данных могут замедлить работу сайта.
  • Валидация и обработка ошибок. Нужно корректно обрабатывать повреждённые или некорректные данные.
  • Обновление уже существующих курсов. Нужно уметь распознавать дубликаты и обновлять их, а не создавать новые записи.

Для решения этих задач оптимально разбить импорт на несколько AJAX-запросов, которые будут поэтапно загружать данные и создавать записи в WordPress.

Создание REST API endpoint для обработки импорта курсов

Первый шаг — создать собственный REST API endpoint, который будет принимать часть данных и создавать или обновлять курсы. Предположим, что у вас есть кастомный тип записи course для курсов.

Добавим функцию в файл functions.php вашей темы или в отдельный плагин:

function wpfreecourses_register_import_endpoint() {
    register_rest_route('wpfreecourses/v1', '/import-courses', array(
        'methods' => 'POST',
        'callback' => 'wpfreecourses_handle_import_courses',
        'permission_callback' => function () {
            return current_user_can('edit_posts');
        },
    ));
}
add_action('rest_api_init', 'wpfreecourses_register_import_endpoint');

function wpfreecourses_handle_import_courses(WP_REST_Request $request) {
    $courses = $request->get_param('courses');
    if (!is_array($courses)) {
        return new WP_REST_Response(array('error' => 'Invalid data format'), 400);
    }

    $results = [];

    foreach ($courses as $course) {
        // Проверяем обязательные поля
        if (empty($course['title']) || empty($course['content'])) {
            $results[] = array('status' => 'error', 'message' => 'Missing title or content');
            continue;
        }

        // Проверяем, есть ли курс с таким названием
        $existing = get_page_by_title($course['title'], OBJECT, 'course');

        if ($existing) {
            // Обновляем существующий курс
            $post_id = $existing->ID;
            wp_update_post(array(
                'ID' => $post_id,
                'post_content' => $course['content'],
            ));
            $results[] = array('status' => 'updated', 'id' => $post_id);
        } else {
            // Создаём новый курс
            $post_id = wp_insert_post(array(
                'post_title' => $course['title'],
                'post_content' => $course['content'],
                'post_status' => 'publish',
                'post_type' => 'course',
            ));
            if (is_wp_error($post_id)) {
                $results[] = array('status' => 'error', 'message' => $post_id->get_error_message());
            } else {
                $results[] = array('status' => 'created', 'id' => $post_id);
            }
        }
    }

    return $results;
}

Данный endpoint принимает массив курсов, каждый из которых содержит заголовок и содержание. Если курс с таким заголовком уже есть, происходит обновление, иначе создаётся новый.

Организация AJAX-запросов для поэтапной загрузки данных

Для обхода ограничений по времени и памяти удобно разбивать импорт на части. В фронтенде можно реализовать загрузку JSON-файла с курсами и отправлять данные порциями по 10–20 записей.

Пример простого JavaScript-кода для отправки данных частями:

function wpfreecourses_importCourses(courses) {
    let chunkSize = 20;
    let index = 0;

    function sendChunk() {
        let chunk = courses.slice(index, index + chunkSize);
        if (chunk.length === 0) {
            console.log('Импорт завершён');
            return;
        }

        fetch('/wp-json/wpfreecourses/v1/import-courses', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-WP-Nonce': wpfreecourses.nonce
            },
            body: JSON.stringify({courses: chunk})
        })
        .then(response => response.json())
        .then(data => {
            console.log(data);
            index += chunkSize;
            sendChunk();
        })
        .catch(err => console.error('Ошибка:', err));
    }

    sendChunk();
}

Важно передавать nonce для защиты REST API от CSRF-атак. Nonce можно сгенерировать и передать скрипту через wp_localize_script.

Пример структуры JSON для импорта курсов

Для успешной работы API нужно подготовить данные в формате:

[
  {
    "title": "Курс по WordPress для начинающих",
    "content": "Подробное описание курса..."
  },
  {
    "title": "Продвинутый курс по PHP",
    "content": "Материалы для разработчиков..."
  }
]
<

Такую структуру можно экспортировать из CSV или другой системы, преобразовав в JSON.

Настройка пользовательского типа записи и метаполей для курсов

Если у вас ещё нет кастомного типа записи course, можно зарегистрировать его так:

function wpfreecourses_register_post_type() {
    register_post_type('course', array(
        'labels' => array(
            'name' => 'Курсы',
            'singular_name' => 'Курс',
        ),
        'public' => true,
        'has_archive' => true,
        'supports' => array('title', 'editor', 'thumbnail'),
        'show_in_rest' => true,
    ));
}
add_action('init', 'wpfreecourses_register_post_type');

Для хранения дополнительных данных, например цены или длительности, используйте метаполя. Их можно добавлять программно или через плагины, например Clearfy Pro.

Рекомендации по оптимизации и безопасности

Для успешного массового импорта важно соблюдать несколько правил:

  • Обрабатывать ошибки и логировать результаты. Добавляйте логи, чтобы не потерять информацию о неудачных записях.
  • Использовать транзакции базы данных при необходимости. Чтобы избежать частичной записи данных.
  • Ограничивать права доступа к импорту. Только администраторы или редакторы должны иметь возможность запускать импорт.
  • Проверять и фильтровать входящие данные. Чтобы избежать внедрения вредоносного кода.

Если у вас большая база курсов, можно дополнительно кешировать результаты, например, с помощью ABC Pagination для удобного отображения списка.

Автоматическая сборка курсов из разных источников в WordPress
15.04.2026
WooCommerce: как установить и настроить оповещения о статусе оплаты заказа
01.05.2026
Автоматическое удаление неактивных заказов в WooCommerce
22.05.2026
Как избежать проблем с производительностью WordPress при использовании внешних API
14.03.2026
Как автоматически создавать отзывы о курсах в WordPress
18.03.2026