Повторяющиеся (repeater) поля Carbon Fields

В этом уроке хотел бы совсем немного поговорить про repeater-поля (Complex fields) в плагине Carbon Fields и показать вам пару примеров.

Уже две недели я выхваливаю этот плагин, конечно же только потому что он мне понравился, я ни с кем не партнёрился.

Также не забывайте прочекать мой видеокурс по созданию темы WordPress на основе готовой вёрстки.

Что такое repeater-поля?

Давайте я наверное сначала покажу вам пример, как это выглядит в админке:

повторяющееся поле в Carbon Fields

На фото выше вы можете заметить, что мы можем добавлять какое-то количество блоков, причём разного типа (с текстом, с фото и с текстом и ссылкой), кроме того их можно менять местами.

Подобное поле на клиентском сайте используется для вывода вот этих блоков:

повторяющиеся блоки на сайте

В самом конце урока вы найдёте видео, в котором я пошагово создавал эти блоки.

Создание повторяющегося поля

Вообще в самом плагине Carbon Fields это поле называется Complex, но все уже привыкли к названию repeater или повторяющиеся поля, потому что оно более подробно описывать, о чём вообще всё это.

Вот супер-лёгкий пример создания повторяющего поля:

Field::make( 'complex', 'truemisha_slider', 'Слайдер' )
	->add_fields( array(
		Field::make( 'text', 'title', 'Заголовок слайда' ),
		Field::make( 'image', 'photo', 'Изображение слайда' ),
	) ),

И не забываем про хук carbon_fields_register_fields и в самом начале кода в файле вызвать:

use Carbon_Fields\Container;
use Carbon_Fields\Field;

Если вы забываете об этом, то рекомендую вернуться к вступительному уроку про Carbon Fields.

После вставки его в код, у вас появится:

Получение значений поля в коде

Окей, поля в админке есть, как теперь получить их значения? Помните в руководстве по Carbon Fields я говорил, что не для всех типов полей можно спокойно использовать get_post_meta() ? Вот complex field это как раз и есть такое поля. Поэтому мы будем использовать carbon_get_post_meta() ну или ту функцию, которая предназначена для настроек таксономий, опций и так далее, в зависимости от того, где вы создаёте поля.

$slides = carbon_get_post_meta( get_the_ID(), 'truemisha_slider' );
 
if( $slides ) {
	foreach( $slides as $slide ) {
		// смысла в слайде ведь нет, если не используется фото??
		if( ! $slide[ 'photo' ] ) {
			continue; // скипаем итерацию цикла, если нет фотки
		}
		echo '<div class="slide">';
		echo wp_get_attachment_image( $slide[ 'photo' ] );
		if( $slide[ 'title' ] ) { // empty() и isset() нет нужды использовать тут
			echo '<h2>' . esc_html( $slide[ 'title' ] ) . '</h2>';
		}
		echo '</div>'
	}
}

Код очень примерный, но я тем не менее старался сделать его максимально подробным, чтобы вы не забывали учитывать «проверки на дурака», например когда пользователь сайта не заполнил фотку или решил поразвлекаться с HTML-тегами внутри заголовка слайда.

Ширина полей внутри группы

Если вы взглянете на поля настроек нашего слайдера, то заметите, что поле заголовка какой-то невероятной длины, я поле изображения едва ли занимает 1/4 часть от экрана!

очень большая ширина поля в группе полей

Хорошая новость – мы можем задавать ширину полей в процентах (работает на flex-basis). Например у нас тут с вами два поля, причём для изображения нужно совсем немного места, я думаю 25% будет ок, а остальное можно оставить для заголовка. Но я попробовал такой вариант и решил разделить поля 50 на 50, так оказалось красивее, для этого я использовал метод set_width().

Field::make( 'complex', 'truemisha_slider', 'Слайдер' )
	->add_fields( array(
		Field::make( 'text', 'title', 'Заголовок слайда' )->set_width( 50 ),
		Field::make( 'image', 'photo', 'Изображение слайда' )->set_width( 50 ),
	) ),

И вот результат:

поля в две колонки внутри группы полей carbon fields

Разные группы полей в пределах одного репитера

Хорошо, идём апгрейдить наш слайдер дальше – что если там будет не только фото, но и видео! Причём в любом порядке!

Тут на самом деле всё легко, чтобы в один репитер добавлять разные группы, мы всего лишь снова и снова используем метод add_fields().

Field::make( 'complex', 'truemisha_slider', 'Слайдер' )
	->add_fields( 'image', 'Изображение', array(
		Field::make( 'text', 'title', 'Заголовок слайда' ),
		Field::make( 'image', 'photo', 'Изображение слайда' ),
	) )
	->add_fields( 'movie', 'Видос', array(
		Field::make( 'text', 'title', 'Заголовок слайда' ),
		Field::make( 'file', 'video', 'Видео слайда' ),
	) ),

