Проект Papi расширяет возможности WordPress с помощью добавления Page Type API для страниц

Используйте кастомную логику представления без регистрации нового пост-типа. Нет нужды плодить CPT ради нескольких уникальных страниц. Достаточно определить класс с нужными параметрами – и всё. У вас будет доступ к мета-полям, шаблонам, хукам, без перегрузки ядра.

Пример простой конфигурации:


class About_Page_Type extends \\YourNamespace\\PageType {
public function register() {
$this->name = \'О компании\';
$this->template = \'templates/about.php\';
}
}

Не используйте глобальные мета-боксы – вместо этого определяйте поля внутри структуры типа. Они будут загружаться только тогда, когда это действительно нужно.


public function fields() {
return [
Text::make(\'Заголовок\'),
Textarea::make(\'Описание\'),
];
}

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

Отдельное внимание: порядок загрузки файлов шаблонов. Подключение нестандартных шаблонов работает через фильтр template_include. Это дает контроль над маршрутизацией без хака ядра.

Никаких switch-case в functions.php. Всё логично организовано, классы разнесены по файлам, поддержка autoload из Composer работает без нареканий.

Внимание! Не пытайтесь использовать классы типов внутри хуков до инициализации. Структура должна быть зарегистрирована после init, иначе система просто проигнорирует её.

Как итог: никаких лишних CPT, всё на уровне обычных страниц, но с возможностями конструкторов данных. Это решение – не про маркетинг, а про архитектуру. Сухую, логичную, функциональную.

Как использовать Page Type API для создания уникальных шаблонов страниц

Определите новый тип шаблона через PHP-файл внутри каталога lib/page-types. Название файла должно соответствовать имени будущего шаблона, например: custom-landing.php.

Внутри этого файла регистрируйте структуру, используя массив с ключами name, template, post_type, options. Пример:


class CustomLandingType extends \\Papi\\Page\\Type {
public function __construct() {
$this->box( \'Основные настройки\', [
papi_property( [
\'slug\' => \'hero_title\',
\'title\' => \'Заголовок\',
\'type\' => \'string\',
] ),
papi_property( [
\'slug\' => \'hero_image\',
\'title\' => \'Изображение\',
\'type\' => \'image\',
] )
] );
}
public function get_template() {
return \'templates/custom-landing.php\';
}
public function get_post_type() {
return \'page\';
}
}

Важно соблюдать строгую связь между файлом шаблона, указанным в get_template(), и реально существующим PHP-шаблоном в каталоге templates. Отсутствие шаблона вызовет ошибку отображения.

В интерфейсе админки после регистрации появляется выбор нужного шаблона при создании новой записи. Название определяется через метод get_label().

Настройка свойств осуществляется через papi_property. Типы данных ограничены: строка, изображение, чекбокс, редактор, список. Используйте только поддерживаемые типы. Никакой самодеятельности.

Внимание! Если вы не определите get_post_type(), шаблон не будет доступен ни в одном типе записей.

Используйте метод show_on_page(), если требуется ограничить шаблон для конкретных ID страниц. Это полезно при создании лендингов под кампании или уникальных посадочных страниц:

Читайте также:  Основы работы с WordPress для начинающих и первые шаги в создании сайта


public function show_on_page( $post_id ) {
return $post_id === 42;
}

Важно помнить: каждый шаблон должен быть изолирован. Не дублируйте поля между типами. Наследование здесь не работает.

Все данные, введенные в этих полях, доступны через papi_get_field( $post_id, \'field_slug\' ). Не используйте get_post_meta() – значения сериализованы особым образом.

Хотите шаблон с кастомным набором блоков, редактором и условиями видимости? Тогда этот подход – молоток. Но помните: один удар – один результат. Упростите структуру до предела. Без магии.

Настройка кастомных полей через Page Type API в Papi

Создавайте поля напрямую в классе типа страницы. Не через интерфейс. Не через хуки. Только через код. Это единственный способ добиться предсказуемого поведения и полной управляемости.

Добавление полей происходит в методе register_fields. Пример:


public function register_fields() {
  $this->box( \'Основные настройки\', [
    papi_property( [
      \'slug\' => \'subtitle\',
      \'title\' => \'Подзаголовок\',
      \'type\' => \'string\'
    ] )
  ] );
}

Поля группируются в боксы. Это обязательная структура. Без бокса – не работает. Поле может быть любого типа: string, bool, file, image, repeater, flex. Некоторые из них требуют дополнительных настроек, особенно repeater и flex – там вложенность, и нужно описывать каждое подполе отдельно.

Пример вложенного repeater:


papi_property( [
  \'slug\' => \'faq\',
  \'title\' => \'Часто задаваемые вопросы\',
  \'type\' => \'repeater\',
  \'settings\' => [
    \'items\' => [
      papi_property( [
        \'slug\' => \'question\',
        \'title\' => \'Вопрос\',
        \'type\' => \'string\'
      ] ),
      papi_property( [
        \'slug\' => \'answer\',
        \'title\' => \'Ответ\',
        \'type\' => \'text\'
      ] )
    ]
  ]
] )

