☰
WORDPRESS / PRACTICE

Как правильно обновить rewrite rules для Custom Post Type в WordPress

Как правильно обновить rewrite rules для Custom Post Type в WordPress

Если записи Custom Post Type существуют в базе данных WordPress, но их URL возвращают ошибку 404, причина часто связана не с конфигурацией Apache или Nginx. WordPress хранит правила маршрутизации в базе данных, и после добавления нового типа записей эти правила могут устареть.

Обычно проблему решает корректное обновление rewrite rules. Однако вызывать flush_rewrite_rules() при каждом запросе нельзя: это создаёт лишние операции с базой данных и может ухудшить производительность сайта. Ниже описан безопасный подход для плагинов, проверки после деплоя и типичные ошибки.

Почему Custom Post Type возвращает 404

При регистрации Custom Post Type WordPress получает информацию о его slug, архиве, иерархии и правилах для отдельных записей. На основе этих данных формируются rewrite rules — набор правил, по которым WordPress определяет, какой запрос соответствует конкретной записи или архиву.

Эти правила не перестраиваются полностью при каждом запросе. WordPress хранит их в базе данных, поэтому после установки или обновления плагина они могут не соответствовать текущей регистрации CPT. В результате запись есть в административной панели, но URL вроде /portfolio/example/ возвращает 404.

Сброс rewrite rules заставляет WordPress сформировать их заново. Однако flush_rewrite_rules() не исправляет ошибки в самом register_post_type(): если CPT зарегистрирован с неправильным slug или вообще не регистрируется, после сброса проблема останется.

  • CPT был добавлен после первого запуска плагина.
  • Изменился slug типа записей или настройки rewrite.
  • Плагин обновили через деплой без повторной активации.
  • Правила были сброшены до регистрации CPT.
  • На сайте есть конфликт slug с таксономией, страницей или другим типом записей.

Правильная схема для активации плагина

Безопаснее всего сбрасывать rewrite rules только во время активации и деактивации плагина. При активации сначала нужно зарегистрировать Custom Post Type, а уже затем вызвать flush_rewrite_rules(). В противном случае WordPress ещё не будет знать о новом типе записей и не добавит его маршруты в правила.

Пример базовой реализации:

function my_register_cpt() {
    register_post_type('portfolio', [
        'label'        => 'Портфоліо',
        'public'       => true,
        'has_archive'  => true,
        'rewrite'      => [
            'slug' => 'portfolio',
        ],
        'supports'     => ['title', 'editor', 'thumbnail'],
        'show_in_rest' => true,
    ]);
}

add_action('init', 'my_register_cpt');

register_activation_hook(__FILE__, function () {
    my_register_cpt();
    flush_rewrite_rules();
});

register_deactivation_hook(__FILE__, function () {
    flush_rewrite_rules();
});

Почему функцию регистрации вызывают дважды

Вызов через add_action('init', ...) нужен для обычных запросов сайта. Отдельный вызов в callback активации необходим потому, что activation hook выполняется в специальном контексте, до стандартного цикла init. Без этого во время выполнения flush_rewrite_rules() CPT может быть ещё не зарегистрирован.

Название функции и параметры register_post_type() в реальном проекте могут отличаться, но порядок действий остаётся неизменным: сначала регистрация, затем сброс правил.

Чего нельзя делать

Распространённая ошибка — вызывать flush_rewrite_rules() в функции, подключённой к init, или непосредственно в шаблоне. В таком случае сброс выполняется при каждой загрузке страницы, а иногда и во время AJAX- или REST-запросов.

Операция изменяет или перестраивает правила маршрутизации и работает с базой данных. Для редкого события вроде активации плагина это нормально, но при выполнении для каждого посетителя создаёт лишнюю нагрузку.

  • Не вызывайте flush_rewrite_rules() в init.
  • Не размещайте его в single-шаблонах или functions.php без условия для одноразового запуска.
  • Не запускайте его при каждом сохранении записи CPT.
  • Не используйте flush как способ исправить неправильный slug типа записей.
  • Не сбрасывайте правила в REST-обработчиках и AJAX-запросах.

Как исправить 404 после деплоя без повторной активации

Если плагин уже установлен, а его код обновили через Git, CI/CD или файловый менеджер, activation hook повторно не запускается. Поэтому CPT, добавленный в новой версии, может не появиться в актуальных rewrite rules.

В такой ситуации удобно использовать WP-CLI. Команду нужно выполнить из корневой директории WordPress или указать правильный путь к установке:

wp rewrite flush

Когда нужен hard flush

Обычная команда wp rewrite flush обновляет правила WordPress. Если нужно также проверить их взаимодействие с конфигурацией веб-сервера, WP-CLI поддерживает параметр --hard, но использовать его следует осторожно и только при наличии необходимых прав доступа и подходящего серверного окружения.

