WPPerks
Конструкторы страниц12 мин чтенияРедакция WPPerks

JetEngine для Elementor: произвольные типы записей, таксономии и связи

Создайте каталог курсов с JetEngine и Elementor: выберите типы записей, поля и таксономии, соедините курсы с преподавателями и выведите только нужные связанные записи.

В карточке курса отображаются название, изображение, тема и продолжительность. В профиле преподавателя — только его курсы. Достаточно изменить запись курса, чтобы динамические карточки получили обновлённые данные везде, где они используются. Такой каталог мы построим с помощью JetEngine для Elementor.

Пример основан на официальной документации и описывает каталог курсов. Зачисление, тесты и оформление оплаты потребовали бы отдельной реализации. Courses и Instructors хранят самостоятельные записи, термины Design и Development группируют каталог, а сохранённая связь соединяет курс с преподавателем. Тот же подход подходит для объектов недвижимости и агентов, проектов и клиентов, мероприятий и спикеров.

JetEngine отвечает за структуру данных и динамические виджеты, Elementor — за макет. Особенно важно правильно соединить эти части: даже аккуратно оформленная карточка покажет чужие курсы, если запрос начинает выборку не с того объекта.

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

Логотип JetEngine над типами записей курсов и преподавателей, терминами таксономии тем и схемой связи одного преподавателя с несколькими курсами.
Общая схема: типы записей хранят самостоятельные сущности, таксономии группируют курсы, а связи соединяют курсы с преподавателями.

Что хранить в типе записей, поле, таксономии и связи

Прежде чем открывать конструктор, перечислите нужные данные. У курса в нашем примере есть название, описание, основное изображение, продолжительность и тема. У преподавателя — имя, биография и портрет. Преподаватель существует независимо от конкретного курса и может вести несколько курсов.

Эта таблица поможет выбрать подходящий способ хранения:

ДанныеМодельПочему подходит
Курс с собственной подробной страницейПроизвольный тип записей CoursesЭто самостоятельная запись, которую можно редактировать
Профиль преподавателяПроизвольный тип записей InstructorsОдин профиль используется для нескольких курсов
Design или DevelopmentТаксономия TopicЭто общие категории для группировки курсов
Продолжительность в минутахМетаполе Number у CoursesЗначение описывает конкретный курс
Необязательная программа курсаМетаполе WYSIWYG у CoursesХранит форматированный текст для отдельного раздела
Кто ведёт курсСвязь Instructor CoursesСоединяет две существующие записи

В WordPress таксономия и её термины — разные сущности. Topic — название таксономии, а Design и Development — её термины. Эта модель классификации описана в документации WordPress по таксономиям.

Имя преподавателя можно было бы записывать в обычное текстовое поле. Но тогда каждый курс хранил бы собственную копию. Отдельный профиль даёт одно место для биографии и портрета, а связь определяет, с какими курсами этот профиль связан. При этом теме курса не нужна самостоятельная запись только ради метки в каталоге.

Для этого примера принимаем правило: у каждого курса один преподаватель, а у преподавателя может быть несколько курсов. Нужна связь «один ко многим». Если один курс ведут несколько преподавателей, выберите «многие ко многим». Определите это правило до создания конкретных связей.

Модель курса в JetEngine: отдельные записи преподавателя и курса, термины Topic и поле продолжительности
Схема модели: преподаватели связаны с курсами, а тема и продолжительность описывают курсы разными способами.

Что понадобится для динамического контента в 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 DesignDesign90 минутMaya Chen
Design Systems FoundationsDesign120 минутMaya Chen
WordPress Development BasicsDevelopment180 минут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. Запрос должен получать дочерние записи заданного родителя, начиная с текущего объекта. Точные значения параметров:

ПараметрЗначение
RelationInstructor Courses
Items to GetGet Children Items for Fixed Parent
Initial Object FromCurrent 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. У первого должны отображаться две карточки, у второго — одна, у третьего — ни одной. Продумайте понятное пустое состояние, чтобы посетитель видел, что курсы пока не добавлены.

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

Используйте 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 уже сможет её отобразить.