Важно! Не используйте одинаковые slug в разных типах страниц. Это приводит к коллизиям данных и потере значений в интерфейсе.

Сортировка, отображение, скрытие – всё контролируется опциями внутри массива papi_property. Можно задать default, description, placeholder, required. Но не переусердствуйте: чем больше ограничений, тем выше шанс на конфликт с кастомной логикой темы.

Есть подводные камни. Поля типа file и image могут не работать, если отключены соответствующие MIME-типы в настройках загрузки. Проверьте functions.php, прежде чем искать ошибку в коде поля.

Помните: поле не отобразится, если не указано в возвращаемом массиве в методе register_fields. Даже если вы его описали, оно не появится без этого шага.

Добавлять кастомные валидаторы – боль. Делается через papi/validate/property, но требует глубокого контроля над данными. Ошибки не отображаются явно. Отладка только через консоль и error_log.

Настройка кастомных полей – не декорация. Это жесткая структура хранения данных. Точность, минимализм и строгая типизация – три кита. Ошибка в одном параметре – сломана вся страница. Без предупреждений.

Читайте также:  Новый менеджер блоков и усиленная защита от критических ошибок в WordPress

Хотите стабильности? Используйте только проверенные типы и минимальное количество уровней вложенности. Чем проще – тем живучее.

Интеграция Page Type API с существующими темами WordPress

Подключение механизма к активной теме – не рутинная задача. Первое: отключи автоматическое подключение типов через фильтр papi/settings/show_editor, если в теме используются кастомные шаблоны. Конфликт будет незаметен до первого сохранения страницы.

Шаблоны должны включать явный вызов the_content(). Без этого контент просто не отрендерится. Простейшая ловушка, в которую попадают даже опытные разработчики. Тема живет, а контент – мертв.

Названия классов типов должны соответствовать файловой структуре. Например, файл page-types/SingleProductPage.php требует класс SingleProductPage. Пропустишь – редактор не увидит тип, даже если он существует.

Важно: не размещай определения классов в functions.php. Используй отдельную папку и автозагрузку через composer или spl_autoload_register.

Если тема использует кастомные поля ACF, инициализация происходит раньше загрузки типа. Результат – сброшенные значения, пустые блоки, полная анархия. Используй хук acf/init внутри конструктора типа, а не в глобальном контексте.

Переопределение шаблона происходит через фильтр template_include. Укажи свой путь, например:


add_filter(\'template_include\', function($template) {
  if (is_singular(\'product\')) {
    return get_template_directory() . \'/templates/single-product.php\';
  }
  return $template;
});

Избегай использования get_page_template(). Этот вызов игнорирует механизм выбора типа и подсовывает дефолт. И да, фильтр papi/settings/show_only_page_type_ui может скрыть редактор полностью – если ты случайно вернешь true глобально.

