这里说的WordPress分类存档页,其实就是我们说的分类文章列表页,比如 WordPress开发。最近有人找倡萌开发了一个分类存档页子分类选择功能,单纯文字说的不太清楚,配合下面的图片做说明吧。
功能说明
当访问一级分类(顶级分类),比如下图的【作文】,就显示【作文】下的子分类列表:
当访问二级分类,【作文】-【动物作文】时,显示它的子分类,同时还保留和它同级的二级分类,同时高亮显示【动物作文】:
当访问三级分类,【作文】-【动物作文】-【小鸡】时,显示的分类列表和上面一样,只不过将【动物作文】和【小鸡】高亮显示:
此外,对子分类做一个高度限制,分类过多就显示一个【点击查看更多】的功能。
功能实现
我们需要通过php代码去获取数据,然后配合js实现一些交互,以及通过css美化一下。
php部分
先贴下代码,代码中重要的部分都有注释说明:
if( !class_exists('WPKJ_Get_Terms_List') ) :
/**
* 获取当前分类的子分类列表
*/
class WPKJ_Get_Terms_List{
function __construct()
{
add_action( 'wp_enqueue_scripts', array( $this, 'wpkj_enqueue_terms_list_scripts'), 10 );
}
public function wpkj_enqueue_terms_list_scripts(){
if( is_category() || is_tax() ) {
wp_enqueue_style( 'terms-list-style', get_template_directory_uri() . '/assets/css/terms-list.css', array(), filemtime(get_template_directory().'/assets/css/terms-list.css') );
wp_enqueue_script( 'terms_list', get_template_directory_uri() . '/assets/js/terms-list.js', array('jquery'), '', true );
}
}
public function wpkj_terms_list( $hide_empty = false ){
//如果不是分类或自定义分类页面,不执行
if( !is_category() && !is_tax() ) return;
//获取当前查询的对象
$object = get_queried_object();
//如果对象不存在,不执行
if( !$object ) return;
$taxonomy = $object->taxonomy; //获取分类法
$current_id = $object->term_id; //获取分类id
if( $current_id ){
//设置一下内容缓冲
ob_start();
echo '<div class="wpkj-terms-list">';
//获取当前分类对象
$current = get_term( $current_id, $taxonomy );
//获取当前分类的父级分类
$parent_id = $current->parent;
if ( $parent_id ) { // 存在父级分类,说明非顶级分类
$parent = get_term( $parent_id, $taxonomy );
$grand_parent_id = $parent->parent;
if( $grand_parent_id ){ //有祖父类,显示父级分类兄弟
$this->wpkj_get_term_children( $grand_parent_id, $parent_id, $taxonomy, $hide_empty, 'term-parents' );
}
//如果有父类,显示同级分类
$this->wpkj_get_term_children( $parent_id, $current_id, $taxonomy, $hide_empty, 'term-brothers' );
//如果有子分类,显示子分类
$this->wpkj_get_term_children( $current_id, false, $taxonomy, $hide_empty, 'term-children' );
} else { // 顶级分类时
//如果有子分类,显示子分类
$this->wpkj_get_term_children( $current_id, false, $taxonomy, $hide_empty, 'term-children' );
}
echo '</div>';
//输出缓冲内容并清除缓冲
echo $result = ob_get_clean();
}
}
/**
* 通过父级id获取并输入子分类数据
* $parent_id 为父级id
* $term_id 为当前分类id,用于对比循环中哪个是当前分类,添加特定的css类名来适配高亮样式
*/
public function wpkj_get_term_children( $parent_id, $term_id = false, $taxonomy, $hide_empty, $class = '' ){
$args = array(
'taxonomy' => $taxonomy,
'hide_empty' => $hide_empty,
'child_of' => $parent_id,
'parent' => $parent_id, // child_of 和 parent 指定为同一个id,将只获取一个级别的数据
);
$terms = get_terms( $args );
if( !is_wp_error( $terms ) ){
$html = '<ul class="terms-ul '.$class.'">';
foreach ( $terms as $term) {
$id = $term->term_id;
//如果是当前分类,就添加一个类名,用于适配高亮样式
if( $term_id && $id === $term_id ){
$html .= '<li class="current"><a href="'. get_term_link( $id, $taxonomy ) .'">'. $term->name .'</a></li>';
} else {
$html .= '<li><a href="'. get_term_link( $id, $taxonomy ) .'">'. $term->name .'</a></li>';
}
}
$html .= '</ul>';
echo $html;
}
}
}
endif;
new WPKJ_Get_Terms_List();
封装了一个简单的类 WPKJ_Get_Terms_List
,为避免可能在以后的项目中有名称冲突,所以在外围判断一下是否存在同名的类。
在 WPKJ_Get_Terms_List
这个类中,除了构造方法以外,包含三个方法:
wpkj_enqueue_terms_list_scripts
:用于引入功能所需的css和js文件。当前的设置是将css和js放在主题的 assets 对应的目录中,如果你的文件放在不同的路径,自己修改路径。wpkj_terms_list
:查询和判断当前分类的数据,然后进行输出。参数$hide_empty
用来设定是否输出不含文章的空分类,默认为false
,即输出,如果不需要输出空分类,在调用时,设置为true
wpkj_get_term_children
:用来获取指定分类id的子分类数据,里面的前两个参数在注释中有说明,其余参数是为了传递一些必要的参数值。
这次开发,没有找到直接获取同级分类兄弟的方法,所以只能转变方式,先获取到父级分类id,然后再获取子分类。刚开始尝试过 get_term_children()
,发现它会获取所有子分类,包括子分类的子分类,实在是没有办法仅限定为下一级的子分类。
然后想到了 get_terms()
,它的所有参数继承自 WP_Term_Query
类,里面有参数 child_of
,如果仅仅设置这个参数,会和 get_term_children()
一样包含了子分类的子分类。然后在网上看到有朋友指出,还需要同时设置 parent
参数为同一个父级分类id,才能限制只显示下一级子分类。
JS部分
为了实现“点击查看更多”的功能,需要配合js代码操作,以下就是 terms-list.js 文件的代码:
jQuery(document).ready(function($) {
// 这部分是为了设置哪个部分列表才是显示在下方的第二部分子分类,
// 以及做一些样式设置,并限定在手机端对父分类列表隐藏
if( $(".term-parents").length>0 ){
var ulClass = ".wpkj-terms-list .term-brothers";
$(".wpkj-terms-list .term-parents li").css("background", "rgb(242,242,242)");
if ($(window).width() < 860) {
$(".wpkj-terms-list .term-parents").hide();
}
} else if( $(".term-children").length>0) {
var ulClass = ".wpkj-terms-list .term-children";
$(".wpkj-terms-list .term-brothers li").css("background", "rgb(242,242,242)");
if ($(window).width() < 860) {
$(".wpkj-terms-list .term-brothers").hide();
}
} else {
var ulClass = ".wpkj-terms-list .term-brothers";
}
// 子分类部分超过设置的高度 117px 就显示“点击查看更多”
$(ulClass).each(function () {
if ($(this).height() > 117) {
var moreHtm = '<span class="more-item js_more">点击查看更多</span>';
$(moreHtm).appendTo($(this).parent());
$(this).css("height", "117px");
}
});
$(document).on("click", ".wpkj-terms-list > .js_more", function () {
$(this).prev(ulClass).css("height", "auto");
$(this).removeClass("js_more").addClass("js_less");
$(this).html('点击隐藏更多');
});
$(document).on("click", ".wpkj-terms-list > .js_less", function () {
$(this).prev(ulClass).css("height", "117px");
$(this).removeClass("js_less").addClass("js_more");
$(this).html('点击查看更多');
});
});
注意代码中 23、26、35 三行的数字 117,是高度设置值,你可能需要根据你的需要,修改这个高度,超过这个高度就显示“点击查看更多”。
倡萌的js是比较弱的,所以逻辑可能有些复杂,见笑了。
CSS样式
我们还需要为列表添加一些样式,以下就是 terms-list.css 的代码:
.wpkj-terms-list{
margin: 15px 0;
}
.wpkj-terms-list .terms-ul{
list-style: none;
border-top: 1px solid rgba(0,0,0,.04);
border-left: 1px solid rgba(0,0,0,.04);
padding: 0;
overflow-y: hidden;
}
.wpkj-terms-list .terms-ul li{
width: 16.66%;
display: inline-block;
border-right: 1px solid rgba(0,0,0,.04);
border-bottom: 1px solid rgba(0,0,0,.04);
text-align: center;
background: #fff;
}
.wpkj-terms-list .terms-ul li a{
padding: 0;
display: block;
line-height: 2;
color: #333;
}
.wpkj-terms-list .terms-ul li.current a{
color: #ff6700;
}
.wpkj-terms-list .more-item{
width: 100px;
margin: 10px auto;
display: block;
cursor: pointer;
color: #ff6700;
}
@media screen and (max-width:860px){
.wpkj-terms-list .terms-ul li{
width: 20%;
}
}
@media screen and (max-width:640px){
.wpkj-terms-list .terms-ul li{
width: 25%;
}
}
@media screen and (max-width:480px){
.wpkj-terms-list .terms-ul li{
width: 33.33%;
}
}
@media screen and (max-width:360px){
.wpkj-terms-list .terms-ul li{
width: 50%;
}
}
样式不可能适配所有主题,需要大家根据自己的需要去调整。
使用方法
一般来说,我们只需要在分类列表的文件,比如 category.php 的适当位置添加下面的代码即可:
<?php
if( class_exists('WPKJ_Get_Terms_List') ) {
$list = new WPKJ_Get_Terms_List();
$list->wpkj_terms_list(); // 如果需要隐藏空分类,在左边的括号内填入 true
}
?>
先判断是否存在我们的类,然后实例化并输出。
从一开始,倡萌就考虑到兼容自定义分类法的,也就是说不仅仅可用于文章的分类,还可以是其他自定义文章类型的自定义分类法。你只需要将上面的代码添加到自定义分类法的列表文件中即可。
没明白怎么用的,PHP的内容是放在什么位置呢?
你可以放到你自己的开发的插件,或主题的functions.php。不过,从你的提问知道你应该不懂PHP开发,所以这个文章可能不适合你
请问,有类似这种功能的插件么?我在尝试将您的代码封装成插件。
客户提供需求后,我寻找过插件,但是没有发现可以满足条件的
哈哈,我也是在寻找,实在找不到了。关键词:过滤器、选择器、菜单。
我把上面的代码封装成插件了,用短代码的方式嵌入页面,不过我那个站的一级目录是自定义帖子的类型,爆出了一些错误,不懂插件开发的我还在尝试解决中。
Notice: Undefined property: WP_Post_Type::$taxonomy in \wp-content\plugins\dd-category-filter\dd-category-filter.php on line 42 Notice: Undefined property: WP_Post_Type::$term_id in \wp-content\plugins\dd-category-filter\dd-category-filter.php on line 43