一.初步尝试
在 index.php 的$this->title();
前面加上$this->sticky();
,如下:
1 2 3
| <h2 class="title"><a href="<?php $this->permalink() ?>"><?php $this->sticky(); $this->title() ?></a></h2> //其实就是下面这行 <?php $this->sticky(); $this->title() ?>
|
然后下面代码放在主题的文章列表输出的index.php中:
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
| $sticky = '1'; if($sticky){ $sticky_cids = explode('|',$sticky); $sticky_html = "<span style='color:red'>[置顶] </span>"; $db = Typecho_Db::get(); $pageSize = $this->options->pageSize; $select1 = $this->select()->where('type = ?', 'post'); $select2 = $this->select()->where('type = ? && status = ? && created < ?', 'post','publish',time()); $this->row = []; $this->stack = []; $this->length = 0; $order = ''; foreach($sticky_cids as $i => $cid) { if($i == 0) $select1->where('cid = ?', $cid); else $select1->orWhere('cid = ?', $cid); $order .= " when $cid then $i"; $select2->where('table.contents.cid != ?', $cid); } if ($order) $select1->order(null,"(case cid$order end)"); if ($this->_currentPage == 1) foreach($db->fetchAll($select1) as $sticky_post){ $sticky_post['sticky'] = $sticky_html; $this->push($sticky_post); } $uid = $this->user->uid; if($uid) $select2->orWhere('authorId = ? && status = ?',$uid,'private'); $sticky_posts = $db->fetchAll($select2->order('table.contents.created', Typecho_Db::SORT_DESC)->page($this->_currentPage, $this->parameter->pageSize)); foreach($sticky_posts as $sticky_post) $this->push($sticky_post); $this->setTotal($this->getTotal()-count($sticky_cids)); }
|
二.进阶集成
上面那种方式,每次需要配置的时候还需要手动去更改index.php文件,有点麻烦。正好之前自己也在写Typecho的主题,就想着把这个文章置顶集成到主题里,通过主题后台直接设置。话不多说,直接开搞,我们先来实现后台填写置顶cid
1.创建后台设置
在主题的functions.php文件中添加以下代码,创建一个新的后台设置选项来存储置顶文章的cid
1 2 3 4 5
| $stickyCids = new Typecho_Widget_Helper_Form_Element_Text('stickyCids', NULL, NULL, _t('置顶文章CID'), _t('在这里填入置顶文章CID,支持多填,用英文逗号隔开')); $form->addInput($stickyCids); $stickyCids->setAttribute('class', 'j-setting-content j-setting-global');
|
2.首页index.php
就当我以为一切顺利的时候,发现了个bug:置顶一直显示少一个,按理说最后一个数字后边是不需要加逗号的(比如69,63,59)但是这样就只会显示69和63两个。经过多次折腾分析,发现就是逗号出了问题,那我们需要确保无论末尾有无逗号,都能正确获取所有的cid。
下面是我修改完善后的代码,放进index.php即可,配合上边后台设置的语句
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
| <?php $stickyCids = $this->options->stickyCids; if ($stickyCids) { $sticky_cids = explode(',', $stickyCids); $sticky_cids = array_filter(array_map('trim', $sticky_cids), 'trim'); $sticky_html = "<span style='color:red'>[置顶] </span>"; $db = Typecho_Db::get(); $pageSize = $this->options->pageSize; $select1 = $this->select()->where('type =?', 'post'); $select2 = $this->select()->where('type =? && status =? && created <?', 'post', 'publish', time()); $this->row = []; $this->stack = []; $this->length = 0; $order = ''; $stickyCidMap = []; $whereClauses = []; $whereParams = []; foreach ($sticky_cids as $i => $cid) { $whereClauses[] = 'cid =?'; $whereParams[] = $cid; $order.= " when ". $cid. " then ". $i; $select2->where('table.contents.cid!=?', $cid); $stickyCidMap[$cid] = $i; } if (!empty($whereClauses)) { $select1->where(implode(' OR ', $whereClauses),...$whereParams); } if (empty(trim($order))) { $orderBy = 'table.contents.created'; $sort = Typecho_Db::SORT_DESC; } else { $orderBy = null; $sort = "(case cid$order end)"; } if ($orderBy!== null) { $select1->order($orderBy, $sort); } if ($this->_currentPage == 1) { $stickyPosts = $db->fetchAll($select1); usort($stickyPosts, function ($a, $b) use ($stickyCidMap) { return $stickyCidMap[$a['cid']] - $stickyCidMap[$b['cid']]; }); foreach ($stickyPosts as $sticky_post) { $sticky_post['sticky'] = $sticky_html; $this->push($sticky_post); } } $uid = $this->user->uid; if ($uid) { $select2->orWhere('authorId =? && status =?', $uid, 'private'); } $sticky_posts = $db->fetchAll($select2->order('table.contents.created', Typecho_Db::SORT_DESC)->page($this->_currentPage, $this->parameter->pageSize)); foreach ($sticky_posts as $sticky_post) { $this->push($sticky_post); } $this->setTotal($this->getTotal() - count($sticky_cids)); } ?>
|
由此,不依赖插件并且植入主题设置的置顶文章功能就完美实现了。或许这就是码代码的乐趣吧,需求驱动、编写代码、发现问题,然后不断尝试去解决问题,最后守得云开见月明!