Продвинутое использование

Meta Box

В этом разделе заглянем немного под капот плагина Meta Box и рассмотрим продвинутые настройки, возможности и другие нестандартные вопросы.

База данных Meta Box

Чтобы лучше понимать, как работать с Meta Box, давайте разберемся, как плагин работает с БД, и куда сохраняются данные.

Данные метаполей сохраняются в родную таблицу WP: wp_postmeta для записей, wp_termmeta для терминов, wp_usermeta для юзеров, wp_commentmeta для комментариев. Т.е. Meta Box использует тот же алгоритм сохранения метаданных, что и функция WordPress add_metadata() и производные от нее:

Раз Meta Box хранит метаполя в логике WordPress, то и получать их значения можно с помощью родных функций WP, например: get_post_meta(). Такой подход к получению данных позволяет не зависеть от плагина во фронт-энде.

Не-повторяемые (не-клонируемые) поля

Для простых полей, которые нельзя клонировать (параметр 'clone' => false), Meta Box сохраняет данные также как сам WordPress:

  • Если поле может имеет только одно значение (параметр 'multiple' => false), оно будет сохранено в одну строку таблицы метаполей (для записей это wp_postmeta).

  • Если поле может иметь несколько значений (параметр 'multiple' => true) - это поля типов: select, checkbox_list, file, image и т.д., тогда каждое значение поля сохраняется в отдельную строку таблицы, где мета ключ будет одинаковый, а значения разные.

Повторяемые (клонируемые) поля

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

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

Заметки

Meta Box полностью совместим с функциями WP

Для сохранения и получения мета-данных родные функции WP полностью подходят. Т.е. можно полностью отказаться от функций вроде rwmb_meta().

Особые значения

Для обычных полей, данные сохраняются в БД в том виде в котором пользователь их вписал или выбрал (для селект полей). Но есть особенные поля, значение которых не обычные и сохраняются нестандартно. Подробнее смотрите в описании каждого поля.

Лучшие практики получения полей

Несмотря на то, что для получения значений можно использовать функции WP (get_post_meta()), все же рекомендуется использовать вспомогательные функции плагина (rwmb_meta()). Они учитывают всю логику сохранения описанную выше и возвращают данные в удобном формате.

Чтобы увидеть в каком виде данных находятся в БД, используйте функцию print_r(), пример:

// не multiple поле
$value = get_post_meta( $post_id, 'meta_name', true ); 

// multiple поле
$value = get_post_meta( $post_id, 'meta_name', false );

print_r( $value );

События (actions)

Список событий, которые могут пригодится.

rwmb_before

Выполняется перед показом любого метабокса. Принимает 1 параметр: экземпляр класса RW_Meta_Box для текущего метабокса.

do_action( 'rwmb_before', $this );
rwmb_before_{$meta_box_id}
Тоже что и rwmb_before, но применено для определенного meta box (определенный ID). Принимает те же параметры.
rwmb_after

Выполняется после отображения любого метабокса. Принимает 1 параметр: экземпляр класса RW_Meta_Box для текущего meta box.

do_action( 'rwmb_after', $this );
rwmb_after_{$meta_box_id}
Тоже что и rwmb_after, но применено к определенному метабоксу (определенному ID). Принимает те же параметры.
rwmb_before_save_post

Это действие выполняется перед сохранением любого метабокса в метаполя. Принимает 1 параметр: ID текущей записи.

do_action( 'rwmb_before_save_post', $post_id );
rwmb_{$meta_box_id}_before_save_post
Тоже что и rwmb_before_save_post, но применяется к определенному мета-боксу (определяемому ID). Принимает те же параметры.
rwmb_after_save_post

Выполняется после сохранения любого метабокса в метаполя. Принимает 1 параметр: ID текущей записи.

do_action( 'rwmb_after_save_post', $post_id );
rwmb_{$meta_box_id}_after_save_post
Тоже что и rwmb_after_save_post, но применяется к определенному мета-боксу (определяемому ID). Принимает те же параметры.
rwmb_after_save_field

Запускается после сохранения каждого поля.

do_action( 'rwmb_after_save_field', null, $field, $new, $old, $post_id );

Принимает параметры:

  • $null - Не используется
  • $field - Опции поля
  • $new - Новое значение поля
  • $old - Старое значение поля
  • $post_id - ID поста

Этот хук можно использовать для выполнения дополнительных действий для определенного поля. Например:

