Статьи

Як створити блок довільних полів (метабокс) в адмінці WordPress

  1. Вступна частина
  2. Перш ніж почати створення
  3. Створюємо мета блок довільних полів
  4. # 1. Створимо новий мета блок для постів
  5. # 2. Заповнимо цей блок полями html форми
  6. # 3. зберігаємо дані
  7. Блок довільних полів для довільного типу записів
  8. Складнощі з типом checkbox
  9. Ще один приклад створення МЕТАБОКС (ООП)
  10. Модулі для створення блоків довільних полів
  11. висновок

Вступна частина

Перш ніж почати розповідати про те як створити довільний блок даних в адмін-панелі на сторінці редагування постів, який буде управляти зазначеними довільними полями, слід зазначити, що WordPress - платформа яка, мабуть, як ніяка інша піддається розширенню з найменшими зусиллями. Зокрема, саме тому під WordPress написано так багато плагінів - все дуже просто, потрібно лише знати ази PHP і розуміти принцип роботи системи.

Кожен, хто досить близько знайомий з WordPress неодноразово зустрічався з поняттям «довільні поля» і з їх допомогою вирішував деякі нетривіальні завдання.

Довільні поля в WordPress - дуже зручний інструмент, коли потрібно «прикріпити» до конкретного посту будь-які додаткові дані. Такими даними може бути що завгодно, починаючи від логічних true / false (1/0), закінчуючи об'ємними текстами, масивами і іншим. Наприклад, ми можемо створити нове довільне поле Title і в його значення написати текст (альтернативний заголовок поста), потім в коді шаблону використовувати наступний код, щоб вивести цей текст:

<Title> <? Php echo get_post_meta ($ post-> ID, 'title', true); ?> </ Title>

Слід зазначити, що функцію get_post_meta () можна використовувати за межами Циклу WordPress, тобто де завгодно в шаблоні. В даному прикладі ми використовуємо її в <head> частини документа, щоб дати html сторінці заголовок відмінний від заголовка самої статті (іноді корисно для SEO).

Інший приклад: використовуючи довільні поля ми можемо виконувати або не виконувати дії, в залежності від того, які дані у нас знаходиться в значенні довільного поля. Наприклад, розміщуючи в довільне поле логічні цифри 1 або 0 ми можемо виводити чи не виводити будь-яку інформацію для поточного поста.

Довільні поля використовуються в WordPress часто-густо, різними плагінами оцінки постів (WP-PostRatings), SEO плагінами (Platinum SEO Pack), що дозволяють вказати Title, Description, Keywords поста, моїм плагіном для створення мініатюр (Kama Thumbnail) і багатьма іншими плагінами. Образно кажучи, кожна четверта нестандартна завдання вирішується за допомогою довільних полів, тому якщо ви ще не знаєте як їх використовувати, то ознайомтеся з цим мануалом . А нижче ми поговоримо про те, як створити окремий блок з потрібними нам довільними полями і як зробити це без плагінів.

Мало хто знає, що якщо створити довільне поле ключ якого (назва) починається на _ (нижнє підкреслення), наприклад _my_special_key, то таке полі не буде виводитися в випадаючому списку довільних полів при редагуванні постів і буде вважатися "внутрішнім" довільним полем, яке використовується системою. Створити таке поле можна тільки запитом до БД, наприклад, використовуючи функції add_post_meta () або update_post_meta () .

меню

Перш ніж почати створення

Забігаючи вперед, скажу що нижченаведені опис буде корисно, тільки тим хто хоч трохи розбирається в HTML, тобто якщо ви зовсім не в зуб ногою в HTML і PHP, то читати все що нижче - марна трата часу.

Припустимо, що ми робимо сайт на замовлення, і при цьому на сайті використовуються довільні поля. Пояснювати замовнику, яке поле вибирати зі списку, щоб додати ту чи іншу інформацію до посту, проблематично, до того ж це швидко забувається. Саме тому вже давно написані плагіни, завдяки яким можна легко створити блок довільних полів, де не потрібно вибирати поле (ключ), і тільки потім вписувати значення. У таких блоках потрібно відразу вписувати значення і є можливість описати кожне поле, при одному погляді на які стає зрозуміло його призначення. Блок, який ми зараз створимо буде виглядати так:

