Добавление полей «подъезд», «этаж», «квартира» на страницу оформления заказа

На многих сайтах ресторанов с доставкой я встречал отдельные поля для ввода «дома», «этажа» и так далее.

Вот к примеру сайт грузинского ресторана:

отдельные поля адреса для квартиры, дома и этажа
Отдельные поля для «квартира», «подъезд» и «этаж».

В WooCommerce у нас по умолчанию есть только два поля – «Адрес 1» и «Адрес 2». Ну типа того:

Стандартные поля адреса в WooCommerce

Дело в том, что когда и «крыло», и «подъезд», и «этаж», и «т.д.» заполняются в одном поле, это может быть не супер-удобно обрабатывать менеджерам вашего магазина. Поэтому давайте разберёмся, как их разделить и чтобы всё классно работало.

Обратите внимание, что я бы не хотел усложнять и фактически добавлять три (или два) поля на страницу оформления заказа, потом добавлять значения этих полей в метабокс заказа в админке и в емейлы. Ведь для администратора нам по сути не важно, будет ли информация записана в разные поля или в одно – главное, чтобы она была удобочитаема, в этом и есть цель. Поэтому ниже я решил поделиться вариантом, который прекрасно работает на парочке проектов, хотя он и не кажется мне супер-красивым. Также хочу порекомендовать видеоурок по полной кастомизации страницы «Оформление заказа» в WooCommerce.

1. Добавление полей

Фактически мы не будем добавлять новые поля тут, а при помощи хука превратим поле «Адрес 2» (billing_address_2) в целых три!

Для этого нам может пригодится хук WooCommerce, который называется woocommerce_form_field_{ТИП ПОЛЯ}, а так как billing_address_2 – это текстовое поле, то и хук будет woocommerce_form_field_text. То есть по сути мы перезапишем HTML поля billing_address_2.

HTML поля адрес 2 по умолчанию выглядит так:

<p class="form-row address-field form-row-wide" id="billing_address_2_field" data-priority="60">
	<label for="billing_address_2" class="screen-reader-text">Крыло, подъезд, этаж и т.д. <span class="optional">(необязательно)</span></label>
	<span class="woocommerce-input-wrapper">
		<input type="text" class="input-text " name="billing_address_2" id="billing_address_2" placeholder="Крыло, подъезд, этаж и т.д. (необязательно)" value="" autocomplete="address-line2" data-placeholder="Крыло, подъезд, этаж и т.д. (необязательно)">
	</span>
</p>

Я предлагаю в этом HTML сильно ничего не менять, только это:

<span class="woocommerce-input-wrapper true-wrapper">
	<input type="number" name="billing_address_2" id="billing_address_2" placeholder="Парадная" value="">
	<input type="number" name="billing_address_3" id="billing_address_3" placeholder="Этаж" value="">
	<input type="number" name="billing_address_4" id="billing_address_4" placeholder="Квартира" value="">
</span>

Тогда наш код с хуком будет вот таким:

add_filter( 'woocommerce_form_field_text', 'true_fields', 25, 4 );
 
function true_fields( $field, $key, $args, $value ) {
 
	if( 'billing_address_2' === $key ) {
 
		$field = '<p class="form-row address-field form-row-wide" data-priority="60">
			<span class="woocommerce-input-wrapper true-wrapper">
				<input type="number" name="billing_address_2" id="billing_address_2" placeholder="Парадная" value="">
				<input type="number" name="billing_address_3" id="billing_address_3" placeholder="Этаж" value="">
				<input type="number" name="billing_address_4" id="billing_address_4" placeholder="Квартира" value="">
			</span>
		</p>';
 
	}
 
	return $field;
 
}

Не знаете, куда вставлять код кстати?

И да, немножно CSS на класс .true-wrapper.

.true-wrapper{
	display: flex;
	justify-content: space-between;
}
.true-wrapper input{
	max-width: 30%;
	flex-basis: 30%;
}

В итоге получаем вполне годный вариант:

Добавление полей адреса WooCommerce
В этом примере мы превратили единственное поле «Адрес 2» в три раздельных поля – Парадная, Этаж, Квартира. Это всё было проделано на стандартной теме WooCommerce – StoreFront.

2. Записываем пользовательский ввод трёх полей в одно поле

Как я вам уже сказал в начале урока, наша цель – провернуть всё это с минимальными усилиями. Поэтому сейчас мы воспользуемся хуком woocommerce_checkout_posted_data, чтобы перед сохранением полей в базу данных перезаписать их так, как нам нужно.

add_filter( 'woocommerce_checkout_posted_data', 'true_process_fields' );
 
function true_process_fields( $data ) {
 
	// в поле billing_address_2 мы и будем записывать новые значения полей
	$data[ 'billing_address_2' ] = '';
	$fields = array();
 
	// получаем данные из глобального $_POST, сначала парадную (подъезд)
	if( ! empty( $_POST[ 'billing_address_2' ] ) ) {
		$fields[] = 'подъезд ' . absint( $_POST[ 'billing_address_2' ] );
	}
	// затем этаж
	if( ! empty( $_POST[ 'billing_address_3' ] ) ) {
		$fields[] = 'этаж ' . absint( $_POST[ 'billing_address_3' ] );
	}
	// затем квартиру
	if( ! empty( $_POST[ 'billing_address_4' ] ) ) {
		$fields[] = 'квартира ' . absint( $_POST[ 'billing_address_4' ] );
	}
 
	// объединяем все заполненные данные запятой
	$data[ 'billing_address_2' ] = join( ', ', $fields );
 
	// возвращаем результат
	return $data;
 
}

В этом коде я использовал функцию absint() для очистки пользовательского ввода. Подробнее о том, зачем нужна очистка – в этом уроке.

Миша

Впервые познакомился с WordPress в 2009 году. Организатор и спикер на конференциях WordCamp. Преподаватель в школе Нетология.

Пишите, если нужна помощь с сайтом или разработка с нуля.

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

Миша Рудрастых и WordPress

Полезности из мира WordPress и жизни студии.

Мой телеграм-канал