add_action( 'rwmb_after_save_field', function ( $null, $field, $new, $old, $post_id ) {
	$pre = '';
	if ( ! empty( $field['attributes']['mod_lock'] ) ) {
		$pre = 'pending_';
	}
	$storage = $field['storage'];

	if ( $new !== $old ) {
		$storage->update( $post_id, $pre . $field['id'], $new );
	}

	if ( empty( $new ) ) {
		$storage->delete( $post_id, $pre . $field['id'] );
	}
}, 10, 5 );
rwmb_{$field_type}_after_save_field
Аналогично rwmb_after_save_field, но применяется только к полю указанного типа.
rwmb_{$field_id}_after_save_field
Аналогично rwmb_after_save_field, но применяется только к определенному по ID полю.
rwmb_enqueue_scripts

Выполняется после добавления в очередь всех скриптов/стилей метабокса. Позволяет разработчикам подключать свои скрипты и стили. Принимает 1 параметр: экземпляр класса RW_Meta_Box для текущего метабокса.

do_action( 'rwmb_enqueue_scripts', $this );

Фильтры (filters)

Смотрите в офф документации.

Интеграция в тему или плагин

Meta Box можно встроить в тему или плагин, т.е. использовать его не как плагин WP. Сделать это можно двумя способами.

Способ 1: Через класс TGM Plugin Activation

TGM Plugin Activation позволяет разработчикам установить зависимость темы или плагина от другого плагина, например Meta Box.

Короткая инструкция по активации и использованию класса:

  1. Скачайте класс TGM_Plugin_Activation - заполните поля и нажмите кнопку «Generate». Убедитесь, что выбрана опция «Plugin» в разделе «I’m going to use TGMPA in a:».

  2. Распакуйте скаченный архив и скопируйте из него файлы class-tgm-plugin-activation.php и example.php в папку вашей темы или плагина. Переименуйте файл example.php, придумайте понятное название.

  3. Откройте переименованный файл example.php и добавьте Meta Box в список плагинов. В итоге получится примерно так:

    require_once dirname( __FILE__ ) . '/class-tgm-plugin-activation.php';
    
    add_action( 'tgmpa_register', 'prefix_register_required_plugins' );
    function prefix_register_required_plugins() {
    
    	$plugins = array(
    		array(
    			'name'     => 'Meta Box',
    			'slug'     => 'meta-box',
    			'required' => true,
    		),
    		// More plugins
    	);
    
    	$config  = array(
    		'id' => 'ваш-id',
    	)
    
    	tgmpa( $plugins, $config );
    }
  4. Подключите переименованный файл example.php в файл темы functions.php или в главный файл плагина.

    require_once __DIR__ . '/example.php';

Теперь, после установки вашего плагина или темы, пользователь увидит уведомление, что нужно также установить плагин Meta Box из каталога WordPress.

Способ 2: Встраивание Meta Box

Чтобы жестко внедрить Meta Box в ваш проект, следуйте инструкции:

  • Скопируйте папку плагина meta-box в тему или плагин.

  • Подключите главный файл Meta Box в код вашего проекта. Например, для темы нужно будет вставить следующую строку в файл functions.php:

    require get_template_directory() . '/meta-box/meta-box.php';
  • Готово! MetaBox подключен.

Недостатки этого способа:

  • Автоматическое обновление плагина будет невозможно, придется все делать вручную.

  • Если MetaBox уже установлен, ваш плагин или тема не смогут быть активированы - активация вызовет фатальную ошибку PHP.

ВАЖНО: Этот метод не рекомендуется и считается плохой практикой. Используйте его только если хорошо осознаете все последствия. Автор плагина рекомендует первый способ!

Создаем свой тип поля

Meta Box настолько гибок, что позволяет легко создавать свои собственные типы полей. В этом примере рассмотрим, как создать поле нового типа - phone, которое может принимать телефон только в формате xxx-xxxx.

PHP класс нового поля

Нужно создать класс RWMB_Phone_Field для нашего поля phone. В целом, чтобы создать класс для поля, нужно создать класс с названием RWMB_{$field_type}_Field и расширить его с помощью класса RWMB_Field.

if( class_exists( 'RWMB_Field' ) ){
	class RWMB_Phone_Field extends RWMB_Field {
		// класс phone поля
	}
}

Теперь, нужно сохранить класс в php файл с любым названием, например field-phone.php и подключить его в файл темы functions.php или в файл плагина:

add_action( 'init', 'prefix_load_phone_type' );
function prefix_load_phone_type() {
	require 'path/to/field-phone.php';
}

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

Методы класса

Наш новый класс получил все методы класса RWMB_Field. Полный список методов смотрите в описании класса RWMB_Field.

Теперь нам нужно создать HTML код нашего поля, делается это переопределением метода html():

