Создание пользовательского типа записей в WordPress
WordPress поставляется с записями (Posts) и страницами (Pages), но этих двух типов контента будет недостаточно, когда клиенту нужен каталог объектов недвижимости, список сотрудников или архив рецептов. Именно здесь на помощь приходит пользовательский тип записей WordPress (custom post type) — полноценная структура контента, которая органично вписывается в существующую модель данных WordPress без необходимости взлома стандартных настроек.
Ключевые моменты
- Пользовательский тип записей (CPT) расширяет общую таблицу
wp_posts, а не создаёт отдельную, предоставляя вам готовые экраны администратора, конечные точки REST API и маршрутизацию шаблонов. - Всегда регистрируйте CPT в плагине, а не в теме, чтобы контент оставался доступным независимо от смены темы.
- Установка параметра
show_in_restвtrueобязательна для поддержки блочного редактора и доступа через REST API. - Сбрасывайте правила перезаписи только при активации плагина — никогда при каждой загрузке страницы.
Что такое пользовательский тип записей?
Пользовательский тип записей (CPT) — это именованный тип контента, который вы регистрируете в WordPress. Несмотря на название, это не отдельная таблица базы данных. Все типы записей — встроенные и пользовательские — используют общую таблицу wp_posts, различаясь значением в колонке post_type. Это важная концептуальная модель: вы расширяете существующую структуру, а не создаёте параллельную.
Стандартные типы записей включают post, page, attachment, revision и nav_menu_item. Когда вы регистрируете CPT, например property или recipe, WordPress обрабатывает его с той же последовательностью: экраны администратора, конечные точки REST API, маршрутизация URL и иерархия шаблонов работают одинаково.
Пользовательские типы записей ≠ произвольные поля. CPT определяет тип контента. Произвольные поля (добавленные через ACF или API метаданных) хранят дополнительные данные, привязанные к этому контенту. Это разные концепции.
Регистрация пользовательского типа записей с помощью register_post_type()
Канонический способ создания пользовательского типа записей WordPress — функция register_post_type(), вызываемая на хуке init.
Вот чистый рабочий пример:
add_action( 'init', 'register_property_post_type' );
function register_property_post_type() {
$labels = [
'name' => 'Properties',
'singular_name' => 'Property',
'add_new_item' => 'Add New Property',
'edit_item' => 'Edit Property',
'not_found' => 'No properties found.',
];
$args = [
'labels' => $labels,
'public' => true,
'has_archive' => true,
'supports' => [ 'title', 'editor', 'thumbnail', 'excerpt' ],
'rewrite' => [ 'slug' => 'properties' ],
'show_in_rest' => true,
];
register_post_type( 'property', $args );
}
Объяснение ключевых параметров
public— Делает CPT видимым в админ-панели и на фронтенде. Установитеfalseдля типов, используемых только внутри системы.labels— Управляет всеми текстовыми строками интерфейса в админ-панели. Стоит заполнить правильно, чтобы редакторы не путались.supports— Объявляет, какие функции редактора отображаются на экране редактирования. Распространённые значения:title,editor,thumbnail,excerpt,custom-fields.has_archive— Включает страницу архива по адресу/properties/. WordPress будет искать соответствующий шаблонarchive-property.php(или вернётся кarchive.php).rewrite— Устанавливает URL-слаг. Отдельные записи будут доступны по адресу/properties/post-name/.show_in_rest— Установите это вtrue. Это открывает доступ к CPT через WordPress REST API и необходимо для корректной работы блочного редактора с вашим типом записей. Без этого редактор возвращается к классическому интерфейсу.
Discover how at OpenReplay.com.
Плагин или тема: где должен находиться код?
Это частый источник путаницы. Регистрируйте пользовательский тип записей в плагине, а не в теме.
Если регистрация вашего CPT находится в functions.php и клиент сменит тему, весь контент этого типа станет недоступным — не удалённым, но невидимым. Выделенный плагин (даже простой однофайловый плагин) сохраняет CPT активным независимо от смены темы.
Не сбрасывайте правила перезаписи при каждом запросе. Вызывайте
flush_rewrite_rules()только один раз — при активации плагина черезregister_activation_hook(). Сброс при каждомinit— это проблема производительности.
Иерархия шаблонов для пользовательских типов записей
WordPress ищет шаблоны в следующем порядке для отдельной записи CPT:
single-{post-type}.php(например,single-property.php)single.phpsingular.phpindex.php
Для архивов порядок следующий: archive-{post-type}.php → archive.php → index.php.
Заключение
С правильно подключённой к init функцией register_post_type(), включённым параметром show_in_rest и регистрацией в плагине у вас есть надёжная, переносимая основа. Отсюда вы можете добавлять пользовательские таксономии, мета-поля через ACF или API метаданных и пользовательские колонки в админ-панели — не затрагивая ничего, что может сломаться при обновлении WordPress или вашей темы.
Часто задаваемые вопросы
Контент остаётся в таблице wp_posts и не удаляется. Однако WordPress больше не распознаёт этот тип записей, поэтому записи становятся невидимыми в админ-панели и на фронтенде. Повторная активация плагина немедленно восстанавливает доступ. Вот почему регистрация CPT всегда должна находиться в выделенном плагине, а не в теме.
Да. Вы можете вызвать register_post_type() несколько раз внутри одного callback-функции init или использовать отдельные callback-функции, подключённые к init. Нет ограничений на количество пользовательских типов записей, которые может зарегистрировать один плагин, хотя каждый должен иметь уникальный слаг типа записи длиной не более 20 символов.
Почти всегда это означает, что необходимо сбросить правила перезаписи. Перейдите в Настройки, затем Постоянные ссылки в админ-панели WordPress и нажмите Сохранить изменения. Это запустит сброс правил перезаписи. Для плагинов вызывайте flush_rewrite_rules() внутри register_activation_hook(), чтобы это происходило автоматически при активации. Никогда не сбрасывайте при каждой загрузке страницы.
Строго говоря, нет, но это всё равно рекомендуется. Установка show_in_rest в true открывает доступ к вашему типу записей через WordPress REST API, что полезно для headless-конфигураций, внешних интеграций и будущей совместимости. Если вы когда-либо переключитесь на блочный редактор, он уже будет работать корректно.
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.