{ Hello Magento 2 }

解决 Magento 2 应用问题,更注重深度挖掘。(ง •̀_•́)ง

0%

wordpress 手动添加文章目录(原创)

问题描述

wordpress 添加文章目录已经有很成熟的方案,无论是通过插件还是通过手动添加代码的方式,但是这些方式都是在文章内容中插入文章目录,而我希望将文章目录单独列到原本属于 widget 的侧边栏中。所以我打算通过借鉴上面两种方式,来实现自己的文章目录。

借鉴手动方式

手动方式重点是向 theme 的functions.php 中添加 add_filter( "the_content", "article_index" );
他将使用函数article_index给文章内容进行过滤。在functions.php中再定义一个function article_index($content)接受文章内容作为参数,返回被过滤后的文章内容(添加了文章目录的内容),文章目录就被插入了。
以下是网络上找到的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function article_index($content) {
$matches = array();
$ul_li = '';
$r = "/<h3>([^<]+)</h3>/im";
if(preg_match_all($r, $content, $matches)) {
foreach($matches[1] as $num => $title) {
$content = str_replace($matches[0][$num], '<h3 id="title-'.$num.'">'.$title.'</h3>', $content);
$ul_li .= '<li><a href="#title-'.$num.'" title="'.$title.'">'.$title."</a></li>n";
}
$content = "n<div id="article-index">
<strong>文章目录</strong>
<ul id="index-ul">n" . $ul_li . "</ul>
</div>n" . $content;
}
return $content;
}

缺点是正则匹配太局限,不支持多级目录。

借鉴插件方式

选择的插件是:Content Index for wordpress
安装后发现功能是我想要的,有多级目录。实现功能的代码是 wp-content/plugins/wp-content-index.php
关键的函数是content_index_analysis但是研究了老半天依然没有理清楚他的逻辑。不过里面找到一个正则$r = "/<h(\d)([^>]*)>(.*)<\/h\d>/isU";他可以匹配所有的<h>标签。

思路

要让 single.php 侧边栏输出文章目录,只要在 single.php 中调用一个定义在 functions.php 中的函数,而该函数负责输出一串包含文章目录的html代码片段就好了。难点是如何输出这些片段。
问题抽象一下后,会发现是这样的,如何让下面这样一组数据组织成树状结构。

1
2
3
4
5
6
[0] h1
[1] h2
[2] h2
[3] h3
[4] h4
[5] h2

他应该被组织成这样

1
2
3
4
5
6
[0] h1
[1] h2
[2] h2
[3] h3
[4] h4
[5] h2

在做这个练习的时候,我发现我依靠了 h 本身的位置和层级

代码

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
67
68
69
70
71
72
73
74
75
76
77
78
function article_index($content) {
$matches = array();
$r = "/<h(\d)([^>]*)>(.*)<\/h\d>/isU";
if (is_single() && preg_match_all($r, $content, $matches, PREG_SET_ORDER)) {
$arr = article_index_create($matches);
$ul_li = article_index_ul($arr);
$side = '<div class="col-md-4"><div id="secondary" class="widget-area content-index" role="complementary">'
.'<nav class="bs-docs-sidebar hidden-print hidden-xs hidden-sm affix">'.$ul_li.'</nav></div></div>';
echo $side;
}
}

function article_index_create($arr) {
$arr_wash = array();
$min_level = $arr[0][1];
$max_level = $min_level;
foreach ($arr as $key => $value) {
preg_match("/id=\"(.*)\"/", $value[2], $href);
$title = trim(strip_tags($value[0]));
$arr_wash[] = ['href'=> $href[1] , 'title' => $title, 'level'=> $value[1]];
if ($min_level > $value[1]) {
$min_level = $value[1];
}
if ($max_level < $value[1]) {
$max_level = $value[1];
}
}
foreach ($arr_wash as $key => $value) {
if ($value['level'] == $min_level) {
$arr_wash[$key]['father'] = $key;
} else {
$father = null;
for ($i = ($key - 1); $i >= 0; $i-- ) {
if ($arr_wash[$i]['level'] < $value['level']) {
$father = $i;
break;
}
}
if (is_null($father)) {
unset($arr_wash[$key]);
} else {
$arr_wash[$key]['father'] = $father;
}
}
}
for ($i = $max_level; $i > $min_level; $i--) {
foreach ($arr_wash as $key => $value) {
if ($value['level'] == $i) {
$arr_wash[$value['father']]['child'][$key] = $value;
unset($arr_wash[$key]);
}
}
}
return $arr_wash;
}

function article_index_ul($arr_wash) {
$ul_li = '<ul>';
foreach ($arr_wash as $key => $val) {
$ul_li .= ul_recursion($val);
}
$ul_li .= '</ul>';
return $ul_li;
}

function ul_recursion($val)
{
if (! $val['child']) {
return '<li><a href="#'.$val['href'].'">'.$val['title'].'</a></li>';
} else {
$ul_li .= '<li><a href="#'.$val['href'].'">'.$val['title'].'</a><ul>';
foreach ($val['child'] as $k => $v) {
$ul_li .= ul_recursion($v);
}
$ul_li .= '</ul></li>';
return $ul_li;
}
}

稍作解释

article_index_create是最主要的,他将调用其它函数来完成生成文章目录的功能。
article_index_create他将接受匹配到的标题,返回包含层级关系的数组。
article_index_ul 负责将包含层级关系的数组转换成ul字符串。
ul_recursion用到了递归来处理子级。

总结

算法比具体的实现要费脑子 >”<

欢迎点评!