「Typecho」读者墙的实现方法
? 想法
最近想给博客实现一个读者墙的功能,具体的想法就是在一个页面输出最近留言的用户以及留言最多的用户。先来看看最终的效果吧——??? 朋友。
?️ 思路
有了想法接下来就是怎么使用前后端语言来实现,其实就是使用php对数据库中的table.comments
数据表进行分组、聚合、查询,我将两个需求分为了两个函数,具体的思路都写在注释里了,想要研究的直接看,不想研究的直接拿去用:
1、查询最多评论的用户——getMostVisitors()
;
function getMostVisitors($limit = 12, $masterEmail = 'myxc@live.cn')
{
$db = Typecho_Db::get(); // 读取数据库
$sql = $db->select('COUNT(author) AS cnt', 'author', 'url', 'mail')
->from('table.comments')
// ->where('status = ?', 'approved')
// ->where('type = ?', 'comment')
->where('mail != ?', $masterEmail) //排除自己上墙
->group('mail') // 按照数据发
->order('cnt', Typecho_Db::SORT_DESC)
->limit($limit); //读取几位用户的信息
$result = $db->fetchAll($sql);
if ($result) {
foreach ($result as $value) { // 循环输出获取到的数据
if (!$value['url']) { // 如果用户没有url,那么就把url转化为邮箱跳转
$value['url'] = 'mailto:' . $value['mail'];
}
$mostactive .= '<li><a target="_blank" rel="nofollow" href="' . $value['url'] . '"><img src="https://cravatar.cn/avatar/' . md5(strtolower($value['mail'])) . '?s=36&d=&r=G"><em>' . $value['author'] . '</em><strong>+' . $value['cnt'] . '</strong></a></li>'; // 前端html结构
}
echo $mostactive;
}
}
2、查询最近评论的用户——getRecentVisitors()
。
function getRecentVisitors($limit = 12, $masterEmail = 'myxc@live.cn')
{
$db = Typecho_Db::get();
$sql = $db->select()->from('table.comments')
->group('mail')
->where('mail != ?', $masterEmail) //排除自己上墙
->limit($limit)
->order('created', Typecho_Db::SORT_DESC);
$result = $db->fetchAll($sql);
if ($result) {
foreach ($result as $value) {
if (!$value['url']) {
$value['url'] = 'mailto:' . $value['mail'];
}
$count = $db->fetchRow(
$db->select('COUNT(*)')
->from('table.comments')
->where('status = ?', 'approved')
->where('mail = ?', $value['mail'])
);
$commentnum = $count['COUNT(*)'];
$mostactive .= '<li><a target="_blank" rel="nofollow" href="' . $value['url'] . '"><img src="https://cravatar.cn/avatar/' . md5(strtolower($value['mail'])) . '?s=36&d=&r=G"><em>' . $value['author'] . '</em><strong>+' . $commentnum . '</strong></a></li>';
}
echo $mostactive;
}
}
? 食用
后端输出
在需要调用的位置使用<?php getRecentVisitors(); ?>
与<?php getMostVisitors(); ?>
输出,例如:
<h2>读者墙</h2>
<p class="notice">留言不积极,思想有问题~☺️</p>
<div id="reader-wall">
<h3>最近来的</h3>
<ul class='readers-list'>
<?php getRecentVisitors(); ?>
</ul>
<h3>最常来的</h3>
<ul class='readers-list'>
<?php getMostVisitors(); ?>
</ul>
</div>
前端样式
这个前端样式是我自己写的,具体效果可以去我的独立页面「??? 朋友」查看:
#reader-wall>.readers-list {
padding: unset;
margin: unset;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
}
#reader-wall>.readers-list li {
width: 25%;
height: fit-content;
list-style: none;
}
#reader-wall>.readers-list a::after {
content: unset
}
#reader-wall>.readers-list a {
margin: 4px;
border: #ccc 1px solid;
border-radius: 2px;
font-size: 10px;
height: 40px;
line-height: 40px;
position: relative;
display: block;
}
#reader-wall>.readers-list a:hover {
transform: translateY(-5px);
box-shadow: 8px 8px 5px rgb(0 0 0 / 38%)
}
#reader-wall img,
#reader-wall strong {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
#reader-wall>.readers-list a>img {
border: 1px solid #ccc;
left: .2rem;
margin: unset;
animation: img-light 4s ease-in-out infinite
}
#reader-wall>.readers-list a:hover>img {
transform: translateY(-50%) scale(1.15) rotate(720deg)
}
@keyframes img-light {
0% {
box-shadow: 0 0 4px #f00;
}
25% {
box-shadow: 0 0 16px #0f0;
}
50% {
box-shadow: 0 0 4px #00f;
}
75% {
box-shadow: 0 0 16px #0f0;
}
100% {
box-shadow: 0 0 4px #f00;
}
}
#reader-wall>.readers-list a>em {
font-size: 1rem;
font-family: fangsong;
max-width: 58%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-weight: bold;
margin: 0 auto;
display: block;
text-align: center;
}
#reader-wall>.readers-list a:hover>em {
font-size: 250%;
}
#reader-wall>.readers-list a>strong {
right: .4rem;
}
@media screen and (max-width:767px) {
#reader-wall>.readers-list li {
width: 50%;
}
}
body.theme-dark #reader-wall>.readers-list a {
background-color: rgba(230, 230, 255, .03);
}
.readers-list * {
-webkit-transition: all .2s ease-out;
-moz-transition: all .2s ease-out;
transition: all .2s ease-out;
}