public static function html( $meta, $field ) {
	return sprintf(
		'<input type="tel" name="%s" id="%s" value="%s" pattern="d{3}-d{4}">',
		$field['field_name'],
		$field['id'],
		$meta
	);
}

Тут мы использовали HTML5 input type tel, с атрибутом pattern, чтобы указать формат телефона вида - xxx-xxxx.

Для этого поля. нет необходимости обрабатывать сохранение значения, или получения значения или подключения скрипта или стилей. Все работает автоматически из кода Meta Box.

Готовый код поля будет выглядеть так:

if( class_exists( 'RWMB_Field' ) ){

	class RWMB_Phone_Field extends RWMB_Field {

		public static function html( $meta, $field ) {
			return sprintf(
				'<input type="tel" name="%s" id="%s" value="%s" pattern="d{3}-d{4}">',
				$field['field_name'],
				$field['id'],
				$meta
			);
		}

	}

}

Использование созданного типа поля

Теперь, при регистрации полей, в параметре type нужно указать наше созданное поле phone:

$meta_boxes[] = array(

	'title' => 'Test',
	'fields' => array(
		array(
			'name' => 'Phone',
			'id'   => 'field_id',
			'type' => 'phone',
		),
		// Other fields
	),
);

Теперь если зайти в редактирование записи мы увидим такой метабокс:

Это все. Когда нужны более сложные типы полей, нужно будет брать код методов из основного класса RWMB_Field{} и переделывать его под свои нужды. Так, например, вам может понадобиться подключить стили или скрипты, очищать значение полей перед сохранением в БД и т.д. RWMB_Field{} имеет все необходимые для этого методы.

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

Установка Meta Box через Composer

Что такое Composer

Composer - это менеджер зависимостей модулей для PHP. Composer позволяет умно устанавливать популярные PHP пакеты (в данном случае плагин Meta Box) и подключать их все одной строкой кода. При этом исключаются возможные конфликты.

Если проект нуждается в двух библиотеках A и Б и обе из них нуждаются в модуле В, то В будет подключен дважды. Это еще усугубиться, когда А и Б подключат В, но с разными версиями. Это вызовет конфликт в PHP и код работать не будет. Composer помогает избежать таких проблем.

Компосер работает по такому принципу: создается конфигурационный файл, где прописываются все нужные для проекта пакеты (плагины, библиотеки). Далее запускается компосер, он скачивает и устанавливает все указанные пакеты и пакеты которые нужны для работы указанных пакетов (зависимые пакеты). Все это устанавливается в одну папку и затем подключается в проект одной строкой кода.

В репозитории Компосера (packagist.org) насчитывается более 100 000 различных пакетов. Поэтому через Компосер можно установить практически любой популярный PHP модуль, в том числе Meta Box.

Установка Composer

Установка Composer подробно описана на официальном сайте. На некоторых хостингах он уже установлен или очень просто ставится, например для Beget есть такая инструкция по установке.

Работа по установке Компосера и его пакетов, проходит в командной строке, в терминале вашего сервера, через SSH соединение.

Настройка конфиг файла

Компосеру нужен всего один конфигурационный файл composer.json, в котором нужно указать библиотеки необходимые для проекта. Содержимое файла должно быть в JSON формате и выглядит так:

{
	"require": {
		"rilwis/meta-box": "4.*"
	}
}

В объекте require, мы говорим Компосеру, какие пакеты нужно установить. Формат указываемого пакеты выглядит так: author/package-name. Значение - это версия пакета. * - значит последняя версия ветки, но можно указать конкретную версию, например, 4.8.7. Подробнее про синтаксис composer.json читайте в офф. документации.

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

Установка пакетов

У нас уже все готово: есть Компосер и конфиг файл для него, остается только запустить Компосер. Для этого, нужно командой cd перейти в папку с файлом composer.json и из нее запустить команду Компосера install (установка):

composer install

Эта команда скажет Компосеру прочитать конфиг файл, скачать и установить указанные в нем пакеты и пакеты от которых они зависят. После установки рядом с файлом composer.json появится новая папка vendor. Т.е. мы увидим такую структуру:

Теперь, все необходимые файлы находятся в папке vendor, нам остается подключить все в наш плагин.

Подключение пакетов

Чтобы подключить все библиотеки установленные Компосером, нужно вставить одну строку в php файл нашего проекта. Она умно подключит все пакеты в php код нашего проекта. В данном примере у нас установлен один пакет - Meta Box.

require __DIR__ . '/vendor/autoload.php';

Все! Meta Box доступен в коде нашего плагина или темы. Можно начинать его использовать.