JetEngine для Elementor: произвольные типы записей, таксономии и связи
Создайте каталог курсов с JetEngine и Elementor: выберите типы записей, поля и таксономии, соедините курсы с преподавателями и выведите только нужные связанные записи.
В карточке курса отображаются название, изображение, тема и продолжительность. В профиле преподавателя — только его курсы. Достаточно изменить запись курса, чтобы динамические карточки получили обновлённые данные везде, где они используются. Такой каталог мы построим с помощью JetEngine для Elementor.
Пример основан на официальной документации и описывает каталог курсов. Зачисление, тесты и оформление оплаты потребовали бы отдельной реализации. Courses и Instructors хранят самостоятельные записи, термины Design и Development группируют каталог, а сохранённая связь соединяет курс с преподавателем. Тот же подход подходит для объектов недвижимости и агентов, проектов и клиентов, мероприятий и спикеров.
JetEngine отвечает за структуру данных и динамические виджеты, Elementor — за макет. Особенно важно правильно соединить эти части: даже аккуратно оформленная карточка покажет чужие курсы, если запрос начинает выборку не с того объекта.
Разберём всю цепочку от регистрации структуры до вывода на сайте, затем изменим направление связи и проверим причины пустых или неправильных списков.

Что хранить в типе записей, поле, таксономии и связи
Прежде чем открывать конструктор, перечислите нужные данные. У курса в нашем примере есть название, описание, основное изображение, продолжительность и тема. У преподавателя — имя, биография и портрет. Преподаватель существует независимо от конкретного курса и может вести несколько курсов.
Эта таблица поможет выбрать подходящий способ хранения:
| Данные | Модель | Почему подходит |
|---|---|---|
| Курс с собственной подробной страницей | Произвольный тип записей Courses | Это самостоятельная запись, которую можно редактировать |
| Профиль преподавателя | Произвольный тип записей Instructors | Один профиль используется для нескольких курсов |
| Design или Development | Таксономия Topic | Это общие категории для группировки курсов |
| Продолжительность в минутах | Метаполе Number у Courses | Значение описывает конкретный курс |
| Необязательная программа курса | Метаполе WYSIWYG у Courses | Хранит форматированный текст для отдельного раздела |
| Кто ведёт курс | Связь Instructor Courses | Соединяет две существующие записи |
В WordPress таксономия и её термины — разные сущности. Topic — название таксономии, а Design и Development — её термины. Эта модель классификации описана в документации WordPress по таксономиям.
Имя преподавателя можно было бы записывать в обычное текстовое поле. Но тогда каждый курс хранил бы собственную копию. Отдельный профиль даёт одно место для биографии и портрета, а связь определяет, с какими курсами этот профиль связан. При этом теме курса не нужна самостоятельная запись только ради метки в каталоге.
Для этого примера принимаем правило: у каждого курса один преподаватель, а у преподавателя может быть несколько курсов. Нужна связь «один ко многим». Если один курс ведут несколько преподавателей, выберите «многие ко многим». Определите это правило до создания конкретных связей.