Интеграция невозможна без учета хука init. Подключай типы строго после этого события. Лучше – внутри after_setup_theme. Гарантия, что всё, что нужно, уже доступно. Убери типы раньше – столкнешься с пустым UI.

Помните: если используешь кастомную иерархию шаблонов, настрой papi/settings/page_type_directory вручную. Автопоиск не охватывает вложенные папки.

Таблица отображения соответствий для интеграции:

Тип страницы Путь до файла Класс Шаблон
Продукт /page-types/SingleProductPage.php SingleProductPage single-product.php
Событие /page-types/EventType.php EventType event.php
Главная /page-types/HomeType.php HomeType front-page.php

Проверь структуру темы. Использует ли она get_template_part()? Тогда внедрение – через частичные шаблоны с передачей данных из типа. Но не через глобальные переменные – используем фильтры, массивы и явные include.

Читайте также:  Китай заблокировал Gravatar и WordPress.com и как обойти Великий китайский файрвол для доступа к этим сервисам

Хочешь, чтобы редактор появился только на нужных страницах? Используй papi/settings/show_page_type. Верни false там, где вмешательство недопустимо: архивы, поиск, 404.

И помни: интеграция – не добавление кода, это хирургия. Режь точно, подключай аккуратно. Иначе всё рухнет.

Управление отображением контента на основе типов страниц в Papi

Сразу: логика показа контента должна основываться на проверке текущего шаблона или конкретного свойства. Игнорировать это – гарантировать хаос в админке и на фронте.

Если нужен разный контент на разных типах – проверяйте уникальные идентификаторы шаблонов через get_post_meta() или используйте фильтрацию по условию papi_get_page_type(). Пример:


if ( papi_get_page_type( get_the_ID() ) === \'custom-article\' ) {
  echo \'Отображается только на типе custom-article\';
}

Динамика начинается, когда условия становятся сложнее. Используйте is_singular() в паре с papi_get_page_type() для построения гибкой архитектуры шаблонов. Код работает как швейцарские часы только при условии, что вы не доверяете интерфейсу и вручную контролируете значения ключей мета-полей.

Рассмотрим фильтрацию меню:


if ( papi_get_page_type() === \'landing\' ) {
  wp_nav_menu( [ \'theme_location\' => \'landing_menu\' ] );
} else {
  wp_nav_menu( [ \'theme_location\' => \'default_menu\' ] );
}

Меню – лишь один пример. Блоки, шорткоды, вызовы API, фильтрация REST – всё это должно учитывать тип текущего объекта. Ошибка – делать общую обвязку, не проверяя контекст.

Важно помнить: проверка типа должна идти первой в цепочке условий. Никаких get_post_type() – используйте нативные методы контекстного доступа.

Игра начинается, когда нужно менять поля админки. Используйте papi_property с параметром show_if:


public function show() {
  return [
    papi_property( [
      \'title\' => \'Скрытое поле\',
      \'slug\' => \'hidden_field\',
      \'type\' => \'string\',
      \'show_if\' => [
        \'field\' => \'toggle_visibility\',
        \'operator\' => \'===\',
        \'value\' => true
      ]
    ] )
  ];
}

Сложные структуры? Вынесите логику в отдельные классы. Старайтесь минимизировать условия в шаблонах – от этого зависит читаемость и дебаг. Чем больше условий на фронте – тем хуже ваша архитектура.

Внимание! Никогда не полагайтесь на визуальные признаки в админке. Настройка должна проверяться только через данные, а не через внешний вид.

  • Используйте уникальные слуги при регистрации
  • Не дублируйте поля между типами
  • Храните зависимости в конфигурации, не в логике шаблонов
  • Тестируйте условия в разных языках и мультисайтах

Не стройте логику отображения на post_type. Это ловушка. Единственный надёжный источник истины – ID шаблона, возвращённый ядром. Не используйте wp_query для фильтрации – только конкретная привязка к типу и значение поля. Это не опция. Это необходимость.

Оставьте комментарий

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