А дані такого блоку в самих довільних полях, після збереження поста, будуть записані так:

Що ми бачимо? - Непотрібні для сторонніх очей ключі довільних полів (про них я говорив вище), які до того ж потрібно ще й вибирати зі списку (а їх там може бути зовсім не 4, а куди більше ...): description, robotmeta, select і title. Зрозуміло, створити мета блок довільних полів - відмінна ідея.

меню

Створюємо мета блок довільних полів

Для створення метаблока нам знадобляться всього 2 хука: add_meta_boxes і save_post , функція add_meta_box () і деякі знання html і php. Додаємо наступний код в файл теми functions.php:

# 1. Створимо новий мета блок для постів

Назвемо його "Додаткові поля":

// підключаємо функцію активації мета блоку (my_extra_fields) add_action ( 'add_meta_boxes', 'my_extra_fields', 1); function my_extra_fields () {add_meta_box ( 'extra_fields', 'Додаткові поля', 'extra_fields_box_func', 'post', 'normal', 'high'); }

# 2. Заповнимо цей блок полями html форми

Робиться це через, зазначену в add_meta_box () функцію extra_fields_box_func (). Саме вона відповідає за зміст мета блоку:

<? Php // код блоку function extra_fields_box_func ($ post) {?&gt; <P> <label> <input type = "text" name = "extra [title]" value = "<? Php echo get_post_meta ($ post-> ID, 'title', 1);?&gt; "style =" width: 50% "/>? заголовок сторінки (title) </ label> </ p> <p> Опис статті (description): <textarea type = "text" name = "extra [description]" style = "width: 100%; height: 50px;" > <? php echo get_post_meta ($ post-> ID, 'description', 1); ?&gt; </ Textarea> </ p> <p> Видимість поста: <? Php $ mark_v = get_post_meta ($ post-> ID, 'robotmeta', 1); ?&gt; <Label> <input type = "radio" name = "extra [robotmeta]" value = "" <? Php checked ($ mark_v, ''); ?> /> Index, follow </ label> <label> <input type = "radio" name = "extra [robotmeta]" value = "nofollow" <? Php checked ($ mark_v, 'nofollow'); ?> /> Nofollow </ label> <label> <input type = "radio" name = "extra [robotmeta]" value = "noindex" <? Php checked ($ mark_v, 'noindex'); ?> /> Noindex </ label> <label> <input type = "radio" name = "extra [robotmeta]" value = "noindex, nofollow" <? Php checked ($ mark_v, 'noindex, nofollow'); ?> /> Noindex, nofollow </ label> </ p> <p> <select name = "extra [select]"> <? Php $ sel_v = get_post_meta ($ post-> ID, 'select', 1); ?> <Option value = "0"> ---- </ option> <option value = "1" <? Php selected ($ sel_v, '1')?>> Обери мене </ option> <option value = "2" <? php selected ($ sel_v, '2')?>> Ні, мене </ option> <option value = "3" <? php selected ($ sel_v, '3')?>> Краще мене < / option> </ select>? вибір за вами </ p> <input type = "hidden" name = "extra_fields_nonce" value = "<? php echo wp_create_nonce (__ FILE__);?>" /> <? php}

Всі назви полів я оформив в масив extra [], щоб потім простіше було обробити ці дані.

Заховані поле name = "extra_fields_nonce", потрібно для перевірки при збереженні даних.

меню

# 3. зберігаємо дані

На цьому етапі, ми вже створили блок довільних полів, тепер потрібно обробити дані полів при збереженні посади. Обробити, значить записати їх в в базу даних або видалити звідти. Для цього використовуємо хук save_post , Який спрацьовує в момент збереження поста. У цей момент ми отримаємо дані з масиву extra [] і опрацюємо них:

// включаємо оновлення полів при збереженні add_action ( 'save_post', 'my_extra_fields_update', 0); ## Зберігаємо дані, при збереженні посади function my_extra_fields_update ($ post_id) {// базова перевірка if (empty ($ _POST [ 'extra']) ||! Wp_verify_nonce ($ _POST [ 'extra_fields_nonce'], __FILE__) || wp_is_post_autosave ( $ post_id) || wp_is_post_revision ($ post_id)) return false; // Все ОК! Тепер, потрібно зберегти / видалити дані $ _POST [ 'extra'] = array_map ( 'sanitize_text_field', $ _POST [ 'extra']); // чистимо всі дані від прогалин по краях foreach ($ _POST [ 'extra'] as $ key => $ value) {if (empty ($ value)) {delete_post_meta ($ post_id, $ key); // видаляємо поле якщо значення порожнє continue; } Update_post_meta ($ post_id, $ key, $ value); // add_post_meta () працює автоматично} return $ post_id; }

