Advanced Custom Fields (ACF) – плагин, с которым WordPress перестаёт упираться в «заголовок + текст + миниатюра». Вы описываете нужные поля в админке, привязываете их к страницам, записям или CPT и выводите в шаблоне темы. Ниже практичный маршрут: установка, набор полей, вывод в single-шаблоне и Flexible Content для сборных страниц.
Зачем ACF, если есть редактор
Стандартного редактора хватает для блога. Когда структура данных жёстче, поля спасают:
- портфолио с галереей, датой и ссылками на проект;
- карточки объектов (недвижимость, услуги, товары) с ценой, площадью, адресом;
- корпоративные лендинги с повторяемыми секциями;
- блог или каталог с разными макетами блоков на одной странице.
Пример: сайт агентства недвижимости. У каждого объекта – цена, комнаты, локация, площадь, галерея. В контент это запихивать неудобно: редактор путает данные, вёрстка плывёт. ACF даёт отдельные поля и предсказуемый вывод в шаблоне.
Установка
- В админке: Плагины → Добавить новый.
- Поиск: Advanced Custom Fields.
- Установить и активировать.
Бесплатной версии часто достаточно. Flexible Content, Options Pages и часть продвинутых типов – в ACF PRO. Ниже примеры с Flexible Content ориентированы на PRO; базовый вывод get_field / the_field работает и в free.
Создание набора полей
Зачем отдельные поля
Пользовательские поля фиксируют структуру: редактор заполняет форму, шаблон всегда знает, откуда брать цену, галерею или URL. Меньше «кривого» HTML в теле записи, проще менять дизайн.
Кейс: портфолио фотографа. На проект логично завести:
- описание;
- галерею;
- ссылки (сайт, профили);
- дату завершения.
Первый field group
- Перейдите в ACF → Field Groups (или «Группы полей») → Add New.
- Название, например: «Детали проекта».
- Добавьте поля с понятными Field Name (латиница, snake_case – именно они идут в код):
project_title– Text;project_gallery– Gallery;social_url– URL;finish_date– Date Picker.
В правилах показа (Location) укажите, где группа видна: тип записи «Проект», шаблон страницы или обычные Pages. Иначе поля появятся везде или нигде.
В интерфейсе ACF можно назвать поля по-русски в Label, но Name лучше держать латиницей: project_title, а не «название_проекта». Так проще поддержка и меньше сюрпризов с кодировкой.
Вывод полей в шаблоне
Допустим, CPT «project» и шаблон single-project.php. Базовый вывод:
<?php if ( get_field( 'project_title' ) ) : ?>
<h1><?php the_field( 'project_title' ); ?></h1>
<?php endif; ?>
<?php
$gallery = get_field( 'project_gallery' );
if ( $gallery ) :
?>
<div class="project-gallery">
<?php foreach ( $gallery as $image ) : ?>
<img src="<?php echo esc_url( $image['url'] ); ?>"
alt="<?php echo esc_attr( $image['alt'] ); ?>">
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php if ( get_field( 'social_url' ) ) : ?>
<a href="<?php echo esc_url( get_field( 'social_url' ) ); ?>" target="_blank" rel="noopener noreferrer">
Ссылка на проект
</a>
<?php endif; ?>
<?php if ( get_field( 'finish_date' ) ) : ?>
<p>Дата завершения: <?php the_field( 'finish_date' ); ?></p>
<?php endif; ?>
Коротко по API:
get_field( 'name' )– вернуть значение (для условий и обработки);the_field( 'name' )– сразу вывести;- всегда проверяйте, что поле заполнено, и экранируйте URL и атрибуты (
esc_url,esc_attr,esc_html).
Для Gallery ACF обычно отдаёт массив изображений – удобнее цикл, чем «вывести as is». Тип Image может отдавать ID, URL или массив: смотрите Return Format в настройках поля.
Flexible Content: гибкие секции страницы
Когда у лендинга разный набор блоков (текст, картинка, CTA) и редактор должен собирать страницу сам, удобен тип Flexible Content (ACF PRO). В админке создаёте layouts, в шаблоне – цикл по рядам.
- Новая группа полей, поле типа Flexible Content, name например
page_sections. - Внутри – layouts:
text_block,image_block,cta_buttonс sub fields. - Location: нужный шаблон страницы.
- В шаблоне:
<?php if ( have_rows( 'page_sections' ) ) : ?>
<?php while ( have_rows( 'page_sections' ) ) : the_row(); ?>
<?php if ( get_row_layout() === 'text_block' ) : ?>
<div class="text-block">
<?php echo wp_kses_post( get_sub_field( 'text' ) ); ?>
</div>
<?php elseif ( get_row_layout() === 'image_block' ) : ?>
<?php
$img = get_sub_field( 'image' );
if ( $img ) :
$src = is_array( $img ) ? $img['url'] : $img;
?>
<div class="image-block">
<img src="<?php echo esc_url( $src ); ?>" alt="Advanced Custom Fields: шаблоны страниц и гибкие макеты в WordPress">
</div>
<?php endif; ?>
<?php elseif ( get_row_layout() === 'cta_button' ) : ?>
<a href="<?php echo esc_url( get_sub_field( 'link' ) ); ?>" class="cta-button">
<?php echo esc_html( get_sub_field( 'button_text' ) ); ?>
</a>
<?php endif; ?>
<?php endwhile; ?>
<?php endif; ?>
Ключевые функции:
have_rows()/the_row()– обход повторителей и flexible;get_row_layout()– какой layout сейчас;get_sub_field()/the_sub_field()– поля внутри ряда.
Практические советы
- Не раздувайте группы. Сначала схема данных на бумаге, потом поля. Лишние 30 полей «на всякий случай» усложняют жизнь редактору.
- Имена полей стабильны. Переименование name ломает уже заполненные данные в шаблонах.
- Кэш. На тяжёлых страницах с кучей get_field смотрите object cache / page cache. Не дёргайте одни и те же поля в цикле без нужды.
- ACF Blocks. Можно регистрировать блоки для Gutenberg на базе ACF – удобно, если контент живёт в редакторе, а не только в page template.
- Безопасность. Не выводите сырые URL и HTML без экранирования и санитизации.
Итог
ACF закрывает разрыв между «просто постом» и нормальной контентной моделью: поля в админке, чистый вывод в теме, при необходимости – flexible-секции. Старт простой: одна группа, 3-4 поля, single-шаблон. Дальше – CPT, flexible и блоки, когда структура проекта это оправдает.

