Как настроить wp_list_categories
У меня есть список категорий в WooCommerce, который я пытаюсь настроить для отображения как на следующем изображении.
Я создал изображение выше, используя обычный HTML и CSS, однако теперь я хотел бы преобразовать его в WordPress, чтобы он создавался динамически.
Вот HTML код:
<div class="col tertiary" id="filters">
<ul class="product-categories">
<li id="pattern_garment_type">
<h5>Женщины</h5>
<ul>
<li class="selected">
<a href="#">Все</a>
</li>
<li class="">
<a href="#">Аксессуары</a>
</li>
<li class="">
<a href="#">Блузки</a>
</li>
.и т.д...
</ul>
</li>
<li id="pattern_garment_type">
<h5>Мужчины</h5>
<ul>
<li class="selected">
<a href="#">Все</a>
</li>
<li class="">
<a href="#">Аксессуары</a>
</li>
<li class="">
<a href="#">Пальто</a>
</li>
..и т.д..
</ul>
</li>
<li id="pattern_garment_type">
<h5>Дети</h5>
<ul>
<li class="selected">
<a href="#">Все</a>
</li>
<li class="">
<a href="#">Малыши</a>
</li>
<li class="">
<a href="#">Девочки</a>
</li>
<li class="">
<a href="#">Мальчики</a>
</li>
</ul>
</li>
</ul>
</div>
Вот текущий WordPress код, с которым я работаю (не уверен, стоит ли использовать walker для настройки вывода, чтобы он генерировался как HTML выше):
<div id="content-filters" class="two columns">
<?php $args = array(
'style' => 'list',
'show_count' => 0,
'use_desc_for_title' => 1,
'child_of' => 0,
'title_li' => __( '' ),
'show_option_none' => __('Нет пунктов меню'),
'number' => null,
'echo' => 1,
'depth' => 2,
'taxonomy' => 'product_cat',
); ?>
<div class="col tertiary" id="filters">
<ul class="product-categories">
<?php wp_list_categories( $args ); ?>
</ul>
</div>
1) Как я могу использовать фильтр wp_list_categories, чтобы добавить ссылку "Все" в начало подкатегорий, которая ведет на страницу, отображающую все элементы.
2) Как я также могу использовать фильтр wp_list_categories, чтобы удалить ссылку из родительской категории и обернуть её в тег для выделения жирным шрифтом (как на примере изображения)?
Буду благодарен за любую помощь
Даже если существует фильтр wp_list_categories
, он передает (и вы должны вернуть) HTML-разметку, сгенерированную функцией wp_list_categories()
. Это означает, что если вы хотите использовать этот фильтр, вам придется изменять DOM с помощью PHP, и хотя это возможно (желательно с использованием внешних PHP-библиотек), это точно не лучшее решение для ваших нужд.
Альтернатива — использовать JavaScript для изменения HTML после его создания. Это возможно, но я разработчик WordPress, а не JavaScript, поэтому я дам вам решение на WordPress.
Вам нужно создать собственный класс Category Walker, а затем использовать его в кастомизированной версии wp_list_categories()
.
Давайте начнем.
Сначала создадим пользовательский класс Category Walker (поместите его в functions.php
):
class My_Category_Walker extends Walker_Category {
var $lev = -1;
var $skip = 0;
static $current_parent;
function start_lvl( &$output, $depth = 0, $args = array() ) {
$this->lev = 0;
$output .= "<ul>" . PHP_EOL;
}
function end_lvl( &$output, $depth = 0, $args = array() ) {
$output .= "</ul>" . PHP_EOL;
$this->lev = -1;
}
function start_el( &$output, $category, $depth = 0, $args = array(), $id = 0 ) {
extract($args);
$cat_name = esc_attr( $category->name );
$class_current = $current_class ? $current_class . ' ' : 'current ';
if ( ! empty($current_category) ) {
$_current_category = get_term( $current_category, $category->taxonomy );
if ( $category->term_id == $current_category ) $class = $class_current;
elseif ( $category->term_id == $_current_category->parent ) $class = rtrim($class_current) . '-parent ';
} else {
$class = '';
}
if ( ! $category->parent ) {
if ( ! get_term_children( $category->term_id, $category->taxonomy ) ) {
$this->skip = 1;
} else {
if ($class == $class_current) self::$current_parent = $category->term_id;
$output .= "<li class='" . $class . $level_class . "'>" . PHP_EOL;
$output .= sprintf($parent_title_format, $cat_name) . PHP_EOL;
}
} else {
if ( $this->lev == 0 && $category->parent) {
$link = get_term_link(intval($category->parent) , $category->taxonomy);
$stored_parent = intval(self::$current_parent);
$now_parent = intval($category->parent);
$all_class = ($stored_parent > 0 && ( $stored_parent === $now_parent) ) ? $class_current . ' all' : 'all';
$output .= "<li class='" . $all_class . "'><a href='" . $link . "'>" . __('All') . "</a></li>\n";
self::$current_parent = null;
}
$link = '<a href="' . esc_url( get_term_link($category) ) . '" >' . $cat_name . '</a>';
$output .= "<li";
$class .= $category->taxonomy . '-item ' . $category->taxonomy . '-item-' . $category->term_id;
$output .= ' class="' . $class . '"';
$output .= ">" . $link;
}
}
function end_el( &$output, $page, $depth = 0, $args = array() ) {
$this->lev++;
if ( $this->skip == 1 ) {
$this->skip = 0;
return;
}
$output .= "</li>" . PHP_EOL;
}
}
Он расширяет WP Walker_Category и переопределяет все 4 метода так, чтобы они соответствовали вашим нуждам.
После этого в functions.php
добавьте кастомизированную функцию:
function custom_list_categories( $args = '' ) {
$defaults = array(
'taxonomy' => 'category',
'show_option_none' => '',
'echo' => 1,
'depth' => 2,
'wrap_class' => '',
'level_class' => '',
'parent_title_format' => '%s',
'current_class' => 'current'
);
$r = wp_parse_args( $args, $defaults );
if ( ! isset( $r['wrap_class'] ) ) $r['wrap_class'] = ( 'category' == $r['taxonomy'] ) ? 'categories' : $r['taxonomy'];
extract( $r );
if ( ! taxonomy_exists($taxonomy) ) return false;
$categories = get_categories( $r );
$output = "<ul class='" . esc_attr( $wrap_class ) . "'>" . PHP_EOL;
if ( empty( $categories ) ) {
if ( ! empty( $show_option_none ) ) $output .= "<li>" . $show_option_none . "</li>" . PHP_EOL;
} else {
if ( is_category() || is_tax() || is_tag() ) {
$current_term_object = get_queried_object();
if ( $r['taxonomy'] == $current_term_object->taxonomy ) $r['current_category'] = get_queried_object_id();
}
$depth = $r['depth'];
$walker = new My_Category_Walker;
$output .= $walker->walk($categories, $depth, $r);
}
$output .= "</ul>" . PHP_EOL;
if ( $echo ) echo $output; else return $output;
}
Самая сложная часть сделана. Теперь код для шаблона, поместите его туда, где вам нужно:
<div id="content-filters" class="two columns">
<div class="col tertiary" id="filters">
<?php
$args = array(
'taxonomy' => 'product_cat',
'show_option_none' => __('No Menu Items.'),
'echo' => 1,
'depth' => 2,
'wrap_class' => 'product-categories',
'level_class' => 'pattern_garment_type',
'parent_title_format' => '<h5>%s</h5>',
'current_class' => 'selected'
);
custom_list_categories( $args );
?>
</div>
</div>
Настройте аргументы $args
по своему усмотрению, я установил их в соответствии с вашим кодом. Только я изменил 'pattern_garment_type' на класс, а не на id, потому что в HTML нельзя иметь один и тот же id у нескольких элементов (как в вашей разметке).
Вот и все, надеюсь, это поможет.