Ось і все, блок довільних полів готовий!

Тепер, змінюючи html код, ми можемо редагувати вміст мета блоку. Але не забуваємо, що назви полів мають вигляд масиву зі значенням ключа довільно поля: name = "extra [meta_key]".

меню

Блок довільних полів для довільного типу записів

Якщо потрібно створити блок для іншого типу записів, припустимо page (для сторінок), то реєструємо ще один мета блок і описуємо його html код в новій функції, яку так само потрібно вказати при реєстрації блоку (extra_fields_box_page_func). Функцію обробки полів при збереженні поста створювати вже не треба, головне вказати назви полів у вигляді масивів extra []:

function my_extra_fields () {add_meta_box ( 'extra_fields', 'Додаткові поля', 'extra_fields_box_func', 'post', 'normal', 'high'); add_meta_box ( 'extra_fields', 'Додаткові поля', 'extra_fields_box_page_func', 'page', 'normal', 'high'); } ## html код блоку для типу записів page function extra_fields_box_page_func () {?> <! - Тут поля html форми -> <? Php} меню

Складнощі з типом checkbox

Недоліком такого методу є те, що масив extra [], обов'язково повинен бути визначений, нехай навіть він передає пусте значення інакше полі не буде оброблено при збереженні даних. У зв'язку з цим, виникає проблема при використанні типу checkbox: <input type = "checkbox", тому що checkbox передає дані тільки, якщо галочка виставлена ​​і взагалі нічого не передає, якщо галки немає. А нам потрібно щоб він передавав пусте значення, щоб код видаляв значення, якщо воно було збережено до цього.

Щоб обійти цей "недугу" я зробив так: перед полем чекбокса створюємо hidden поле з name як у чекбокса і порожнім значенням. І виходить, якщо галочка стоїть, то значення hidden поля перебивається, якщо галки немає, то береться пусте значення hidden поля.

Тобто checkbox потрібно викликати так:

<Input type = "hidden" name = "extra [my_checkbox]" value = "" /> <input type = "checkbox" name = "extra [my_checkbox]" value = "1" />

Такий же трюк іноді може стане в нагоді і для поля з типом radio.

Приклад реального коду з типами checkbox:

