Структура блочной темы
У мастерской согласованы материалы, роли и адреса. Теперь отделим содержимое от внешней оболочки. Блочная тема WordPress хранит шаблоны в виде блоковой разметки, которую движок соединяет с текущими данными. Результат урока — минимальная собственная тема pw-workshop, достаточно маленькая для понимания каждого файла. Она не содержит готовый коммерческий дизайн, систему курсов или импорт прежних страниц.
Для определения самостоятельной блочной темы нужны style.css с заголовком темы и templates/index.html. Файл theme.json полезен для настроек, но не является обязательным признаком блочной темы. Это различие закреплено в руководстве по структуре темы. В данном шаге намеренно начнём с двух обязательных файлов; общие части и настройки добавим последовательно, чтобы видеть задачу каждого слоя.
Два файла и один резервный шаблон
В отдельной учебной установке каталог темы имеет путь wp-content/themes/pw-workshop/. Заголовок style.css позволяет панели определить название и сведения о теме. Сам файл пока содержит только комментарий: оформление блоков WordPress и базовые правила среды будут отличаться от нашей будущей палитры. Не обещаем загрузку произвольных CSS-правил без enqueue. В блочной теме многие визуальные настройки позже будут передаваться через theme.json, без дополнительного functions.php.
Полное содержимое style.css:
/*
Theme Name: PW Workshop
Description: Minimal educational block theme for Web Workshop.
Version: 0.1.0
Requires at least: 7.1
Requires PHP: 8.3
Text Domain: pw-workshop
*/
Полное содержимое templates/index.html:
<!-- wp:site-title {"level":1} /-->
<!-- wp:query {"query":{"perPage":6,"pages":0,"offset":0,"postType":"post","order":"desc","orderBy":"date","author":"","search":"","exclude":[],"sticky":"","inherit":true}} -->
<div class="wp-block-query"><!-- wp:post-template -->
<!-- wp:post-title {"isLink":true,"level":2} /-->
<!-- wp:post-excerpt /-->
<!-- /wp:post-template -->
<!-- wp:query-pagination -->
<div class="wp-block-query-pagination"><!-- wp:query-pagination-previous /-->
<!-- wp:query-pagination-numbers /-->
<!-- wp:query-pagination-next /--></div>
<!-- /wp:query-pagination -->
<!-- wp:query-no-results -->
<!-- wp:paragraph -->
<p>Материалы не найдены.</p>
<!-- /wp:paragraph -->
<!-- /wp:query-no-results --></div>
<!-- /wp:query -->
Сначала активируйте тему только на своём стенде и откройте ленту записей. Ожидаются название сайта, три заголовка записей со ссылками и краткие описания. Здесь активация не выполнялась. Если записи остались черновиками, анонимная лента не покажет их: отсутствие элементов не доказывает ошибку Query. Для этого шага можно опубликовать три учебные записи внутри закрытой установки, сохранив их адресную карту и отличая её от рабочей среды.
Откуда берётся содержимое списка
Блок Query задаёт контекст выборки, а Post Template повторяет дочерние блоки для каждой найденной записи. Post Title и Post Excerpt относятся к текущему элементу, поэтому не содержат наших трёх заголовков буквально. Изменение названия записи в панели должно отразиться в списке без правки файла темы. Так мы отделяем данные от структуры представления. Если вставить заголовки вручную обычными Heading, список перестанет обновляться вместе с материалами.
В примере inherit: true означает наследование основного запроса страницы. Остальные поля показывают форму настроек блока, но не следует считать perPage: 6 гарантированным размером основного запроса при таком наследовании. Для ленты количество записей связано с настройкой чтения, а для архива — с основным запросом. Это важная граница: код блока и серверная выборка не всегда имеют одинаковый источник значения. В уроке о поиске будем менять основной запрос осмысленно.
Пагинация отображает ссылки между страницами результата, а не между уроками одного курса. На наших трёх записях её почти нечего демонстрировать. Чтобы исследовать вторую страницу, позже добавим ещё три записи и согласуем маленький размер списка. Не утверждаем, что цифры пагинации уже появились. Подготовленный шаблон содержит соответствующие блоки, но фактический вывод зависит от количества публичных записей и параметров запроса.
Почему index не решает все страницы
index.html является резервным шаблоном и может использоваться, когда более подходящего файла нет. Поэтому минимальная тема определяется движком, но ещё не показывает одиночную страницу так, как мы хотим. Открытие /study/ в этом состоянии не обязано вывести полноценный текст страницы: внутри шаблона есть список, а не Post Content. Это сознательная граница урока. В следующем шаге добавим page.html и single.html, которые используют текущий объект отдельно от списка.
Порядок выбора описан в иерархии шаблонов. Более специфичный шаблон подходит определённому виду запроса, а резервный обеспечивает последнюю возможность представления. Не копируйте index.html в десяток файлов «на всякий случай». Копии быстро расходятся: один получает исправление навигации, другой остаётся старым. Сначала выделим общий хедер и футер, затем небольшое различающееся содержимое страницы и записи.
Ещё один источник представления — изменения, сохранённые редактором сайта в базе. Если вы уже экспериментировали с той же темой, файл на диске может перестать быть фактическим активным вариантом. В учебном состоянии предполагаем отсутствие таких пользовательских переопределений. При несоответствии вывода сначала проверьте источник выбранного шаблона. Перезаписывание файлов и очистка браузерного кеша не устраняют сохранённый в базе альтернативный шаблон.
Сохраняйте файлы в UTF-8 и не меняйте расширение шаблона на .php по аналогии с классической темой. Комментарии блоков читаются WordPress как описание дерева, а HTML внутри задаёт сохранённую структуру. Вставка PHP-кода непосредственно в такой HTML-шаблон не является способом выполнить серверную логику. Для функции приложения позже создадим плагин. Это разделение помогает держать тему понятной: дизайнер меняет блоки, а обработка данных остаётся в месте, которое не исчезает при переключении оформления.
После активации посмотрите запись темы в панели и доступные шаблоны. Название PW Workshop берётся из заголовка stylesheet, а не из имени каталога или названия сайта. Тема и сайт также различаются по версии: обновление WordPress не увеличивает автоматически Version нашего кода. Когда расширяем собственную тему, меняем её версию осмысленно и сохраняем снимок. В архиве начальное состояние 09 и конечное состояние 10 находятся отдельно, поэтому последующие файлы не скрывают намеренно минимальную структуру первого примера.
Наблюдаемый результат и граница
Сверьте название темы в панели, ленту трёх записей, ссылки на их согласованные адреса и сообщение пустого результата при отсутствии публикаций. Для каждого пункта в архиве предусмотрено ожидаемое состояние, а наблюдаемое значение оставлено not_run. У темы нет скриншота подтверждённого вывода, собственных CSS-ресурсов, переводов или поддержки всех видов архива. Эти функции не следует подразумевать по наличию заголовка Theme Name.
Попробуйте изменить заголовок одной записи, сохранив её слаг. Лента должна взять новый текст из базы и оставить ссылку на прежний адрес. Именно этот небольшой эффект объясняет основную роль темы: менять представление известных сущностей без дублирования редакционных данных. Следующая глава расширит тот же каталог pw-workshop, подключив общую оболочку и полноценное содержимое одиночного документа.