Публикация в группе: Плагин WP-Recall - Личный кабинет на WordPress

Категории группы: Полезное

Всем привет!

Начиная с версии 16.22.0 под капотом плагина WP-Recall загудело новое мощное API произвольных полей.

Произвольные поля WP-Recall - одна из основных частей ядра плагина. Именно на основе этого функционала создаются все формы плагина: административные настройки, формы входа и регистрации, профиль, различные менеджеры в административной части, форма публикации, формы форума и многие другие примеры из многочисленных дополнений плагина. Я уже рассказывал как работать с произвольными полями и как строить различные формы на основе произвольных полей, прошу ознакомиться с материалом, если еще не успели сделать это ранее.

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

Сначала давайте рассмотрим пример инициализации и работы с отдельным произвольным полем.

Сначала формируем массив с данными произвольного поля. Я не буду подробно останавливаться на структуре массива, его содержимое массива и порядок формирования не претерпели изменений, с этим вопросом можно подробно ознакомиться в моих предыдущих статьях ссылки на которые я оставил выше.

$field = array(
	'type' => 'text',
	'slug' => 'field_one',
	'title' => __('Текстовое поле'),
	'placeholder' => __('Заполните это поле'),
	'required' => 1,
	'notice' => __('тут какое то примечание к полю')
)<br>

Далее инициализируем произвольное поле

$fieldObject = Rcl_Field::setup( $field );

В результате мы получим объект с данными произвольного поля в свойствах и полезными методами, которые понадобятся для дальнейшей работы.

Полный перечень всех методов и свойств можно посмотреть в файле

/classes/fields/class-rcl-field-abstract.php

Класс содержит абстрактное поле с общими методами, а уже каждый конкретный тип поля формируется соответствующими классами, которые находятся в папке

/classes/fields/types/

Специальные классы из этой папки передают нюансы определенного типа поля: формируют отдельные свойства, его отображение, настройки, порядок вывода значения и тд.

Итак, для построения формы из полученного объекта поля нам могут понадобиться следующие основные методы:

->get_value() - получает значение поля для вывода, в зависимости от типа может быть обернуто html-разметкой
->get_notice() - получает указанную заметку к полю, результат обернут html-разметкой
->get_title() - наименование поля, обернут html-разметкой
->get_field_value('title' = false) - значение поля, обернут html-разметкой
->get_field_input() - основное html-представление поля, без заголовка
->get_field_html() - полное html-представление поля

Используя эти методы можно быстро сформировать html-представление поля для использования в своем коде или форме.

Я все же предполагаю, что для создания форм вы будете использовать функцию rcl_get_form(), которую я описывал в статье о создании форм, она позволяет быстро и без заморочек создавать формы на основе текущего API произвольных полей.

Давайте рассмотрим пример создания и добавления поля своего типа.

Для начала нам потребуется создать класс-потомок от класса Rcl_Abstract_Field с основными методами:

class Rcl_MY_Field extends Rcl_Field_Abstract {

	//специальные свойства поля

	function __construct( $args ) {
	    parent::__construct( $args );
	}

	//метод, где указывается массив опций поля, 
	//которые будут доступны в административном менеджере полей
	function get_options() {
	
	}

	//возвращаем минимальное html-представление поля
	function get_input() {

	}
	
	//возвращает значение поля (если возвращается только $this->value, 
	//то можно не определять метод, он уже есть в родителе)
	function get_value(){
		
	}

}

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

Давайте допустим, что в нашем проекте нам необходимо использовать некое поле, которое будет состоять из нескольких числовых или текстовых input'ов, число которых может изменяться в зависимости от переданных данных при формировании поля. Соответственно, данные, указанные в этих input'ах должны сохраняться в массив. Мы предполагаем использовать данное поле в нашей форме. Поехали.

Укажем специальные свойства класса и возможные настройки поля в методе get_options(). У нас будет два специальных свойства: одно для указания количества input'ов, второе - для указания типа этих inpit'ов. Массив настроек формируется точно также как и любое произвольное поле плагина, настройки формируем с оглядкой на то, что нужные нам свойства должны изменяться через них:

class Rcl_MY_Field extends Rcl_Field_Abstract {

	//специальные свойства поля
	public $number_fields;
	public $type_fields;

	function __construct( $args ) {
	    parent::__construct( $args );
	}

	function get_options() {

		return array(
			array(
				'slug'		 => 'number_fields',
				'default'	 => $this->number_fields,
				'type'		 => 'number',
				'title'		 => __( 'количество полей' )
			),
			array(
				'slug'		 => 'type_fields',
				'default'	 => $this->type_fields,
				'type'		 => 'radio',
				'title'		 => __( 'тип полей' ),
				'values' => [
					'text' => __('Текстовое поле'), 
					'number' => __('Числовое поле')
				]
			)
		);
	}

	function get_input() {}

	function get_value(){}

}

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

  • title
  • slug (id)
  • value
  • placeholder
  • maxlenght
  • required
  • notice
  • input_id
  • input_name

Теперь формируем минимальное html-представление нашего поля. Мы помним, что это несколько input'ов типа text или number, количество зависит от свойства type_fields:

class Rcl_MY_Field extends Rcl_Field_Abstract {

        /******/

	function get_input() {
	
		$fields = array();
		for($a = 0; $a < $this->number_fields; $a++){
			$fields[] = '<input type="'.$this->type_fields.'" name="' . $this->input_name . '[]" value="' . $this->value[$a] . '">';
		}
	
		return implode(' ', $fields);
	}
	