<? Php // підключаємо функцію активації мета блоку (my_extra_fields) add_action ( 'admin_init', 'my_extra_fields', 1); function my_extra_fields () {add_meta_box ( 'extra_fields', 'Додаткові поля', 'extra_fields_box_func', 'post', 'normal', 'high'); } // код блоку function extra_fields_box_func ($ post) {?&gt; <P> <label> <input type = "text" name = "extra [title]" value = "<? Php echo get_post_meta ($ post-> ID, 'title', 1);?&gt; "style =" width: 50% "/>? заголовок сторінки (title) </ label> </ p> <p> Опис статті (description): <textarea type = "text" name = "extra [description]" style = "width: 100%; height: 50px;" > <? php echo get_post_meta ($ post-> ID, 'description', 1); ?&gt; </ Textarea> </ p> <p> Видимість поста: <? Php $ mark_v = get_post_meta ($ post-> ID, 'robotmeta', 1); ?&gt; <Label> <input type = "radio" name = "extra [robotmeta]" value = "" <? Php checked ($ mark_v, ''); ?> /> Index, follow </ label> <label> <input type = "radio" name = "extra [robotmeta]" value = "nofollow" <? Php checked ($ mark_v, 'nofollow'); ?> /> Nofollow </ label> <label> <input type = "radio" name = "extra [robotmeta]" value = "noindex" <? Php checked ($ mark_v, 'noindex'); ?> /> Noindex </ label> <label> <input type = "radio" name = "extra [robotmeta]" value = "noindex, nofollow" <? Php checked ($ mark_v, 'noindex, nofollow'); ?> /> Noindex, nofollow </ label> </ p> <p> <select name = "extra [select]" /> <? Php $ sel_v = get_post_meta ($ post-> ID, 'select', 1) ; ?> <Option value = "0"> ---- </ option> <option value = "1" <? Php selected ($ sel_v, '1')?>> Обери мене </ option> <option value = "2" <? php selected ($ sel_v, '2')?>> Ні, мене </ option> <option value = "3" <? php selected ($ sel_v, '3')?>> Краще мене < / option> </ select>? вибір за вами </ p> <p> <input type = "hidden" name = "extra [white]" value = ""> <label> <input type = "checkbox" name = "extra [white]" value = "1" <? php checked (get_post_meta ($ post-> ID, 'white', 1), 1)?> /> білий </ label> <input type = "hidden" name = "extra [red]" value = ""> <label> <input type = "checkbox" name = "extra [red]" value = "1" <? php checked (get_post_meta ($ post-> ID, 'red', 1), 1)? > /> червоний </ label> <input type = "hidden" name = "extra [black]" value = ""> <label> <input type = "checkbox" name = "extra [black]" value = "1 "<? php checked (get_post_meta ($ post-> ID, 'black', 1), 1)?> /> чорний </ label> </ p> <input type =" hidden "name =" extra_fields_nonce "value = "<? php echo wp_create_nonce (__ FILE__);?>" /> <? php} // включаємо оновлення полів при збереженні add_action ( 'save_post', 'my_extra_fields_update', 0); / * Зберігаємо дані, при збереженні поста * / function my_extra_fields_update ($ post_id) {// базова перевірка if (empty ($ _POST [ 'extra']) ||! Wp_verify_nonce ($ _POST [ 'extra_fields_nonce'], __FILE__) || wp_is_post_autosave ($ post_id) || wp_is_post_revision ($ post_id)) return false; // Все ОК! Тепер, потрібно зберегти / видалити дані $ _POST [ 'extra'] = array_map ( 'sanitize_text_field', $ _POST [ 'extra']); foreach ($ _POST [ 'extra'] as $ key => $ value) {if (empty ($ value)) {delete_post_meta ($ post_id, $ key); // видаляємо поле якщо значення порожнє continue; } Update_post_meta ($ post_id, $ key, $ value); // add_post_meta () працює автоматично} return $ post_id; } меню

Ще один приклад створення МЕТАБОКС (ООП)

Цей приклад показує як створити одне поле, в якому буде зберігатися масив даних. Масив можна розширювати або зменшувати через натискання на + або видалити (працює на скрипті).

Це приклад створення поля "повторювач", як у плагіна ACF (поле repeater в платній версії).

В результаті отримаємо такий метабокс:

