- Вступна частина
- Перш ніж почати створення
- Створюємо мета блок довільних полів
- # 1. Створимо новий мета блок для постів
- # 2. Заповнимо цей блок полями html форми
- # 3. зберігаємо дані
- Блок довільних полів для довільного типу записів
- Складнощі з типом checkbox
- Ще один приклад створення МЕТАБОКС (ООП)
- Модулі для створення блоків довільних полів
- висновок
Вступна частина
Перш ніж почати розповідати про те як створити довільний блок даних в адмін-панелі на сторінці редагування постів, який буде управляти зазначеними довільними полями, слід зазначити, що 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) {?> <P> <label> <input type = "text" name = "extra [title]" value = "<? Php echo get_post_meta ($ post-> ID, 'title', 1);?> "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); ?> </ Textarea> </ p> <p> Видимість поста: <? Php $ mark_v = get_post_meta ($ post-> ID, 'robotmeta', 1); ?> <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) {?> <P> <label> <input type = "text" name = "extra [title]" value = "<? Php echo get_post_meta ($ post-> ID, 'title', 1);?> "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); ?> </ Textarea> </ p> <p> Видимість поста: <? Php $ mark_v = get_post_meta ($ post-> ID, 'robotmeta', 1); ?> <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 = "" <?