背景
WordPress 文章底部一般都有文章导航,比如点击文章底部“上一篇”,可以导航到上一篇文章;刷到一些博客文章,底部导航显示的不是“上一篇”、“下一篇”,而是带了文章标题、分类等,这怎么做到的?
前言
搜索关键词 “wordpress 上一篇 下一篇 带标题”,找到一些中文文章,写的是如何修改,但是给了代码,虽然没有告知在哪个文章中,但是找到了关键词get_previous_post(),应该是通过这个函数获取到上一篇文章的对象,并且在 /wp-includes/link-template.php 文件中;
修改切换英文搜索 “wordpress next previous post”,找到 Astra 官方的文章,How to Change Previous and Next Link Text from a Single Blog Post? (wpastra.com),其中给出了详细的代码,和修改的位置,原来在主题的 function.php 中修改。(这里也说明买了专业版的 Astra Pro 也不能做到这个?)
什么是 function. php,这个文件是 wordpress 暴露出来,留给开发者修改 wordpress 行为的入口,留下了很多 hook,帮助开发者修改 wordpress;支持两类 hook,actions、filters:
- action 获取它接收到的信息,对其进行操作,并且不向调用挂钩返回任何内容;
- filter 获取它接收到的信息,对其进行过滤,然后将其返回以供进一步使用。
这次我们需要使用 filter,修改主题的某种行为。
目标
本次需要实现下面的功能
- 将文字“上一篇”,“下一篇”改成文章的标题,并在标题上方显示文章的分类。
- 调整样式,合适的展示效果,兼容手机端。
成果
先展示成果:
代码与样式修改:
- wordpress 管理后台,外观->主题文件编辑器,找到 function.php,文件末尾添加代码:
/** * added by user @2023-01-03 */ add_filter( 'astra_single_post_navigation', 'astra_change_next_prev_text' ); /** * Function to change the Next Post/ Previous post text. * * @param array $args Arguments for next post / previous post links. * @return array */ function astra_change_next_prev_text( $args ) { $next_post = get_next_post(); $prev_post = get_previous_post(); $next_text = false; if ( $next_post ) { $next_text = sprintf( '<div class="nav-next-block"> <div> <div class="nav-block-cat">%s</div> <div class="nav-block-title">%s</div> </div> <div class="ast-right-arrow">→</div> </div>', implode(",", wp_list_pluck(get_the_terms($next_post,'category'), 'name')), $next_post->post_title ); } $prev_text = false; if ( $prev_post ) { $prev_text = sprintf( '<div class="nav-previous-block"> <div class="ast-left-arrow">←</div> <div> <div class="nav-block-cat">%s</div> <div class="nav-block-title">%s</div> </div> </div>', implode(",", wp_list_pluck(get_the_terms($prev_post,'category'), 'name')), $prev_post->post_title ); } $args['next_text'] = $next_text; $args['prev_text'] = $prev_text; return $args; }
- 外观-> 自定义->额外css,编辑器末尾添加 css 样式:
/* 底部导航 */ .post-navigation .nav-previous { width: 50%; } .nav-previous .ast-left-arrow { padding-right:1em } .nav-previous .nav-previous-block { display: flex; align-items: center; text-align: left; /* line-height: 1.8; */ } .post-navigation .nav-block-cat { /* padding-bottom:1em; */ color: #2e8b57; } .post-navigation .nav-block-title { height:3em; padding: 1em 0; overflow: hidden; } .post-navigation .nav-next { width: 50%; } .nav-next .ast-right-arrow { padding-left: 1em; } .nav-next .nav-next-block { display: flex; align-items: center; text-align: right; } @media (max-width: 420px) { .single .post-navigation .nav-next, .single .post-navigation .nav-previous { width: 50%; margin-bottom:0; } }
过程
上面代码在 Astra 主题下有作用,如果是其它的主题,可能方法有所不同,所以提供一些修改过程比较有用。读者可以根据自己的主题做一些探索。
修改 function.php
如前文说,直接将 How to Change Previous and Next Link Text from a Single Blog Post? (wpastra.com) 代码复制到 function.php 中,实现了文章标题导航的效果。
寻找 Post 属性
展示文章分类,需要找到文章的分类,不知道如何去弄,代码中得到了一个 post 对象 $next_post,但是不知道这个 post 对象存在的数据和属性,查询 wordpress 官方,得到了 WP_Post 定义。
获取分类
直接使用 $next_post->post_category,得到却是一个 array,提示不能将 array_to_string;搜索可知,数组弄成string,需要implode,改成 implode(“,”, $next_post->post_categroy),输出的是一个数字,看来是分类的id,而不是文字。
提取分类文字
这个过程耗用了不少时间,找了不少资料,也没有解决,输出 \$next_post,json_encode(\$next_post),其中并没有 post_categroy 属性;再次阅读 WP_Post 的代码,发现 $next_post->post_categroy,是一个方法去完成:
if ( 'post_category' === $key ) { if ( is_object_in_taxonomy( $this->post_type, 'category' ) ) { $terms = get_the_terms( $this, 'category' ); } if ( empty( $terms ) ) { return array(); } return wp_list_pluck( $terms, 'term_id' ); }
这段代码从对象中,取出了 category,获取 terms 对象集合,但是使用 term_id,提取了分类的id,应该还能使用其它方式,提取到分类名称,查看 get_object_terms需要传入 WP_Term 做参数,WP_Term的定义在这里,这样,我们使用 name,就能得到分类的名称了。
照葫芦画瓢,用这个代码就能从 对象的 terms 中获取到分类数据:
wp_list_pluck(get_the_terms($prev_post,'category'), 'name')
修改样式
代码中输出了合理的 div 结构,最后就是调节样式的内容。
图方便直接修改了代码,在代码中给 div 容器加 style,每次更新 function.php 文件,刷新页面查看效果,这种方式最慢。
正确的做法是,给 div 添加合理的样式,直接在 额外css 样式编辑器修改 css 样式表,可以在右侧看到效果,并且可以切换到不同的屏幕尺寸(模拟手机、平板),大幅节约时间。
后记
- wordpress 正确地添加 hook 代码的方式,应该是新建单独的 php 文件,在 function.php中包含即可。
include( get_stylesheet_directory() . '/includes/theme_setup.php' );
- 使用代码编辑器插件方式修改 function.php,更好,比如插件 Code Snippets,但是我们需要先弄懂了 wordpress hook 的一些机制,才能更好地利用这些代码编辑插件。对应到前面说的“中文文章只说了代码却没说修改位置”,老鸟应该使用了这种插件。
- 可以在定义自己的 action,修改 css,不一定要在主题的额外 css 样式中修改。
- 搜索 Useful WordPress hook,获取更多的 wordpress 修改方式,比如阅读时提醒订阅,加载广告,文章页面添加通用文字等。
- WordPress 支持的 hooks 列表,hooks
- 在搜索的过程中,很多博主都在说,新建子主题的必要性,不要因为主题升级,导致函数与样式丢失;如果使用 Astra 主题,手工创建也很简单,也可以使用官方的工具。
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。