<? Php new My_Best_Metaboxes; class My_Best_Metaboxes {public $ post_type = 'post'; static $ meta_key = 'company_address'; public function __construct () {add_action ( 'add_meta_boxes', array ($ this, 'add_metabox')); add_action ( 'save_post_'. $ this-> post_type, array ($ this, 'save_metabox')); add_action ( 'admin_print_footer_scripts', array ($ this, 'show_assets'), 10, 999); } ## Додає матабокси public function add_metabox () {add_meta_box ( 'box_info_company', 'Інформація про компанію', array ($ this, 'render_metabox'), $ this-> post_type, 'advanced', 'high'); } ## Показує метабокс на сторінці редагування поста public function render_metabox ($ post) {?> <Table class = "form-table company-info"> <tr> <th> Адреси компанії <span class = "dashicons dashicons-plus- alt add-company-address "> </ span> </ th> <td class =" company-address-list "> <? php $ input = '<span class =" item-address "> <input type =" text "name =" '. self :: $ meta_key.' [] "value ="% s "> <span class =" dashicons dashicons-trash remove-company-address "> </ span> </ span> '; $ Addresses = get_post_meta ($ post-> ID, self :: $ meta_key, true); if (is_array ($ addresses)) {foreach ($ addresses as $ addr) {printf ($ input, esc_attr ($ addr)); }} Else {printf ($ input, ''); }?> </ Td> </ tr> </ table> <? Php} ## Очищає і зберігає значення полів public function save_metabox ($ post_id) {// Check if it's not an autosave. if (wp_is_post_autosave ($ post_id)) return; if (isset ($ _POST [self :: $ meta_key]) && is_array ($ _POST [self :: $ meta_key])) {$ addresses = $ _POST [self :: $ meta_key]; $ Addresses = array_map ( 'sanitize_text_field', $ addresses); // очищення $ addresses = array_filter ($ addresses); // приберемо порожні адреси if ($ addresses) update_post_meta ($ post_id, self :: $ meta_key, $ addresses); else delete_post_meta ($ post_id, self :: $ meta_key); }} ## Включає скрипти і стилі public function show_assets () {if (is_admin () && get_current_screen () -> id == $ this-> post_type) {$ this-> show_styles (); $ This-> show_scripts (); }} ## Виводить на екран стилі public function show_styles () {?> <Style> .add-company-address {color: # 00a0d2; cursor: pointer; } .Company-address-list .item-address {display: flex; align-items: center; } .Company-address-list .item-address input {width: 100%; max-width: 400px; } .Remove-company-address {color: brown; cursor: pointer; } </ Style> <? Php} ## Виводить на екран JS public function show_scripts () {?> <Script> jQuery (document) .ready (function ($) {var $ companyInfo = $ ( '. Company-info' ); // Додає бокс з введенням адреси фірми $ ( '. add-company-address', $ companyInfo) .click (function () {var $ list = $ ( '. company-address-list'); $ item = $ list.find ( '. item-address'). first (). clone (); $ item.find ( 'input'). val ( ''); // чистимо знанченіе $ list.append ($ item); }); // Видаляє бокс з введенням адреси фірми $ companyInfo.on ( 'click', '.remove-company-address', function () {if ($ ( '. item-address'). length> 1) { $ (this) .closest ( '. item-address'). remove ();} else {$ (this) .closest ( '. item-address'). find ( 'input'). val ( ''); }});}); </ Script> <? Php}} меню

Модулі для створення блоків довільних полів

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

  • Advanced Custom Fields (ACF) - мабуть, найпопулярніший і гнучкий плагін для створення довільних полів. З хорошою документацією.

  • Custom Field Suite - схожий на ACF, тільки менш наворочений.

  • Carbon Fields - схожий на ACF тільки без візуальної настройки, все робиться в коді. Добре підійде для розробників. Безкоштовний.

  • CMB2 - CMB2 інструмент для розробників для створення: метабоксов, метапол. Дозволяє легко керувати записами, елементами таксономії, користувачами, коментарями чи створювати довільні сторінки налаштувань.

  • Custom Field Template - справжній комбайн. З ним можна створити будь-яку форму, для будь-яких типів постів, вказати форми для окремих посад і рубрик. Думаю в більшості випадків, можна обійтися без такого комбайна.

  • kc-settings - ураган а не плагін, хоч і не є прихильником плагінів, але рекомендую.
меню

висновок

Простота в налаштуванні блоку довільних полів при створенні його таким способом втрачається! Я ні в якому разі не хочу сказати, що створювати блоки таким способом краще ніж використовувати плагіни. Однак, такий підхід більш гнучкий, тому що ми можемо створити абсолютно будь-які поля і розташувати / стилізувати їх як нам заманеться.

До того ж, зазвичай немає потреби створювати по кілька таких блоків і часто їх редагувати, як це можна робити використовуючи плагіни. Наприклад, на цьому блозі я використовую такий підхід і зовсім невеликий код в functions.php позбавляє мене від необхідності використовувати черговий плагін.

Це скоріше навчальна стаття і для багатьох плагіни реалізують цю задачу будуть найкращим рішенням.

Php echo get_post_meta ($ post-> ID, 'title', true); ?
Php // код блоку function extra_fields_box_func ($ post) {?
Gt; <P> <label> <input type = "text" name = "extra [title]" value = "<?
Php echo get_post_meta ($ post-> ID, 'title', 1);?
Gt; "style =" width: 50% "/>?
Php echo get_post_meta ($ post-> ID, 'description', 1); ?
Gt; </ Textarea> </ p> <p> Видимість поста: <?
Php $ mark_v = get_post_meta ($ post-> ID, 'robotmeta', 1); ?
Gt; <Label> <input type = "radio" name = "extra [robotmeta]" value = "" <?

Новости