На скриншоте ниже понятно, что при нажатии на кнопку добавления группы, вы можете выбрать, какая это будет группа – с фото или с видео:

Разные группы полей внутри поля complex в carbon field

Ах да, когда будете выводить такое поле на сайте, то у каждого слайда появится параметр типа, а именно $slide[ '_type' ], который будет равен или image или movie.

Отображение в виде вкладок

Возможно вы не захотите, чтобы поля шли друг за другом вертикально, тогда хочу предложить вам ещё две опции – это отображение полей в виде горизонтальных и вертикальных вкладок, для этого мы будем использовать метод set_layout() непосредственно к комплексному полю.

Например:

Field::make( 'complex', 'truemisha_slider', 'Слайдер' )->set_layout( 'tabbed-horizontal' )

Получается:

горизонтальные вкладки комплексного поля carbon fields

Или например:

Field::make( 'complex', 'truemisha_slider', 'Слайдер' )->set_layout( 'tabbed-vertical' )

Получается:

вертикальные вкладки комплексного поля карбон филдс

Вложенность. Одно комплексное поле внутри другого комплексного поля.

Да – внутри репитера может быть ещё один репитер! 🤯

Ну и это прекрасно, я думаю. Правда я не знаю, как это можно применить к нашему примеру слайдера. Давайте сделаем как в официальной документации – заменим поле заголовка на репитер, т е возможность добавлять несколько текстовых элементов.

Field::make( 'complex', 'truemisha_slider', 'Слайдер' )
	->add_fields( array(
		Field::make( 'image', 'photo', 'Изображение слайда' ),
		Field::make( 'complex', 'slide_fragments', 'Надписи на слайде' )
			->add_fields( array(
				Field::make( 'text', 'fragment_text', 'Текст'  ),
				Field::make( 'select', 'fragment_position', 'Расположение' )
					->add_options( array( 'Сверху слева', 'Сверху справа', 'Снизу слева', 'Снизу справа' ) ),
			))
	)),

Ну и в админке это будет выглядеть вот так:

вложенность повторяющегося поля carbon fields

Установка максимального количества повторений полей

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

Field::make( 'complex', 'truemisha_slider', 'Слайдер' )->set_max( 5 ) // 5 слайдов это уже норм!

Это будет работать таким образом, что при добавлении 5-го слайда, кнопка добавления повторения поля будет исчезать – удобно!

Разрешаем или нет дублирование полей

У каждой повторяющейся группы полей рядом с кнопкой удаления есть кнопка дублирования группы:

Эту кнопку можно отключить методом set_duplicate_groups_allowed().

Field::make( 'complex', 'truemisha_slider', 'Слайдер' )->set_duplicate_groups_allowed( false )

Заголовки групп

Выше в примерах вы уже могли заметить, что я добавлял заголовки группам, но это были очень примитивные заголовки типо «Изображение» или «Видео», но самое интересное начинается тогда, когда к этим заголовкам мы можем добавлять ещё и значение одного из поля внутри группы!

Например использовав метод set_header_template() и вот такой код:

Field::make( 'complex', 'truemisha_slider', 'Слайдер' )
	->add_fields( 'image', 'Изображение', array(
		Field::make( 'text', 'title', 'Заголовок слайда' ),
		Field::make( 'image', 'photo', 'Изображение слайда' ),
	) )
	->set_header_template( '
		<% if (title) { %>
			Изображение: <%- title %>
		% } %>
	' )
	->add_fields( 'movie', 'Видос', array(
		Field::make( 'text', 'title', 'Заголовок слайда' ),
		Field::make( 'file', 'video', 'Видео слайда' ),
	 ) )
	->set_header_template( '
		<% if (title) { %>
			Видос: <%- title %>
		<% } %>
	' ),

Мы получим очень классный результат:

Программируем заголовки групп полей carbon fields

Пример при ипользовании двух значений полей внутри заголовка:

->set_header_template( '
	<% if (name) { %>
		Пассажир: <%- name %> <%- years ? "(" + years + ")" : "" %>
	<% } %>
' )

Видеоурок

Миша

Недавно я осознал, что моя миссия – способствовать распространению WordPress. Ведь WordPress – это лучший движок для разработки сайтов – как для тех, кто готов использовать заложенную структуру этой CMS, так и для тех, кто предпочитает headless решения.

Сам же я впервые познакомился с WordPress в 2009 году. Организатор WordCamp. Преподаватель в школах Epic Skills и LoftSchool.

Если вам нужна помощь с вашим сайтом или может даже разработка с нуля на WordPress / WooCommerce — пишите. Я и моя команда сделаем вам всё на лучшем уровне.