Что понадобится для динамического контента в Elementor
Установите и активируйте JetEngine и Elementor. В руководстве Crocoblock по листингам Elementor повторяемая карточка и Listing Grid создаются с Elementor Free и JetEngine.
Для собственных шаблонов отдельных записей и архивов понадобится дополнительный инструмент. Используйте Theme Builder из Elementor Pro либо совместимую систему шаблонов, например отдельный плагин JetThemeCore. Crocoblock описывает шаблоны отдельных записей JetThemeCore для Elementor Free и JetEngine. Дополнительные возможности конструктора рассмотрены в нашем обзоре Elementor Pro.
У этих шаблонов разные задачи. Листинг определяет оформление одной повторяемой карточки. Single-шаблон задаёт подробную страницу, на которой карточки могут размещаться. Регистрация типа Courses сама по себе не создаёт ни одного из этих макетов.
Если каталог уже работает, выполняйте настройку на тестовой копии сайта. Запишите выбранные машинные идентификаторы: поля, листинги и запросы будут обращаться к ним. Если предлагаемые идентификаторы уже заняты в вашей установке, выберите другие.
Создайте произвольные типы записей JetEngine и поля курса
Откройте JetEngine → Post Types → Add New. Создайте Courses, затем повторите действия для Instructors. Этот экран регистрации разобран в руководстве Crocoblock по созданию CPT.
Для примера используем такие идентификаторы:
| Тип записей | Машинный ключ | Основное содержимое |
|---|---|---|
| Courses — курсы | wpperk_course | Название, описание в редакторе, основное изображение |
| Instructors — преподаватели | wpperk_instructor | Имя в названии, биография в редакторе, портрет как основное изображение |
Машинные ключи отличаются от понятных человеку подписей в панели управления. WordPress ограничивает идентификатор типа записей 20 символами. Префикс проекта помогает избежать совпадений с другими регистрациями. См. рекомендации WordPress по регистрации типов записей.
В расширенных настройках каждого CPT включите через Supports поддержку названия, редактора и основного изображения. Для публичного каталога включите Is Public, Publicly Queryable и Show Admin UI: записи получат публичные подробные страницы и меню редактирования. Если нужен обычный архив курсов, включите Has Archive у Courses. Назначение этих параметров объясняет справочник настроек CPT.
Для основного изображения нужна также поддержка миниатюр со стороны темы. Это условие указано в документации WordPress по возможностям типов записей.
Если хотите редактировать отдельный курс или профиль непосредственно в Elementor, включите соответствующий тип в Elementor → Settings. Эта настройка отвечает за кнопку «Edit with Elementor» и не заменяет создание листинга или назначение Single-шаблона. См. настройку редактора для CPT.
Задайте полям курса постоянные имена
В разделе метаполей Courses добавьте Duration с типом Number. Используйте идентификатор wpperk_duration_minutes, а в описании поясните, что редактор вводит число минут без единицы измерения. Сохраните 90; подпись «мин» добавим уже в шаблоне вывода.
Если программа курса должна выводиться отдельно от основного описания, добавьте необязательное поле WYSIWYG с именем wpperk_syllabus. Если отдельный раздел не нужен, оставьте описание в обычном редакторе и не создавайте лишнее поле.
У JetEngine видимая подпись поля и сохраняемый Name/ID различаются. Перед сохранением проверьте идентификатор, даже если он был заполнен автоматически. Типы Number, WYSIWYG и остальные настройки перечислены в справочнике метаполей.
Для всех записей этого примера используйте минуты. Если один редактор введёт значение в часах, общая подпись карточки станет неверной, а сравнение продолжительности потеряет смысл. Добавьте подсказку «Продолжительность в минутах», чтобы правило было понятно без дополнительных объяснений.
Добавьте таксономию Topic и заполните записи
Откройте JetEngine → Taxonomies → Add New. Назовите таксономию Topic, задайте уникальный ключ wpperk_topic и свяжите её с Courses. Сохраните таксономию, затем добавьте термины Design и Development через её меню в разделе Courses.
Выберите подходящий термин у каждого курса и сохраните запись. Регистрация таксономии создаёт систему классификации, но не распределяет по ней существующие курсы. Оба действия показаны в руководстве по настройке таксономий.
Для двух тем достаточно плоской структуры. Если позднее понадобятся ветки Design → Interface Design и Design → Graphic Design, можно использовать иерархическую таксономию. Иерархия терминов при этом остаётся отдельной от связи преподавателя с курсом.
Теперь создайте три записи преподавателей и три записи курсов. Названия и значения в таблице — учебные примеры для проверки настройки:
| Курс | Topic | Продолжительность | Кого связать с курсом |
|---|---|---|---|
| Accessible Interface Design | Design | 90 минут | Maya Chen |
| Design Systems Foundations | Design | 120 минут | Maya Chen |
| WordPress Development Basics | Development | 180 минут | Omar Ali |
Добавьте Maya Chen, Omar Ali и Lena Ortiz в Instructors. У курсов заполните описания, основные изображения и числовую продолжительность. Опубликуйте те учебные записи, которые должны быть видны в каталоге. Для Lena Ortiz пока не назначайте курсы: этот профиль поможет проверить пустой результат.
Одного определения поля недостаточно для вывода продолжительности — значение должно быть сохранено у курса. У листинга без записей тоже нет содержимого для повторения. Заполните этот небольшой набор данных до оформления каталога.
Настройте связи JetEngine и соедините конкретные записи
Откройте JetEngine → Relations → Add New. Создайте связь Instructor Courses: Parent object — Instructors, Child object — Courses, Relation type — One to many («один ко многим»).
Включите элементы управления связями для обоих объектов, чтобы редакторы могли назначать их из профиля преподавателя и из записи курса. Возможные параметры и типы связей описаны в справочнике Relations.
Здесь «родительский» и «дочерний» обозначают направление связи. Они не превращают курс в дочернюю запись преподавателя в стандартной иерархии WordPress. Учитывайте это различие при настройке запроса.
Откройте профиль Maya Chen, найдите область связанных дочерних записей, выберите два существующих курса с темой Design и сохраните изменения. Соедините Omar Ali с WordPress Development Basics. Если включены соответствующие элементы управления, преподавателя можно назначать и со стороны курса. Crocoblock отдельно описывает редактирование связанных записей.
После сохранения откройте один курс и убедитесь, что нужный преподаватель назначен. Одинаковые имена, термины таксономии или авторы записей WordPress эту связь не создают. Её создаёт сохранённое соединение двух конкретных записей.
Биографию храните у преподавателя, продолжительность — у курса. Если позднее появится совместное преподавание и роль одного человека будет различаться от курса к курсу, роль следует хранить на самой связи. JetEngine поддерживает метаданные связей и их динамический вывод.
Создайте карточку курса и повторите её через Listing Grid
В JetEngine → Listings/Components добавьте листинг: источник Posts, тип записей Courses, представление Elementor. Назовите его Course Card. Настройки источника описаны в справочнике шаблонов листинга.
Добавьте Dynamic Image с источником Post thumbnail. Затем Dynamic Field с источником Post/Term/User/Object Data и полем Title, а также Dynamic Link с источником Permalink. Эти виджеты JetEngine должны получать данные текущего курса, а не хранить текст, скопированный из первой учебной записи.
Для продолжительности добавьте ещё один Dynamic Field. Выберите источник Meta Data и поле wpperk_duration_minutes. Включите Customize field output и задайте %s мин: вместо заполнителя появится сохранённое число. Для необязательных значений решите, скрывать ли пустой виджет или показывать понятный запасной текст. Эти возможности описывает справочник Dynamic Field.
Для темы используйте виджет Dynamic Terms и выберите таксономию Topic. Метка темы и продолжительность теперь получают данные из разных источников, хотя в карточке могут выглядеть похожими элементами.
Оставьте в карточке изображение, название, тему, продолжительность и заметную ссылку на подробную страницу. Полное описание и необязательную программу разместите на странице курса. Уровень заголовка выбирайте по структуре окружающей страницы, а длинные названия проверяйте на мобильном экране.
Сохраните листинг. На обычной странице Elementor добавьте Listing Grid и выберите Course Card, чтобы проверить весь каталог. До подключения запроса по связи убедитесь, что разные курсы показывают разные названия, изображения и значения продолжительности. Так проще отличить ошибку источника данных от ошибки отбора записей.
Выведите только курсы текущего преподавателя
Карточка отвечает за оформление, запрос — за выбор записей. Для списка, основанного только на связи, откройте JetEngine → Query Builder → Add New и создайте Relations Query с названием Courses for Current Instructor.
Выберите тип Relations Query и связь Instructor Courses. Запрос должен получать дочерние записи заданного родителя, начиная с текущего объекта. Точные значения параметров:
| Параметр | Значение |
|---|---|
| Relation | Instructor Courses |
| Items to Get | Get Children Items for Fixed Parent |
| Initial Object From | Current Object ID |
Сохраните запрос и создайте Instructor Single в своей системе шаблонов. В JetThemeCore откройте Crocoblock → Theme Builder, создайте шаблон страницы и задайте условие Include → Singular → Instructors → All. Для основной области создайте шаблон Elementor. В Elementor Pro создайте Single Post и назначьте его типу Instructors через условия отображения.
Выведите динамическими виджетами имя преподавателя, основной портрет и биографию из содержимого записи. Под профилем разместите Listing Grid, выберите Course Card, включите Use Custom Query в разделе Custom Query и назначьте Courses for Current Instructor. Сохраните шаблон и проверьте, что его условия относятся к записям преподавателей.
На настоящем URL преподавателя запрос начнёт выборку с ID этого профиля и вернёт ID связанных курсов. Направление запроса и варианты исходного объекта описаны в справочнике Relations Query.
Откройте публичные профили Maya Chen, Omar Ali и Lena Ortiz. У первого должны отображаться две карточки, у второго — одна, у третьего — ни одной. Продумайте понятное пустое состояние, чтобы посетитель видел, что курсы пока не добавлены.