В большинстве случаев для 404 у Custom Post Type достаточно обычного обновления правил. Если после этого URL не работает, проблема может быть связана со структурой постоянных ссылок, конфигурацией сервера или кодом регистрации CPT.

wp rewrite flush --hard

Проверка регистрации Custom Post Type

Перед диагностикой rewrite rules убедитесь, что CPT действительно регистрируется для нужного запроса. Проверьте, выполняется ли add_action('init', ...), нет ли условия, отключающего регистрацию на фронтенде, и не возникает ли PHP-ошибка при загрузке плагина.

Также важно проверить параметры rewrite. Если для CPT задано rewrite => false, WordPress не будет создавать стандартные человекопонятные URL. Если используется собственный slug, фактический адрес записи может отличаться от названия post type.

  • Проверьте правильность первого аргумента register_post_type().
  • Убедитесь, что slug не содержит ошибок и не дублирует slug страницы.
  • Проверьте has_archive, если нужна страница архива CPT.
  • Убедитесь, что запись имеет статус, доступный на фронтенде, например publish.
  • Проверьте журналы PHP, если код плагина не загружается.
wp post-type list
wp rewrite list | grep portfolio

Другие причины 404 после сброса правил

Если после корректного flush URL всё ещё возвращает 404, не следует бесконечно повторять эту команду. Сначала проверьте, открывается ли обычная страница WordPress и работают ли записи других типов.

Отдельное внимание нужно уделить конфликтам адресов. Например, страница со slug portfolio может пересекаться с архивом CPT, который использует тот же slug. Подобные конфликты способны приводить к непредсказуемой маршрутизации.

На сайтах с кешированием после изменения правил также может потребоваться очистить кеш страниц или кеш reverse proxy. Это не заменяет flush rewrite rules, но старый кеш может скрывать результат исправления.

  • Проверьте, не занят ли slug CPT страницей или таксономией.
  • Очистите кеш после обновления правил, если он используется.
  • Убедитесь, что WordPress работает с правильными значениями siteurl и home.
  • Проверьте rewrite-правила сервера, если 404 возникает для всех человекопонятных URL.
  • Сравните результат для URL записи, архива и таксономии CPT.

Рекомендации для обновлений плагина

Если новый CPT добавляется во время обновления плагина, не стоит полагаться только на повторную активацию. Пользователи обычно обновляют плагины без деактивации, поэтому activation hook в таком сценарии не выполнится.

Для более сложных изменений можно хранить версию rewrite rules в настройках плагина и выполнять flush один раз после обнаружения новой версии. Такой механизм нужно реализовать осторожно: он должен срабатывать один раз, а не при каждом запросе.

  • Для первой установки используйте register_activation_hook().
  • Для удаления маршрутов после деактивации используйте register_deactivation_hook().
  • После деплоя без активации выполните wp rewrite flush.
  • После изменения slug учитывайте старые URL, редиректы и возможные 404.
  • Тестируйте отдельную запись, архив и связанные таксономии.

Частые вопросы

Нужно ли сбрасывать rewrite rules после каждого создания записи CPT?

Нет. Создание, редактирование или удаление отдельной записи не меняет структуру rewrite rules. Сброс нужен после регистрации CPT, изменения его slug или других параметров маршрутизации.

Почему flush_rewrite_rules() не помог исправить 404?

Возможно, CPT не регистрируется, имеет неправильный slug, отключённый параметр rewrite или конфликтует со страницей либо таксономией. Причиной также могут быть кеш или ошибки конфигурации веб-сервера.

Достаточно ли просто деактивировать и активировать плагин?

Во многих случаях да, если activation hook написан правильно. Во время активации CPT должен быть зарегистрирован до вызова flush_rewrite_rules(). Для автоматизированного деплоя надёжнее выполнить wp rewrite flush.

Можно ли вызвать flush_rewrite_rules() вручную из административной страницы?

Можно, если запуск ограничен одноразовым действием с проверкой прав и nonce. Но для стандартного плагина лучше использовать activation hook, механизм миграции версий или WP-CLI.

Влияет ли show_in_rest на URL Custom Post Type?

Нет. Этот параметр управляет доступностью типа записей в WordPress REST API и редакторе. Он не заменяет параметр rewrite и сам по себе не исправляет 404 для фронтенд-URL.

Вывод

404 для Custom Post Type после установки или обновления плагина часто возникает из-за устаревших rewrite rules. Правильная последовательность проста: зарегистрировать CPT, один раз обновить правила во время активации или выполнить wp rewrite flush после деплоя.

Не используйте flush_rewrite_rules() в обычном цикле запросов. Если после одноразового сброса URL не заработал, проверьте регистрацию CPT, конфликты slug, кеш и конфигурацию сервера — именно эти причины чаще всего остаются после корректного обновления правил.

← Все материалы WordPress