Добавляем в Advanced Custom Fields фильтр вывода полей у поста «для определнных категорий и подкатегорий» в WordPress
В 90% случаев при разработке на WordPress спасает компонент Advanced Custom Fields. Это компонент динамического добавления полей для разных компонентов WordPress — постов, страниц, настройки темы (только в PRO) и многое другое.
Для каждого набора полей есть настройка — где будут выводиться эти поля. Выбор достаточно большой, но при разработке очередного сайта мне не хватило условия — выводить для постов, которые находятся в определенной рубрике (категории) или подрубрике (подкатегории). Стандартный функционал предлагает выбрать только фиксированную рубрику.
Благо, у компонента ACF есть отличное API, построенное на хуках, чем мы и воспользуемся.
Для начала нам необходимо добавить условия в настройки группы полей, это должно будет выглядеть следующим образом:
В данном случае нам необходимо добавить два хука, первый из которых добавляет новый пункт «Post Parent Category» в группу «Post». Второй хук добавляет значения фильтра, а именно список категорий. Код вывода списка категорий подсмотрен в исходниках ACF плагина, там есть замечательная функция acf_get_taxonomy_terms($taxonomy), которая используется для схожих фильтров.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | if(!function_exists('delfiLocationRulesTypes')) { add_filter('acf/location/rule_types', 'delfiLocationRulesTypes'); function delfiLocationRulesTypes( $choices ) { $choices['Post']['parent_category'] = 'Post Parent Category'; return $choices; } } if(!function_exists('delfiLocationRulesValuesParentCategory')) { add_filter('acf/location/rule_values/parent_category', 'delfiLocationRulesValuesParentCategory'); function delfiLocationRulesValuesParentCategory($choices) { $terms = acf_get_taxonomy_terms( 'category' ); if( !empty($terms) ) { $choices = array_pop($terms); } return $choices; } } |
Вторым и более сложным шагом является обработка данного фильтра. Т.к. в WordPress нет возможности получить иерархию рубрик (категорий) или я просто не нашел данного функционала, то делаем рекурсивное получение всех рубрик по цепочке. Если вложенность большая, то будет достаточно много запросов, но это сравнение происходит только на стороне администратора, поэтому не страшно.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | if(!function_exists('delfiLocationRulesMatchParentCategory')) { add_filter('acf/location/rule_match/parent_category', 'delfiLocationRulesMatchParentCategory', 100, 3); function delfiLocationRulesMatchParentCategory($match, $rule, $options) { $ruleValue = explode(':', $rule['value']); $ruleTerm = get_term_by('slug', $ruleValue[1], $ruleValue[0]); if(is_null($options['post_taxonomy'])) { $options['post_taxonomy'] = wp_get_post_categories($options['post_id']); } $terms = array(); if(!empty($options['post_taxonomy'])) { foreach($options['post_taxonomy'] as $termId) { if(!empty($termId)) { delfiGetTermsRecursive($termId, $terms); } } } if(!empty($terms) && isset($ruleTerm->term_id)) { foreach($terms as $term) { if($term->term_id == $ruleTerm->term_id || $term->parent == $ruleTerm->term_id) { if($rule['operator'] == "==") { return true; } elseif($rule['operator'] == "!=") { return false; } } } } return false; } } if(!function_exists('delfiGetTermsRecursive')) { function delfiGetTermsRecursive($id, &$terms) { if($id > 0) { $term = get_term((int) $id, 'category'); $terms[] = $term; if($term->parent > 0) { delfiGetTermsRecursive($term->parent, $terms); } } } } |
В данном коде две функции, где одна обрабатывает — выводить ли группу полей на текущей странице, а вторая рекурсивно проходит по цепочке рубрик.
Ссылки по теме:
https://www.advancedcustomfields.com/resources/custom-location-rules/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | //Acf add parent sub category if(!function_exists('delfiLocationRulesTypes')) { add_filter('acf/location/rule_types', 'delfiLocationRulesTypes'); function delfiLocationRulesTypes( $choices ) { $choices['Post']['parent_category'] = 'Post Parent Category'; return $choices; } } if(!function_exists('delfiLocationRulesValuesParentCategory')) { add_filter('acf/location/rule_values/parent_category', 'delfiLocationRulesValuesParentCategory'); function delfiLocationRulesValuesParentCategory($choices) { $terms = acf_get_taxonomy_terms( 'category' ); if( !empty($terms) ) { $choices = array_pop($terms); } return $choices; } } if(!function_exists('delfiLocationRulesMatchParentCategory')) { add_filter('acf/location/rule_match/parent_category', 'delfiLocationRulesMatchParentCategory', 100, 3); function delfiLocationRulesMatchParentCategory($match, $rule, $options) { $ruleValue = explode(':', $rule['value']); $ruleTerm = get_term_by('slug', $ruleValue[1], $ruleValue[0]); if(is_null($options['post_taxonomy'])) { $options['post_taxonomy'] = wp_get_post_categories($options['post_id']); } $terms = array(); if(!empty($options['post_taxonomy'])) { foreach($options['post_taxonomy'] as $termId) { if(!empty($termId)) { delfiGetTermsRecursive($termId, $terms); } } } if(!empty($terms) && isset($ruleTerm->term_id)) { foreach($terms as $term) { if($term->term_id == $ruleTerm->term_id || $term->parent == $ruleTerm->term_id) { if($rule['operator'] == "==") { return true; } elseif($rule['operator'] == "!=") { return false; } } } } return false; } } if(!function_exists('delfiGetTermsRecursive')) { function delfiGetTermsRecursive($id, &$terms) { if($id > 0) { $term = get_term((int) $id, 'category'); $terms[] = $term; if($term->parent > 0) { delfiGetTermsRecursive($term->parent, $terms); } } } } |
Комментарии к Добавляем в Advanced Custom Fields фильтр вывода полей у поста «для определнных категорий и подкатегорий» в WordPress (6)
Patrick Greenwood
А у меня такая задача стоит.
У меня есть категории
Стран
и подкатегории
Города
Как мне создать поля выбора сначала страны, а потом выбор города (но только в этой стране) в другом поле.
Есть идеи?
P/s/ Мне кажется это достаточно актуальный функционал, но он до сих пор не реализована в коробке ACF. Странно почему
Stanislav
Для этого подойдет поле ACF Repeater, но он в платной версии. Но и цена порядка 20$ на домен окупается с лихвой, если проект более менее крупный. И там после 4 таких лицензий можно перейти на безлимитное количество доменов, как я понимаю. Ну или найти на просторах сети отдельно плагин с данным полем.
Patrick Greenwood
Нет ACF Repeater для этого никак не подойдет.
Он понадобится если мне нужно будет добавить несколько городов из разных стран.
Я понимаю что есть два варианта решения.
1. нужно поле Таксономии, но вывод там нужен только категорий (стандартно выводит все и категории и подкатегории)
2. Нужно поле Таксономиии с выводом подкатегорий выбранной конкретной категории в поле выше. Т.е. возможно тут должно быть участие условной логики, которую тоже нужно кастомизировать добавлением хуков.
Или второй вариант. Я тут на сайте ACF нашел статью https://www.advancedcustomfields.com/resources/dynamically-populate-a-select-fields-choices/
Как я понял можно кастомизировать поле Select с выводом в «варианты» списка категорий . Если я правльно понял… Дальше думаю.
Stanislav
Не сразу понял вопроса.
В Select действительно можно динамически загружать данные и это еще один удобный момент в ACF. Но тут вопрос связывания двух полей, с этим не сталкивался. Т.е. чтобы в одном Select выводить в зависимости от выбора первого.
Плюс описанная методика в статье заносит данные в настройки поля, т.е. заполняет Choises поле автоматом, как будто бы это сделано вручную. Не знаю, насколько это критично, да и в целом, сначала нужно решить вопрос — как получать значение поля Страны для вывода значения Городов.
По поводу п.1 Поведение вывода таксономий наверняка можно изменить хуками, т.е. убрать вывод иерархии
Patrick Greenwood
есть плагин Advanced Custom Fields: Categories
но что то он у меня не работает.
Не появляется поле Categories
Patrick Greenwood
вот подобный вопрос на форуме ACF задают https://support.advancedcustomfields.com/forums/topic/set-child-category/
но я пока не догнал с решениями предложенными в комментах