	/******/

}

Мы прогнали простой цикл с количеством итераций равным type_fields и в каждой сформировали свой input сразу позаботившись о выводе значения, если такое уже будет присутствовать на тот момент.

Осталось описать вывод значения поля:

class Rcl_MY_Field extends Rcl_Field_Abstract {

        /******/

	function get_value(){
		return implode(', ', $this->value);
	}

}

Так как в значении у нас массив значений, значит мы разворачиваем его в строку с запятой в разделителе.

Полный класс нашего поля

class Rcl_MY_Field extends Rcl_Field_Abstract {

	public $number_fields;
	public $type_fields;

	function __construct( $args ) {
	    parent::__construct( $args );
	}

	function get_options() {

		return array(
			array(
				'slug'		 => 'number_fields',
				'default'	 => $this->number_fields,
				'type'		 => 'number',
				'title'		 => __( 'количество полей' )
			),
			array(
				'slug'		 => 'type_fields',
				'default'	 => $this->type_fields,
				'type'		 => 'radio',
				'title'		 => __( 'тип полей' ),
				'values' => [
					'text' => __('Текстовое поле'), 
					'number' => __('Числовое поле')
				]
			)
		);
	}

	function get_input() {
	
		$fields = array();
		for($a = 0; $a < $this->number_fields; $a++){
			$fields[] = '<input type="'.$this->type_fields.'" name="' . $this->input_name . '[]" value="' . $this->value[$a] . '">';
		}
	
		return implode(' ', $fields);
	}

	function get_value(){
		return implode(', ', $this->value);
	}

}

Вроде класс готов, но я присмотрелся к строчке

$fields[] = '<input type="'.$this->type_fields.'" name="' . $this->input_name . '[]" value="' . $this->value[$a] . '">';

и подумал, что использовать в данном случае html для формирования поля input определенного типа некомильфо и решил сделать его на основе ... уже имеющихся типов произвольных полей: text и number. После соответствующей замены получилось совсем хорошо:

class Rcl_MY_Field extends Rcl_Field_Abstract {

	public $number_fields;
	public $type_fields;

	function __construct( $args ) {
	    parent::__construct( $args );
	}

	function get_options() {

		return array(
			array(
				'slug'		 => 'number_fields',
				'default'	 => $this->number_fields,
				'type'		 => 'number',
				'title'		 => __( 'количество полей' )
			),
			array(
				'slug'		 => 'type_fields',
				'default'	 => $this->type_fields,
				'type'		 => 'radio',
				'title'		 => __( 'тип полей' ),
				'values' => [
					'text' => __('Текстовое поле'), 
					'number' => __('Числовое поле')
				]
			)
		);
	}

	function get_input() {
	
		$fields = array();
		for($a = 0; $a < $this->number_fields; $a++){
			$fields[] = Rcl_Field::setup([
				'type' => $this->type_fields,
				'slug' => $this->slug,
				'input_name' => $this->input_name . '[]',
				'value' => $this->value[$a]
			])
			->get_input();
		}
	
		return implode(' ', $fields);
	}

	function get_value(){
		return implode(', ', $this->value);
	}

}

Без html стало куда лучше)

Теперь осталось зарегистрировать наше произвольного поля нового типа, пусть будет тип 'mytype'. Делается это так:

add_filter( 'rcl_fields', 'add_my_new_field_type' );
function add_my_new_field_type( $fields ) {

	$fields['mytype'] = array(
		'label'	 => __( 'Мой тип поля' ),
		'class'	 => 'Rcl_MY_Field'
	);

	return $fields;
}

После этого, мы можем использовать новый тип произвольного поля в нашей форме, например так:

$form = rcl_get_form([
	'submit' => __('Сохранить'),
	'fields' => [
		[
			'type' => 'mytype',
			'slug' => 'myfield',
			'title' => __('Название поля'),
			'number_fields' => 3,
			'type_fields' => 'number',
			'value' => [ //тут укажем дефолтные значения для каждого input
				1,2,3
			]
		]
	]
]);

Не забываем указать 'slug' - он будет определять тег name для input и основные свойства поля, необходимые для его формирования. Также можем указать дефолтные значения в свойстве 'value'.

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

Наш класс будет формировать примерно такое ядро поля:

<div class="rcl-field-core">
	<input type="number" name="myfield[]" value="1">
	<input type="number" name="myfield[]" value="2">
	<input type="number" name="myfield[]" value="3">
</div>

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

Вот такая революционная возможность появилась. Я уверен, что в дальнейшем мы увидим появление новых типов полей, которые будут предлагаться общественности для использования в виде дополнения или отдельных сниппетов, ну а в ядре плагина, уже очень скоро, появится новое поле реализующее продвинутый загрузчик файлов. Все интересное впереди!

А тут для тех, кто дочитал до конца, я делюсь типом поля 'rangedate' - диапазон дат https://pastebin.com/7kmYjyWy, возможно вам это пригодится.

Пока на этом все.

Если вы были внимательны, то обратили внимание, что мы никак не задействовали сформированные опции нашего поля, но мы обязательно рассмотрим этот момент чуть позже, в следующей статье.

Надеюсь Вам было не только интересно, но и понятно)

Всем удачи!

3

Автор публикации

не в сети 23 часа

Андрей CS

12K
занят
Комментарии: 2763Публикации: 492Регистрация: 30-11--0001Продаж/Покупок: 0/0