Oudin,
Отвечаю на часть вашего вопроса по CSS:
Используйте это, чтобы убрать маркеры списка:
.ul.product-categories, ul.children{
list-style-type: none;
}
Используйте это, чтобы сделать только основные категории жирными:
li {font-weight:normal} // сначала нужно установить обычное состояние списка
ul.product-categories > li{font-weight:bold;} // затем можно изменить верхний уровень списка, не затрагивая дочерние элементы
Вот как можно стилизовать эти элементы с помощью CSS, не создавая собственные классы.
Вы также можете добавить этот аргумент в wp_list_categories:
'hide_empty' => 0
Чтобы показать все категории, даже те, в которых нет записей.
Есть два подхода к решению второй части вашего вопроса (добавление ссылки ALL и удаление ссылок из основных категорий):
- Можно использовать Javascript/jQuery для удаления/добавления нужных элементов после загрузки страницы
- Можно написать фильтр для wp_list_categories, чтобы внести эти изменения
Вариант 2 будет более правильным с точки зрения архитектуры. Вариант 1 будет самым быстрым в реализации.
Я пока не реализовал ни один из них из-за нехватки времени. Но рекомендую изучить создание фильтров в WordPress.

Спасибо за ответ, однако меня больше интересует кодинг для WordPress, а не CSS, как я уже упоминал, я уже создал HTML и CSS для приложенного изображения. Что требуется — это правильный способ генерации HTML через WordPress, аналогичный тому, что я предоставил. Так что если вы могли бы подробнее рассказать о фильтрах, это было бы замечательно.