Используйте Posts Query, когда нужны дополнительные условия
Прямой Relations Query удобен для отбора по сохранённой связи. Если нужно явно показывать только опубликованные записи, задавать сортировку или добавлять условия по таксономиям и метаданным, создайте отдельный Posts Query.
Выберите тип записей Courses и статус Published. В Post & Page → Post In добавьте макрос Related Items. Укажите Instructor Courses, запрашивайте Child Object, а исходный ID получайте из Current Object ID. Сохраните запрос и назначьте его Listing Grid как пользовательский. Этот вариант показан в руководстве по связям между записями.
В расширенных настройках макроса задайте Fallback: ID записи, которая точно не существует в вашей установке. Пустой макрос включения иначе может оставить запрос без ограничения и вывести все записи. Такое поведение описано в руководстве по макросам Query Builder. Не считайте число из чужого примера свободным ID на своём сайте.
Повторно проверьте профиль Lena Ortiz. Затем свяжите с преподавателем черновик курса и убедитесь, что запрос только опубликованных записей его исключает. Это проверки, которые необходимо выполнить на вашей установке: одного предпросмотра в редакторе для подтверждения публичного поведения недостаточно.
Измените направление на странице курса
Создайте листинг Instructor Card из Instructors. В шаблоне Course Single используйте второй Relations Query: Items to Get → Get Parent Items for Fixed Child, Initial Object From → Current Object ID. Он получает родителей для заданного дочернего объекта. Теперь исходный объект — курс.
| Страница | Исходная запись | Что получить | Листинг |
|---|---|---|---|
| Профиль преподавателя | Текущий преподаватель | Связанные дочерние курсы | Course Card |
| Страница курса | Текущий курс | Связанные родительские профили | Instructor Card |
В модели «один ко многим» у курса будет один связанный преподаватель. В модели «многие ко многим» запрос может вернуть несколько профилей. Изменение направления вывода не меняет установленное правило связи.
Контролируйте, какой объект считается текущим
В листинге Instructors текущим объектом может быть профиль, карточка которого сейчас выводится. Во вложенном листинге Courses текущим объектом уже может стать курс. Выбирайте Default WordPress Object (for current page), если намеренно хотите получать объект внешней Single-страницы независимо от активной карточки.
Для запроса курсов такой глобальный объект всё равно должен быть преподавателем. На обычной посадочной странице это сама страница, а не автоматически выбранный преподаватель. Различие объясняет руководство по контексту связей. Не прописывайте ID Maya Chen в шаблон, предназначенный для всех преподавателей.
Проверьте данные до изменения дизайна
Если листинг показывает неправильный результат, сначала проследите сохранённые записи и запрос:
| Проблема | Что проверить сначала |
|---|---|
| У всех преподавателей одинаковые курсы | Исходный объект, фиксированный ID и назначение пользовательского запроса |
| У Lena Ortiz виден весь каталог | Пустой макрос Related Items и отсутствие Fallback в Posts Query |
| Карточек нет | Сохранённые связи, их направление и выбранный листинг |
| Везде повторяется одно название | Статический текст или неправильный контекст виджета |
| Продолжительность не отображается | Значение в записи курса и точный ключ метаполя |
| Шаблон применяется к посторонним записям | Условия Single-шаблона и запись, выбранная для предпросмотра |
Не подменяйте связь JetEngine параметром Post Parent ID. Он относится к стандартной иерархии WordPress. В варианте с макросом ID связанных записей нужно передавать в Post In. См. параметры Posts Query.
Отсоедините один курс от Maya Chen и убедитесь, что он исчез из её сетки, но сохранился как запись курса. Измените продолжительность и проверьте новое значение во всех местах вывода этой карточки. Также проверьте обратный запрос на странице курса, мобильный макет и ссылки на подробные страницы.
После этих проверок добавляйте посетительские фильтры, если они нужны каталогу. Фильтрация Listing Grid в руководстве Crocoblock использует отдельный плагин JetSmartFilters. Для добавления записей через публичную форму JetFormBuilder может сопоставлять поля формы с записью и выполнять действие Connect Relation Items совместно с JetEngine. Форму необходимо настроить отдельно: зарегистрированная в панели связь сама по себе не создаёт такой рабочий процесс.
Начните с трёх учебных курсов и подтвердите правильность модели, сохранённых связей и обоих направлений запроса. Затем расширяйте каталог через те же поля редактирования. Для следующего курса понадобится новая запись, тема и связь с преподавателем; повторяемый макет Elementor уже сможет её отобразить.