阅读视图

发现新文章,点击刷新页面。

WPJAM Basic - 样式定制:一键自定义 WordPress 前后台和登录页面

继续 #WPJAM Basic# 插件的详细介绍,前面介绍了「优化设置」还没有看的同学,可以先看一下,今天接着介绍「样式定制」的功能,「样式定制」也是 WPJAM Basic 最早开发的功能,开发这个功能主要是为了方便自定义网站。

简单说就是「样式定制」功能让用户可以在 WordPress 前后台和登录这三个主要不同的界面的头部(head)和底部(footer)插入一些定制代码,实现对网站页面样式和前端功能进行快速的定制。

因为是给三个主要不同的界面实现定制,那我们也分三个部分来讲解吧:

前台定制

前台定制的功能管的就是前台的页面了,通过前台 Head 代码前台 Footer 代码来定制前台的样式和功能。

这个功能对于有时候网站需要验证的时候有用,比如验证百度站长的时候,百度站长会给你两种选择:

  1. 让你在根目录上传一个 txt 文件
  2. 在头部的 Head 代码总加一段代码

如果不方便上传 txt 验证文件时候,直接把代码复制到这里的头部 Head 代码即可,即使方便的上传验证文件时候,把代码贴到这里也是更方便。

如果你的主题不支持暗黑模式,也可以通过把下面代码贴到这里的前台 Head 代码,也可以实现博客暗黑模式:

<style type="text/css">
@media (prefers-color-scheme: dark) {
html, img {filter: invert(1) hue-rotate(180deg);}
html, iframe {filter: invert(1) hue-rotate(180deg);}
img {opacity: .75;}
}
</style>

此外我在新版还增加了「文章页代码」选项,本来该功能是扩展,现在我把功能增加到「样式定制」功能中,因为这里使用起来比较顺手,不过做成了开关,开启可以单独设置每篇文章 head 和 Footer 代码。

先说下该功能的主要用途,主要是因为如果某些文章的展示的时候需要引入一些的 JS 和 CSS 来实现特殊的页面效果,怎么处理好呢?如果直接内容编辑框中插入,首先不是特别方便和友好,也可能由于安全或者其他的原因而造成插入失败。

「文章页代码」功能就是为该需求实现的,它可以让大家在文章编辑页面插入文章头部代码和底部代码:

另外他还可以让大家选择是否支持在文章列表页设置,有三个选项:支持,不支持,只允许,如果可以设置,在后台的文章列表页面中就有「文章页代码」按钮,如下图所示:

点击「文章页代码」按钮,就可以通过弹窗的方式来设置文章详情页的头部和底部代码:

后台定制

如上图所示,后台定制多了两个个功能,一个就是可以上传一个 40x40 大小的图片替换后台左上角的 WordPress 图标,另外一个是「后台右下角显示内存使用和 SQL 数量」,开启之后,在后台右下角显示:

其他和「前台定制」一样,也是通过后台 Head 代码后台 Footer 代码来定制后台的样式或者功能。

登录界面

登录界面也有两个额外的功能,首选是可以设置「登录之后跳转的页面」,比如可以设置网站首页,后台文章列表页面等等,另外一个是可以「屏蔽登录界面语言切换器」,这个不必多言。

其他一样可以设置 Head 和 Footer 代码,通过这两个值,可以做出自定义的登录界面。如果你懂 CSS,我们就可以自定登陆界面的 logo,甚至通过只用 CSS 就能做出非常漂亮的 WordPress 登录界面

关于样式定制,目前就提供了这些选项,基本满足简单定制的需求,该功能虽然偏向程序员使用,但是只要懂一些 CSS 和 JS,还是可以定制出很不错的 WordPress 后台,登录界面和前台的样式和交互。

WPJAM Basic - 优化设置:一键优化和增强 WordPress 功能

#WPJAM Basic# 插件的「优化设置」是 WPJAM Basic 插件的开端,可以说是我爱水煮鱼博客多年使用 WordPress 的经验而整理的优化插件。

我们 WordPress JAM 为了在定制开发的时候方便,就把各种用不上的功能,或者可能影响性能的功能,都提供开关,只需要一键搞定。

经过几年的发展,优化设置的功能分成功能屏蔽和增强优化两大块:

功能屏蔽

上图可以很清楚看到,功能屏蔽就是让你屏蔽 WordPress 中一些用不上的功能,我把功能屏蔽分成六大块:

常规功能

屏蔽文章修订功能,精简文章表数据。

WordPress 的文章版本修订功能是通过在 wp_posts 表中增加一条记录来实现的,这样如果修改了几次,就会有好几个修订版本,插入好几条记录。

如果经常修改文章或者博客有多个作者的话,每篇文章记录在 posts 表中都会有多条记录,文章一多,wp_posts 表的数据就会急剧上升,数据表的增大,最后自然影响了查询,肯定会变慢。所以建议屏蔽文章修订功能,提高数据库效率。

彻底关闭Trackback,防止垃圾留言。

Trackbacks 是被设计出来用于博客间交流,但实际上这样的应用很少,反而被 Spammer 滥用,并且各种防垃圾评论插件比如 Akismet 也经常漏掉,可以说防不胜防,Trackback 真的让人不慎其烦,建议彻底关闭 WordPress 的 Trackback。

关闭XML-RPC功能,只在后台发布文章。

XML-RPC协议用于客户端发布文章,如果只是在 WordPress 后台发布,可以关闭 XML-RPC 功能,提供 WordPress 的安全性。

关闭自动更新功能,通过手动或SSH方式更新。

WordPress 的更新服务器在国外,并且没有在国内开启加速服务,所以 WordPress 在后台检查更新的时候,可能因为各种原因无法顺畅连接上,然后一直卡着,造成 WordPress 后台有时很慢很慢。建议关闭 WordPress 后台和自动更新功能,通过手动或者SSH方式更新WordPress。

屏蔽站点Feed,防止文章被快速被采集。

WordPress Feed 主要用于阅读器使用,但是现在使用阅读器的用户越来越少,而 Feed 更多成为了一些垃圾站快速全文采集的方式,造成不必要的资源消耗,建议关闭站点 Feed。

屏蔽站点管理员邮箱定期验证功能。

WordPress 会在每六个月管理员再次登录之后,会看到站点管理员的邮箱地址验证界面,这是担心管理员的邮箱不再使用,引起一些安全的问题,让管理员再次确认,如果不会这方面的问题,觉得没有必要,可以屏蔽邮箱验证。

转换功能

屏蔽Emoji转换成图片功能,直接使用Emoji。

WordPress 使用图片来渲染Emoji表情文字,但是渲染图片经常打不开,并且现在主流浏览器都已经支持Emoji文字,并且现在绝大部分服务器的 MySQL 数据库(5.5版本之后)都支持 utf8mb4 编码格式,所以无需将 Emoji 转换成 HTML 实体进行存储了,直接存储速度更快,节省了实体转换的时间消耗。建议屏蔽 Emoji 功能。

屏蔽字符转换成格式化的HTML实体功能。

WordPress会将一些纯文本字符转换成格式化的 HTML 实体,但是这些转换并不适合中文环境,所以我们最好去掉这些字符转换,也能节约这些转换所消耗的时间。

屏蔽WordPress大小写修正,自行决定如何书写。

WordPress 默认会把 Wordpress 这样的写法转换成 WordPress,就是中间的 P 会变成大写。如果熟悉 WordPress 的用户,都会正确 WordPress 模式书写,所以从效率优先考虑,没有必要浪费时间在这个转换上面,一样一键移除。

后台功能

后台功能移除为欧洲通用数据保护条例生成的页面。

GDPR 是欧洲的通用数据保护条例,它制定了非常严格的隐私条例,WordPress为了适应该法律,在后台设置很多隐私功能,如果只是在国内运营博客,可以移除后台隐私相关的页面。

移除仪表盘的「WordPress 活动及新闻」。

WordPress 后台仪表盘页面会有「WordPress 活动及新闻」功能,但是大部分都是英文文章,如果你不想出现,可以一键移除。

移除后台界面右上角的帮助和选项。

WordPress 后台很多页面右上角,比如后台文章列表页面,都会有「显示选项」和「帮助」这两个按钮,一个是用来显示和设置该页面的选项,一个是用来获取该页面的帮助信息:

此图片的alt属性为空;文件名为1646055773-image.png

首先这两个按钮都在右上角,很多用户都不会特别注意,以至于自己操作了都忘记了,并且帮助文档对用户也帮助不大,建议两个都移除。

页面功能

页面功能移除页面头部版本号和服务发现标签代码。

WordPress 会在页面的头部输出版权信息和其他服务发现代码,版权信息代码会让用户知道你的目前运行的 WordPress 的版本,而服务发现代码则可以说明你的博客支持哪些服务。

这些代码在前台反而会引起一些安全的问题,最好一键去掉。

移除工具栏和后台个人资料中工具栏相关选项。

一般不建议在网站前台显示 WordPress 工具栏,所以可以一键移除。

嵌入功能

嵌入功能禁用Auto Embeds功能,加快页面解析速度。

Auto Embeds协议让你插入一个视频网站或者图片分享网站的链接,这个链接里面含有的视频或者图片就自动显示出来,但是该功能支持的网站都是国外的,如果运营的是中文博客,建议禁用 Auto Embeds 功能,加快页面解析速度。

屏蔽嵌入其他WordPress文章的Embed功能。

文章Embed功能让你可以在WordPress站点用嵌入的方式插入本站或者其他站点的WordPress文章。如果你不需要,可以屏蔽文章Embed功能。

古腾堡编辑器

屏蔽Gutenberg编辑器,换回经典编辑器。

WordPress 5.0 发布带来的 Gutenberg 编辑器,也叫区块编辑器,这个编辑器很酷,但是很多人不习惯,还是喜欢原来简简单单的编辑,name可以屏蔽 Gutenberg。

屏蔽小工具区块编辑器模式,切换回经典模式。

同样主题的小工具功能,新版 WordPress 也同样使用区块编辑器模式,你如果习惯了原来的经典模式,也可以一键屏蔽,切换回经典模式。

增强优化

增强优化主要将 WordPress 一些资源加速优化,并且添加一些常用的小功能,目前有以下的功能:

前端公共库

我们常用的 JS 库,比如 jQuery / Underscore 这些,网上都有提供免费的公共库,这里提供几个常用的前端公共库,可以根据自己的喜欢选择。

Google 字体加速服务

Google 字体很好用,很方便,WordPress 很多主题也使用了 Google 字体,但是 Google 在线字体在国内的速度不是很快,甚至有时候还无法打开,这也是 WordPress 有时候在国内速度不够快的原因。

WPJAM Basic 可以让选择第三方 Google 字体字体加速服务,也可以自定义输入加速服务地址:

详细介绍:使用 Google 字体加速服务,加快 WordPress 打开速度

Gravatar 加速服务

Gravatar 部分 CDN 服务器在国内访问困难,出现头像无法显示的问题,而 WordPress 后台或者评论页有时候默认加载 Gravatar 头像图片的,这样就可能造成页面卡死的情况。

WPJAM Basic 可以让选择第三方 Gravatar 镜像加速服务,也可以自定义输入加速服务地址:

详细介绍:使用 Gravatar 加速服务,加快 WordPress 打开速度

Frame 嵌入

WPJAM Basic 可以让你直接在后台设置 Frame 嵌入,避免点击劫持,增强网站的安全性:

详细介绍:如何防止 WordPress 页面被 Frame 嵌入

分类链接简化

去掉 category 的分类目录和 WordPress 的页面的 URL,这两种页面的页面rewrite 规则是不是一样的,那么我们可以直接使用页面的 rewrite 规则来处理了。

WPJAM Basic 还额外增加一个选项,如果博客自定义了其他的自定义分类模式,可以选择设置哪个分类模式应用该功能:

详细介绍:去掉 WordPress 分类目录 URL 中的 category 最佳方法

图片时间戳

如果长期上传的图片名字都是 1.jpg 的话,那么上传一张图,会造成数据库进行几十到上百次的 SQL 查询,应该在上传的时候把图片的名字更改了,给图片的名字加多一个时间戳,这样就能几乎保证图片名字不可能重复了:

详细介绍:如果经常在 WordPress 上传同名的图片,最好开启这个选项

之前还有一些优化增强功能,我因为各种原因去除或者移到别的插件。

  • 搜索结果快速跳转:提高搜索效率,当搜索结果只有一篇时直接重定向到文章该功能已经移到搜索优化插件。
  • 禁止admin用户名:使用admin作为用户名是最大的安全漏洞,建议禁止使用 admin 用户名尝试登录 WordPress,提高网站的安全性。很多人因为用户名是 admin,又开启这个功能,然后站点登录不了,然后说 WPJAM Basic 的问题,忍疼删除该功能,大家记得不要设置 admin 的用户名。
  • 前台不加载语言包:WordPress加载语言包是需要花费 0.1-0.5 秒不等的时间,如果对性能要求极致,可以前台不加载语言包,但是要把主题文件中的描述改成中文。很多人设置了该功能,前台出现英文,说WPJAM Basic 乱改,所以继续忍疼删除该功能。
  • 媒体文件默认链接到:无/媒体文件/附件页面,该功能已经迁移到图片集插件。

用 WP Simple EXIF 让博客图片展示更多细节信息

图片的 EXIF(Exchangeable Image File Format)信息,是数码相机或手机在拍摄照片时自动记录的参数数据,包括拍摄时间、设备型号、光圈、快门速度、ISO 感光度、焦距、曝光补偿等。通过在博客上展示图片的 EXIF 信息,不仅可以为摄影爱好者提供参考,帮助他们了解拍摄设置与效果之间的关系,也能提升内容的专业性和可信度,让读者更深入地了解作品背后的技术细节与创作思路。

2022.05.01 西昌之行-20
2022 年 5.1 西昌烧烤

Kevin's Space 博客就是通过调用七牛云的图片处理接口,在图片页面中直接展示了拍摄的 EXIF 信息(如上图所示),实现了性能与功能的结合。如果你的网站图片尚未接入 CDN 或对象存储服务,也不必担心,可以尝试使用本文介绍的插件 WP Simple EXIF,它能自动读取并展示图片的基本拍摄参数,操作简..... [ 阅读全文 ]


原文链接: https://www.shephe.com/website/wp-simple-exif/
版权声明: Kevin's Space 版权所有,转载请用明链标明本文地址
本站相关: 随机文章 | 站长微博 | 关于本站 | 联系站长 | 捐助作者

利用 Live Photos Block 插件给博客添加实况照片

苹果的实况照片(Live Photos)功能能够捕捉照片前后各 1.5 秒的视频,为静态图片赋予生动感。而如果你想在 WordPress 博客中也展示这样的视觉效果,现在可以通过 Live Photos Block 插件 来轻松实现。

这个插件实现简单,加载轻巧,效果还算不错,适合用于图片故事类博客或日常记录。我在果果日记博客的测试中,体验总体良好。不过,它仍有一定优化空间,比如可进一步避免脚本重复加载,并让脚本仅在区块真正启用时才加载,等等。当然,这些都可以通过简单修改代码来实现,可以自己动手优化一下。

1. WordPress-LivePhotos 插件简介

Live Photos Block 插件是由博友 万事屋日记 编写并开源的 Gutenberg 区块扩展,允许用户在编辑器中插入一个自定义区块,以模拟苹果实况照片的播放效果。

你可以在区块中上传任意一张图片(如 JPG、PNG)和一个短视频(如 MOV、MP4),插件会自动构造一个前端播放器,让这对照片+视频组合表现出如 Live Photo 般的效果。

插件引用了 Apple 官方的 JS,前台效果可以说一毛一样。但它并不需要照片和视频具备特定格式、长度或编码要求——只要浏览器支持,插件都能正常工作。

2. 实况照片格..... [ 阅读全文 ]

原文链接: https://www.shephe.com/website/wordpress-live-photos-block-plugin/
版权声明: Kevin's Space 版权所有,转载请用明链标明本文地址
本站相关: 随机文章 | 站长微博 | 关于本站 | 联系站长 | 捐助作者

一点点展开我的 macOS

Core

Alfred 是我的应用启动器,感兴趣的朋友可参考配置:2024 Alfred 5 基础设置和 Worklfow 推荐Shortcutie 可以利用私有 API 为 Shortcuts 提供丰富的系统级扩展动作,配合 Alfred 使用更佳,我最常用的是「通知清理」。

我长期订阅 Setapp,这是一个软件打包订阅服务,所有在该服务内软件后会加一个星号*

DEVONthink 是资料管理的核心,大部分内容使用 Typora 编辑(PicGO 为图床),其他资料的格式主要为 PDF、Doc、Markdown 和 Html。浏览器插件 Obsidian Web Clipper(AI 总结) 和 SingleFile(HTML) 可以快速收集信息,然后使用 Hazel 自动转入 DEVONthink 中。Obsidian 自带的 Html 剪藏工具不是很好用。数据库中尽量储存复述和重新理解过的资料,少储存源文件,这样能减少数据库的大小,也让内容更聚焦。Apple mail 中的邮件可以直接拖拽到 DEVONthink Inbox 中归档。数据库通过 Dropbox 同步。

Voicenotes 用于记录语音笔记,自动转文字并总结,并建立数据库,易用且好用。我是早期买断制用户,现在好像只能订阅。东西是好东西,但性价比没以前那么高。喜欢语音笔记的朋友可以试试这种用 shortcuts 实现的方式: 语音iOS 音频转文字并导入 Obsidian

我使用 PDF Expert 阅读 PDF 文件,MarginNote* 阅读需要记笔记的 epub 文件,高亮和笔记可直接导入 DEVONthink。不需要笔记的 epub,则用 Calibre 阅读。

Apple Calender 和 Things 3 用于日程和项目管理,配合 Dato* 在 Menu bar 中快速查看信息。Things 中的项目可以直接拖拽到 Apple calendar 中。

进入工作状态后,我会用 QSpace 替代 Finder 管理项目,用 Bookends 管理文献。以前一直用 Zotero,DEVONthink 4.0 加强了和 Bookends 的联动,我便转而尝试了它。Setapp 里虽然包括了 Commaner One,但界面稍微臃肿了一些,没有 QSpace 美观舒适。

使用 Sublime Text 查看代码,用 RStudio 和 VSCode 进行数据分析。TablePlus* 和 Delimited 可以更方便的查看数据。

根据老板的喜好选择论文撰写软件,以前用 Microsoft word,目前则使用 Texifier

使用 Librewolf 一年多,还是回到了Chromium 内核。目前,Brave 是我的主力浏览器,从浏览器级别构建广告拦截功能,目前不依赖 Manifest V3,使用 1Password 管理密码。作为 Kagi 的忠实用户,我一直对 Orion Browser 有很高期待,每隔半年会试用一次,但至今没优化到能做主力浏览器的程度。近期最喜欢的浏览器插件是 Sider,结合了 POE 的 AI 对话功能,和双语翻译、Youtube 字幕翻译、网页总结、PDF 翻译总结… 另外,Sider 挺适合 1-3 人合租,价格不错。

我习惯使用 RSS 订阅内容,FreshRSS 是我的 RSS 管理器。Reeder 则是我的阅读器,可以直接订阅 FreshRSS 中的内容。

WordPress 被用于搭建博客。每隔三个月,会用 SiteSucker 为博客做二次备份,能够异步下载网站的网页、图片、PDF、样式表等文件并重建站点目录结构。其他自托管服务可见这篇 Blog

Menu Bar

我使用 Bartender 管理 Menu Bar,将其折叠成三个层级,「常驻可见」、「隐藏」和「后台常驻」

常驻可见:

  • DEVONthink Extra:用于快速记录笔记。
  • Dropbox:云盘同步中枢。
  • Trickster*:可以查看近期使用的软件和文件,并支持查看 DEVONthink 内最近查看的文件,和 Alfred 联动。
  • LookAway:非常漂亮的休息提醒 App,有干眼和坐姿提醒,能设置一些场景下不启用,如游戏、视频和会议。各方面都比我之前使用的 Time Out* 要好些。
  • Dato*:快速查看日历信息,有全屏的会议提醒。
  • Squirrel: 输入法。
  • DisplayBuddy*:研究所的电脑是 1080P 的,这个软件能启用 HiDPI 分辨率,略微提升显示效果。
  • AIDente Pro*:电池健康管理工具。Apple 官方的电池管理工具被我隐藏了。
  • Alcove:最接近 macOS 原生的动态岛功能,简单舒适,没有多余的功能。
  • One Switch*(偶尔):仅使用它的「屏幕键盘清洁模式」。
  • 如果想保持屏幕常亮,会使用 Lungo*。Amphetamine 也不错,但我更喜欢咖啡图标。
  • Gestimer 2(偶尔):交互很舒服的番茄钟应用,通过拖拽设定时间。我不是番茄钟的重度用户,仅心情好的时候,会用一段时间。

隐藏(点击 menu bar 可显示):

  • Bettermouse:用于替代罗技的鼠标管理软件,兼容我目前使用的两款鼠标,可设置快捷键。
  • PicGO:图床工具,接入 Typora。
  • Copy ‘Em:非常棒的剪切板软件,交互合理且流畅,工作中需要的小功能它基本都有,细节很多。
  • Supercharge*:系统增强工具,提供数十种可选功能,用户可按需开启,无需额外脚本或插件。
  • MagicQuit:自动关闭长时间未使用过的软件。
  • 1Password:交互体验最好的密码管理软件。
  • PopClip*:选中文本即显工具条,可以快速检索和翻译内容。安装插件后,只要能选中文本的内容,都可以剪藏到 DEVONthink。
  • ScreenMemory:通过定期截屏,保留用户的操作记录。与 Rewind 有一些相似,交互没有 Rewind 舒适,但功能够用,价格实惠。

后台常驻(完全隐藏):

  • Mission Control Plus*:为 Mission Control 设计的增强工具。
  • Hazel:完成各种自动化文件管理,将文字自动化的导入 Devonthink。
  • Codepiper:自动复制短信中的验证码。不要买 App store 版,功能不全。
  • Bob:macOS 上现阶段体验最好的翻译 & OCR 软件。
  • CleanShot X*:截图软件。
  • Magnet:窗口管理器。
  • Shareful:优化系统共享菜单。
  • iPreview:增强 macOS 的 Quick Look 浏览功能。
  • Mounty:将 NTFS 分区重新挂载为读写模式,实现在 macOS 下对 NTFS 卷的写入支持。
  • Key Maestro:大的macOS自动化工具,很多 Supercharge 的功能都可以用它实现。
  • New File Menu:优化 Finder 菜单栏,快速创建新文件。
  • OpenInTerminal:允许用户从 Finder 一键在终端或编辑器中打开当前文件夹或文件,无需手动导航。

其他

线上会议之前,我习惯用 Hand Mirror 检查一下摄像头状态。会议中,Presentify 能帮助我在屏幕上做标注,KeyCastr 则能显示实时使用的按键。

比较简单的思维导图,会用 MindNode* 绘制,复杂的则使用 Kinopio

BetterZip* 是我最喜欢的压缩文件管理器,它可以在不解压缩的情况下查看压缩文件的内容。

Clean My Mac*:垃圾清理、恶意软件扫描、应用管理… 确实比 OnyX 体验更好,但如果不在 Setapp 中我也不会购买。

FoxTrot Search:很好用的本地全文检索工具。

Chatwise 是我觉得目前最好用的第三方 AI 聊天软件,功能添加的很克制,没有变的很臃肿。另外,我最近尝试使用指纹浏览器(AdsPower),拼车订阅 ChatGPT Pro,效果还不错,能畅用 Deep Research 和 o3。

Renamer* 是批量重命名软件,稳定,清晰。

最近开始用 Mela 记录菜谱,用 Tripsy* 规划旅行计划。

Darkroom:不知不觉用了 10 年的修图软件,Snapseed 之后最喜欢的一个。

Picture View:一款轻巧快速的 macOS 图片浏览应用。 体积小巧,方便快速的查看图片,不产生缓存,适合作为默认看图应用。

我使用 Squash* 和 PDF Squeezer* 压缩图片和 PDF 文件。

Permute* 转换音频图片格式,用 Downie* 下载视频,使用 Elmedia Player* 观看视频。

Affinity 系列软件:制图三件套,便宜管饱。

Steam:最近喜欢玩电脑上的桌游,比如展翅翱翔、猫与花毯等。还因为买二手桌游在英国认识了新朋友。

Spotify:听音乐,最近很喜欢这四张专辑。

WordPress 6.8 发布,速度更快、防护更强、使用更顺手!

WordPress 6.8 正式版发布了,按照 WordPress 官方说法,这是一个精雕细琢的版本,对日常使用的工具进行了全面的打磨和升级,让你的网站运行更快、防护更强、使用更顺手

样式手册全面优化

样式手册(Style Book)采用结构化布局设计,界面更加清爽直观,通过清晰的标签,让管理员可以轻松管理全站的颜色、字体等样式设置。

特别值得一提的是,现在样式手册还兼容经典主题,只要主题包含 editor-styles.css 文件或 theme.json 配置文件,就能在「外观」>「设计」中使用这一功能,在编辑 CSS 或使用定制器时,所有样式更改都能实时预览,让设计过程更加直观高效。

编辑器改进

数据视图(Data Views)的选项展示更加清晰明了,现在可以轻松地从查询循环中排除置顶文章。此外,编辑器还包含了70多处细节优化,从内容排版到最终发布,整个创作流程都变得更加流畅自然。


极速预加载技术

WordPress 6.8 引入了极速预加载技术(Speculative Loading),它能够在用户鼠标悬停或点击链接时,会自动预加载下一页内容,使页面跳转几乎达到瞬时完成的效果。开发者还可以通过插件或自定义代码来调整预加载策略,最后这项功能仅在现代浏览器中生效,对老旧浏览器则完全无影响。

更强的哈希算法

WordPress 6.8采用了更强大的bcrypt哈希算法,这种算法算法需要消耗大量计算资源才能破解,使得密码保护更加牢不可破。此外所有安全升级都是自动完成的,管理员无需进行任何额外操作,系统就会自动将现有密码迁移到新的加密方式。

性能提升

在无障碍体验方面,WordPress 6.8 做了 100 多项修复和增强,涵盖 WordPress 体验的方方面面,修复了所有内置的主题,改进了导航菜单管理、自定义工具,并简化了标签功能等,并且针对区块编辑器的块、数据视图及其整体用户体验也进行了 70 多项改进。

在性能方面,WordPress 6.8 也做了一系列的修复和增强,提升了从编辑到浏览的各项功能,除了前面预测加载之外,还特别优化了区块编辑器、块类型注册和查询缓存,朝着任何交互的等待时间都不会超过 50 毫秒这个目前前进。

数据库查询性能也得到显著提升,特别是优化了WP_Query类的缓存键生成机制,有效降低了高并发访问时的服务器负载,让网站在流量激增时也能保持稳定运行。

WPJAM Basic 昨天也更新到了 6.7.6 版本,我也会很快同步更新到 6.8 版本,并且我会根据 WordPress 6.8 持续更新,注重兼容性和性能优化,如有使用问题,也欢迎反馈到知识星球。

WordPress 官方推出了 AI 建站工具,让你分分钟就打造美观网站

WordPress 在其官方托管 SasS 平台正式推出了一款全新的 AI 驱动网站构建器,这款工具可以在几分钟内为用户创建出功能齐全、外观美观的 WordPress 网站。用户只需通过聊天机器人输入相关提示,便可生成包括文本、布局和图像等在内的网站内容。

WordPress 官方推出的这款 AI 网站构建器操作异常简便,对技术背景几乎没有任何要求,用户可以告诉 AI 自己需要建立个人网站还是商业网站,并描述希望的页面元素,如标题外观、配色方案等,AI 系统便会根据这些指令自动生成网站的基本框架。

越具体的初始提示将带来更理想的结果,在生成网站时,聊天机器人会询问一些关键信息,例如公司名称和位置。生成完成后,网站将包含 AI 生成的标题、图片和文本。

这一功能特别适用于企业家、自由职业者、博主等需要快速建立专业网络形象的群体,值得注意的是,虽然这款 AI 网站构建器功能强大,但目前仍主要适用于生成简单的页面。对于需要更复杂集成的网站,如电子商务商店等,暂时还无法直接通过该工具创建。

为了让用户充分试用这一新功能,WordPress.com 也为用户提供了 30 次免费提示额度,对于开发者,还可以将 AI 生成的网页切换回手动编辑的模式,自己再次修改。

一旦网站构建完成,用户可以将其转移到 WordPress.com 的托管服务上,继续手动编辑或重新返回 AI 构建器进行调整。而使用 WordPress.com 的托管计划,费用起价为每月18美元。另外需要注意的是,这个工具目前仅适用于新创建的站点,已经存在的网站则无法使用。

不过这项服务目前仅限于 WordPress 官方运营的 SaaS 平台 WordPress.com,对于自己托管的 WordPress 独立站点,暂时还没有提供相应的插件。不知道 WordPress 官方之后是否将其开源。

地址:https://wordpress.com/ai-website-builder/

使用 OPCache 字节码缓存让 WordPress PHP 执行效率提升 300%

前面我们介绍了使用 Memcached 内存缓存来实现 WordPress 站点秒开,其实 WordPress 加速还有个一个大招就是使用 OPcache 字节码缓存来提升 PHP 的执行效率,经测试最高可达提升 300%。

这么强吗?那今天就介绍一下 OPCache!

OPCache 是什么?

OPCache 是 PHP 的官方推出的字节码缓存器(Zend OPcache),通过将 PHP 脚本预编译的字节码存储在共享内存中来提升 PHP 的性能,在 PHP 5.5.0 及后续版本中已经绑定了 OPcache 扩展,

 缓存预编译字节码的好处就是避免重复解析和编译脚本,省去了每次加载和解析 PHP 脚本的开销,那么这一过程是如何实现的呢?

缓存字节码:PHP 脚本首次被执行的时候,Zend 引擎会将代码转换为 ​抽象语法树(AST)​,再编译为 ​字节码(opcodes)​,OPCache 扩展会拦截这一过程,将字节码存储在共享内存中,后续请求直接调用内存中的字节码,跳过重复编译的过程。

内存共享机制:OPCache 使用共享内存(mmap 或 shm)存储字节码,所有 PHP 进程(如 PHP-FPM 子进程)共享同一份缓存,降低了内存的占用,相比其他方案,OPCache 与 PHP 内核深度集成,效率更高。

所以 OPCache 在下面几个关键点提升了性能:

  • CPU 节省:避免重复编译,降低 CPU 负载(尤其是 WordPress 这类动态脚本)。
  • I/O 优化:减少磁盘读取 .php 文件的次数(对机械硬盘效果显著)。
  • 内存效率:字节码比原始 PHP 代码更紧凑,共享内存减少整体内存占用。

所以对于 WordPress 来说,就特别需要 OPCache 了,因为 WordPress 每个页面请求都会加载大量 PHP 文件(主题、插件、核心),这样未优化的 WordPress 在流量高峰时容易因 PHP 编译拖慢响应。

如何启用 OPCache

PHP PHP 5.5.0 及后续版本默认包含 OPCache,OPcache 只能编译为共享扩展,如果你使用 --disable-all 参数 禁用了默认扩展的构建, 那么必须使用 --enable-opcache 选项来开启 OPcache。

编译之后,就可以使用 zend_extension 指令来将 OPcache 扩展加载到 PHP 中。在非 Windows 平台使用 zend_extension=/full/path/to/opcache.so, Windows 平台使用 zend_extension=C:\path\to\php_opcache.dll

汇总一下在 php.ini 中添加下面代码:

zend_extension=opcache.so ; Linux
zend_extension=opcache.dll ; Windows
opcache.enable=1

针对 WordPress,可以加入这些专属优化配置:

[opcache]
opcache.enable=1
opcache.memory_consumption=256      ; WordPress 建议 ≥128MB
opcache.max_accelerated_files=10000 ; 覆盖 WordPress 核心 + 插件文件数
opcache.interned_strings_buffer=16  ; WordPress 大量重复字符串(如钩子名)
opcache.validate_timestamps=0       ; 生产环境关闭自动检查
opcache.revalidate_freq=0           ; 与 validate_timestamps=0 配合
opcache.save_comments=1             ; WordPress 依赖注释(如钩子文档)
opcache.enable_file_override=1      ; 覆盖 include/require 优化

安装好时候,如何检测验证安装成功了呢?

简单可以通过通过 phpinfo() 或命令行 php -v 查看是否加载。也可以在后台 「WPJAM」主菜单下「系统信息」子菜单中的「服务器」标签中「PHP 扩展」看到:OPCache:

当然最重要是「OPCache」标签页:

WPJAM Basic - 系统信息 - OPCache

这里也会罗列出 OPCache 的一些状态,比如已用内存和剩余内存,以及他们之间百分率,命中率和未命中率,以及他们之间百分率等等数据,还有相关的饼图。

生产环境一般建议关闭 validate_timestamps,避免频繁检查文件修改,文件有更新的时候通过手动重启 OPCache 或 PHP-FPM 来更新代码,也可以在上图中点击「刷新缓存」即可。

下面是一个简单 WordPress 站点在开启 OPCache 前后的性能对比:

场景未启用 OPCache启用 OPCache优化幅度
首页加载时间800ms300ms↓62.5%
后台管理页面1200ms500ms↓58.3%
并发请求(100 QPS)CPU 90%CPU 45%↓50%

所以可以看到启用 OPCache 最高接近 300% 的提升。

简单总结

PHP 代码使用 OPCache 之后,可以提高代码的执行效率,特别是 WordPress 这类文件比较多的 CMS 系统,所以在使用 Memcached 内存缓存来实现 WordPress 站点秒开之后,记得一定要开启 OPCache 来提速,另外 #WPJAM Basic# 也在 WordPress 集成了 OPCache 状态页面,可以看到 PHP 使用 OPCache 的状态。

在 WordPress 后台集成了标签选择器(tag-input)和多选选择器(mu-select)

使用过 #WPJAM Basic# 的同学都知道,WPJAM Basic 集成了多个字段组件,这些组件都是后台定义一下,然后前段就能够渲染,并且提交的时候也会根据类型进行验证和处理,反正就是我通过前后端双修的模式将字段设置这块做到了最简洁了。😁

比如多个输入框(类型:mu-text),在「CDN 加速」里的「扩展名」字段:

甚至可以无限重复的一组字段(类型:mu-fields),在「缩略图设置」里面的:「未设置缩略图是,获取特色图片顺序」字段:

还有设置多个图片(类型:mu-img),还是在「缩略图设置」里面的「默认缩略图」字段:

这些字段都是后端配置的,自动渲染生成的,不用再多写一行前段 JS 代码:

「扩展名」字段:

[
	'exts'	=> [
		'type'		=> 'mu-text',
		'button_text'	=> '添加扩展名',
		'direction'	=> 'row',
		'sortable'	=> false,
		'description'	=> '镜像到云存储的静态文件扩展名'
	]
]

「获取顺序」字段:

[
	'post_thumbnail_orders'	=> [
		'title'		=> '文章缩略图',
		'type'		=> 'mu-fields',
		'group'		=> true,
		'max_items'	=> 5,
		'before'	=> '首先使用文章特色图片,如未设置,将按照下面的顺序获取:<br />',
		'fields'	=> [
			'type'	=> ['type'=>'select',	'options'=>[
				''			=> '请选择来源',
				'first'		=> '第一张图',
				'post_meta'	=> [
					'label'		=> '自定义字段',
					'fields'	=> ['post_meta'=>['type'=>'text',	'class'=>'all-options',	'placeholder'=>'请输入自定义字段的 meta_key']]
				],
				'term'		=>[
					'label'		=> '分类缩略图',
					'show_if'	=> ['term_thumbnail_type', 'IN', ['img','image']],
					'fields'	=> ['taxonomy'=>['options'=>[''=>'请选择分类模式']+$tax_options]]
				]
			]]
		]
	]
]

「默认缩略图」字段:

[
	'default'	=> [
		'title'		=> '默认缩略图',
		'type'		=> 'mu-img',
		'item_type'	=>'url'
	]
]

就是这样配置一下就好,剩下的程序会自动处理,厉害吧!这就是我前后端兼修的能力。😂

但是还是有些地方需要一些主键,比如在列表筛选的时候,用到上面这些多输入框的时候,界面就有点挤了,所以就有了「标签选择器」和「多选选择器」这两个字段组件。

「标签选择器」这个其实和上面的多输入框很类似,只是它每输入一个之后,就变成类似标签的样式:

支持自动完成,拖动排序,删除,按退格键(Backspace)不仅可以删除输入的文字,也可以删除前面的标签(为了防止误删,需要快速按两次)。这个可能更多的是样式的改进,但是更重要的是界面的节省。

使用也很简单,首先它的类型是:tag-inpug

[
	'tags'	=> [
		'type'			=> 'tag-input',
		'data_type'		=> 'taxonomy',	// 数据类型
		'taxonomy'		=> 'post_tag',	// 文章标签
		'min_items'		=> 2,	// 至少 2 个
		'max_items'		=> 3,	// 最多 3 个
		'unique_items'	=> true // 不能重复,已选择的项目不会再次出现
	]
]

有时候被选择的项目数量是有限的,比如分类,但是要多选,如果使用 select 的话,只能单选,当然 select 有个 multiple 属性,但是显示的效果是这样的:

通过按着 CTRL 或者 Shift 然后点击进行多选,怎么用,怎么难受,并且高度太高,不好排版,如果强制设置为一行,都不知道选择了什么。

所以我们做了「多选选择器」这个组件,它默认显示选中的选项,通过逗号分割开:

点击「下拉选择框」(其实这个是个按钮,通过 CSS 改造和下拉选择框很类似)就可以看到所有选项,并且所有选项前面都有个复选框:

勾选之后,就会显示到上面「下拉选择框」中,并且同样也支持设置至少和最多的数量,选好之后点击人地方,这个下拉复选框就隐藏了,这样就能大大节省界面:

使用也很简单,首先它的类型是:mu-select,其实把上面标签选择器的代码复制下来,改下类型就好了

[
	'tags'	=> [
		'type'			=> 'mu-select',
		'data_type'		=> 'taxonomy',	// 数据类型
		'taxonomy'		=> 'category',	// 文章分类
		'min_items'		=> 2,	// 至少 2 个
		'max_items'		=> 3,	// 最多 3 个
	]
]

如果你基于 WPJAM Basic 进行二次开发,那么这两个字段组件可以帮到你很多。为了写这两个字段,我相当于又重修了一下 JavaScript 这门语言,还好现在有 DeepSeek,很多模棱两可的东西,都可以问题,然后也可以让它给到一些演示代码,然后在改就简单了很多。😁

在 WordPress 中如何优雅的使用全局变量

程序写多了,都会认同这条规则:在 WordPress 中,都尽量不要使用全局变量,其实任何 PHP 程序中都是这样的。为什么?先从简单介绍下全局变量开始。

什么是全局变量

全局变量是在 PHP 脚本的任何作用域中都可以访问的变量,主要包括以下几种形式:

超全局变量 (Superglobals)

PHP 预定义的全局数组,​无需使用 global 声明即可在任何作用域访问:

  • $_GET:HTTP GET 请求参数
  • $_POST:HTTP POST 请求参数
  • $_REQUEST:GET/POST/COOKIE 的合并数据
  • $_SESSION:会话数据
  • $_COOKIE:客户端 Cookie 数据
  • $_SERVER:服务器和执行环境信息
  • $_FILES:上传文件信息
  • $_ENV:环境变量
  • $GLOBALS:所有全局变量的引用集合

使用 global 关键字

在函数或方法内部通过 global 关键字访问全局变量:

$globalVar = 10;

function test() {
    global $globalVar;
    echo $globalVar; // 输出 10
}

$GLOBALS 数组

直接通过 $GLOBALS 访问全局变量:

$globalVar = 10;

function test() {
    echo $GLOBALS['globalVar']; // 输出 10
}

使用全局变量的问题

代码可维护性差

  • 隐式依赖:函数内部依赖全局变量会导致代码逻辑不透明,难以追踪数据来源。
  • 耦合度高:修改全局变量可能影响多个地方,引发难以调试的副作用。

作用域污染

  • 命名冲突:全局变量可能与其他变量或库中的变量同名,导致意外覆盖。
  • 生命周期不可控:全局变量在脚本结束前一直存在,可能占用不必要的内存。

并发和线程安全问题

  • 在并发环境(如多线程或异步任务)中,全局变量可能被多个线程同时修改,导致数据不一致。

测试困难

  • 全局状态使得单元测试难以隔离,测试用例之间可能互相影响。

安全隐患

  • 超全局变量(如 $_GET$_POST)未过滤时可能引发安全漏洞(如 SQL 注入、XSS)。

全局变量虽然方便,但过度使用会导致代码质量下降。应该遵循“最小作用域原则”和“单一职责原则”,能显著提升代码的可维护性和安全性。

在 WordPress 中正确使用全局变量

但是我们在代码中还是要使用一些全局变量,或者类似全局变量的变量,比如我在小程序中记录当前登录的用户的 openid:$weapp_openid。那么怎么办呢?

先上代码:

function wpjam_var($name, ...$args){
	static $vars;

	$vars	??= wpjam_parse_user_agent();	// 当前用户访问的环境信息

	if($args && (!isset($vars[$name]) || !is_closure($args[0]))){
		$value	= maybe_closure($args[0], $name);

		if(is_wp_error($value) || is_null($value)){
			return $value;
		}

		$vars[$name]	= $value;
	}

	return $vars[$name] ?? null;
}

我创建一个 wpjam_var 函数,这个函数创建一个静态变量 $vars,它是一个数组,所有全局要使用的变量都存到该数组中。

$weixin_openid	= '通过小程序插件获取';

// 存储变量
wpjam_var('weapp_openid', $weixin_openid);

然后在之后 $weapp_openid 可以通过以下方法获取:

// 获取变量
wpjam_var('weapp_openid');

它还支持闭包函数,比如我们可以将获取 $weapp_openid 包装成一个函数:

function weapp_get_current_openid(){
	return wpjam_var('weapp_openid', function(){
		$access_token	= wpjam_get_parameter('access_token');

		if(!$access_token){
			return new WP_Error('illegal_access_token', 'Access Token 为空!');
		}

		return WEAPP::get_openid_by_access_token($access_token);
	});
}

这样在之后的地方都可以使用 weapp_get_current_openid 获取 $weapp_openid。它的具体如何获取和实现,

最后再总结一下 wpjam_var 函数,它的第一个参数 $name 很简单,变量的名称,第二个参数分三种情况:

  1. 如果没有设置,就返回该变量的值,没有设置则为 null
  2. 如果是简单的值(非闭包),则设置并返回该值。
  3. 如果是闭包函数,如设置 $name 的变量,则返回它的值,如果未设置,通过调用闭包函数获得值,然后设置并返回。

wpjam_var 函数的好处

1. 作用域隔离,避免污染

  • 数据封闭性
    示例中的 $weapp_openid 通过 wpjam_var 存储,​仅限函数内部访问,外部无法直接修改,彻底规避全局变量的命名冲突和意外覆盖。
  • 安全访问
    所有操作必须通过 wpjam_var 函数(如 weapp_get_current_openid()),​天然实现私有性,避免全局污染。敏感数据(如 access_token)的获取逻辑封装在闭包内,防止外部直接暴露。

2. 性能优化(延迟初始化)​

  • 按需加载
    示例中 $weapp_openid 的闭包函数可能涉及数据库查询,首次调用时执行一次并缓存结果,后续直接复用,避免重复计算。
  • 内存级访问速度
    静态变量存储在内存中,访问速度远超全局变量或文件读取。同一请求中多次调用 weapp_get_current_openid() 时,​性能提升显著​(如减少冗余 API 调用)。

3. 灵活的数据管理

  • 动态惰性计算
    通过闭包(如示例中的匿名函数)实现“按需生成数据”,仅在未缓存时触发逻辑,资源利用率更高。
  • 错误隔离与健壮性
    检测 WP_Error 或 null(如 access_token 为空时返回错误),​避免污染缓存,确保后续逻辑仅处理有效数据。

4. 可维护性与扩展性

  • 逻辑集中管理
    weapp_get_current_openid() 作为唯一入口,​集中维护 openid 的获取规则,修改生成逻辑(如更换认证方式)只需调整闭包,无需全局搜索。
  • 易于扩展功能
    支持快速添加类型检查、日志记录或缓存失效机制(如 reset 参数),​无需改动外部调用代码,扩展成本低。
  • 代码清晰度
    数据定义($weapp_openid)与业务逻辑(闭包)分离,​提升可读性,降低维护难度。

5. 安全性提升

  • 输入验证与过滤
    示例中闭包内对 access_token 做非空校验,​拦截非法输入​(如空值或无效格式),防止无效请求进入下游逻辑。
  • 风险隔离
    敏感操作(如 get_openid_by_access_token())封装在闭包中,​统一实施安全策略​(如加密、超时控制),避免全局变量直接暴露的风险。

6. 适用场景

  • 高频请求数据
    如示例中的 openid,适用于同一请求内多次访问的场景(如用户信息、权限校验)。
  • 动态配置管理
    根据环境加载不同配置(如开发/生产环境参数),通过闭包实现按需加载。
  • 共享资源访问
    替代单例模式,简化数据库连接池等共享资源的管理。

上面这段话,是 deepseek 帮我总结的,果然比我吹的好,但是也说明这个函数实现的好,哈哈!在最新版的 #WPJAM Basic# 即可直接使用。

CloudCone - 中盘 VPS 清仓促销活动 14美元/年起!

CloudCone 上线了中盘 VPS 清仓活动,近期有入门美国VPS或是 存储需求的倒是不错的选择~

他家所有的机器和 RN(RackNerd)的DC02地区的VPS都在MC机房,在普通路线VPS里面表现比较稳定。

清仓套餐详情

特惠商品,售完即止!

名称配置流量价格位置链接
CS-Q1-25-VPS-12核/1G/60G2T/月14 美元/年美国 洛杉矶https://app.cloudcone.com.cn/vps/378/create?ref=11351&token=cs-q1-25-vps-1
CS-Q1-25-VPS-23核/2G/120G3T/月24 美元/年美国 洛杉矶https://app.cloudcone.com.cn/vps/379/create?ref=11351&token=cs-q1-25-vps-2
CS-Q1-25-VPS-36核/4G/240G4T/月44 美元/年美国 洛杉矶https://app.cloudcone.com.cn/vps/380/create?ref=11351&token=cs-q1-25-vps-3

简单测试

这次 CloudCone - 中盘 VPS 清仓使用都是 SSD 缓存硬盘,而不是纯 SSD 硬盘。

SSD缓存硬盘 是通过 SSD 固态阵列对 HDD 机械硬盘进行加速的技术;与纯 SSD 硬盘相比,其 IO 性能稍逊一筹,但结合了机械硬盘的大容量优势,以下是性能对比:

纯SSD硬盘:

------------------磁盘dd读写测试--感谢lemonbench开源--------------------
 -> 磁盘IO测试中 (4K Block/1M Block, Direct Mode)
 测试操作               写速度                                  读速度
 100MB-4K Block         18.5 MB/s (4509 IOPS, 5.68s)            48.9 MB/s (11933 IOPS, 2.15s)
 1GB-1M Block           497 MB/s (474 IOPS, 2.11s)              2.3 GB/s (2195 IOPS, 0.46s)
---------------------磁盘fio读写测试--感谢yabs开源----------------------
Block Size | 4k            (IOPS) | 64k           (IOPS)
  ------   | ---            ----  | ----           ---- 
Read       | 125.94 MB/s  (31.4k) | 430.73 MB/s   (6.7k)
Write      | 126.28 MB/s  (31.5k) | 433.00 MB/s   (6.7k)
Total      | 252.22 MB/s  (63.0k) | 863.73 MB/s  (13.4k)
           |                      |                     
Block Size | 512k          (IOPS) | 1m            (IOPS)
  ------   | ---            ----  | ----           ---- 
Read       | 746.93 MB/s   (1.4k) | 973.88 MB/s    (951)
Write      | 786.62 MB/s   (1.5k) | 1.03 GB/s     (1.0k)
Total      | 1.53 GB/s     (2.9k) | 2.01 GB/s     (1.9k)

SSD缓存硬盘:

------------------磁盘dd读写测试--感谢lemonbench开源--------------------
 -> 磁盘IO测试中 (4K Block/1M Block, Direct Mode)
 测试操作		写速度					读速度
 100MB-4K Block		14.6 MB/s (3568 IOPS, 7.17s)		41.3 MB/s (10078 IOPS, 2.54s)
 1GB-1M Block		462 MB/s (441 IOPS, 2.27s)		2.8 GB/s (2708 IOPS, 0.37s)
---------------------磁盘fio读写测试--感谢yabs开源----------------------
Block Size | 4k            (IOPS) | 64k           (IOPS)
  ------   | ---            ----  | ----           ---- 
Read       | 17.05 MB/s    (4.2k) | 338.89 MB/s   (5.2k)
Write      | 17.05 MB/s    (4.2k) | 340.67 MB/s   (5.3k)
Total      | 34.11 MB/s    (8.5k) | 679.56 MB/s  (10.6k)
           |                      |                     
Block Size | 512k          (IOPS) | 1m            (IOPS)
  ------   | ---            ----  | ----           ---- 
Read       | 341.56 MB/s    (667) | 295.25 MB/s    (288)
Write      | 359.70 MB/s    (702) | 314.91 MB/s    (307)
Total      | 701.27 MB/s   (1.3k) | 610.16 MB/s    (595)

IO 逊色纯固态阵列硬盘,但优于机械盘,但是提供了大容量。

磁盘外的测评可看之前的文章:CloudCone 7 周年促销,推出多款高性价比 VPS

配置链接
2核/1G/60Ghttps://app.cloudcone.com.cn/vps/378/create?ref=11351&token=cs-q1-25-vps-1
3核/2G/120Ghttps://app.cloudcone.com.cn/vps/379/create?ref=11351&token=cs-q1-25-vps-2
6核/4G/240Ghttps://app.cloudcone.com.cn/vps/380/create?ref=11351&token=cs-q1-25-vps-3

同台服务器上多个 WordPress 站点如何使用同个 Memcached?

前面我们介绍了「使用 Memcached 内存缓存来实现 WordPress 站点秒开」,很多用户都开始使用 Memcached 来提高 WordPress 站点速度,但是使用的时候碰到第一个或者说最多的问题就是,同台服务器上多个 WordPress 网站怎么同时使用 Memcached?

站点间数据互串

如果同时将 #WPJAM Basic# 插件 template 目录下的 object-cache.php 文件复制到同个服务器上多个 WordPress 站点的 wp-content 目录下来同时开启 Memcached 缓存,可能会出现这样的问题:

访问一个网站会跳转到另外一个网站,也就是说数据会串了。

这是怎么回事呢?这是因为 object-cache.php 默认是使用 WordPress 的表前缀($table_prefix区分不同站点在内存中的缓存的

如果你在同个服务器多个 WordPress 网站的表前缀都相同,都是默认的 wp_,那么 object-cache.php 就无法区分是哪个站点了。

那么怎么解决呢?

怎么同时使用 Memcached

定位了问题,那么就非常好解决,有两个解决方法:

1. 修改表前缀,让不同的 WordPress 博客使用不同的表前缀。我开发了一个 WordPress 数据库表前缀修改器,一键生成修改数据库表前缀所需的SQL,让你在 WordPress 修改表前缀之后能够更加方便全站修改。

2. 如果修改表前缀不方便,我还提供了 WP_CACHE_KEY_SALT 这个缓存 key 盐值的常量,你只需要在不同站点的 wp-config.php 文件定义不同的 WP_CACHE_KEY_SALT 值即可

比如两个站点分别定义为:

define('WP_CACHE_KEY_SALT', 'site1');
define('WP_CACHE_KEY_SALT', 'site2');

如果设置了还不行,可能你的 object-cache.php 不是最新版,那就下载一下最新版的 WPJAM Basic 插件,然后将 wpjam-basic/template/ 目录下的 object-cache.php 文件复制到 wp-content 目录下。

如何设置 Memcache 服务器地址

此外还有一些用户服务器的设置,他们的 Memcached 的服务器地址不是默认的 127.0.0.1,或者它们使用的云服务器的 Memcached 服务,很多聪明的同学会自己修改 object-cache.php 中的 Memcached 服务器地址。

其实不用那么麻烦 #WPJAM Basic# 提供的 object-cache.php 支持自定义服务器地址的, 只要在 wp-config.php 文件填下如下代码,将相应的服务器地址和端口改成自己的即可:

global $memcached_servers;

$memcached_servers	= [
	[
		'127.0.0.1', // Memcached 服务器地址
		11211        // Memcached 服务器端口
	]
];

最后,关于在 WordPress 中使用 Memcached:

1. 使用 Memcached 内存缓存来实现 WordPress 站点秒开

2. Memcached 和 Redis 有什么区别,做缓存 WordPress 用哪个好?

3. WordPress 是如何缓存的?对象缓存(Object Cache)详细介绍和使用!


WPJAM Basic 插件已经集成了 Memcached,下载 WPJAM Basic 之后,将 wpjam-basic/template/ 目录下的 object-cache.php 文件复制到 wp-content 目录下即可。

preg_replace_callback 如果正则有问题,竟然不是返回原字符串,而是返回 null

#WPJAM Basic# 有个功能,就是在 WordPress 后台文章列表添加上文章特色图片,并且支持点击设置:

这个功能因为 WordPress 没有好的 Hook 使用,我是通过对最终生成的 HTML 实现正则替换实现的。

这个功能本来挺好的,然后有个用户说使用 WPJAM Basic 之后,说后台文章列表空白,经过我仔细的 Debug,原来他使用的标签太多了,使得 HTML 过于复杂,正则回溯次说过多,发生错误了。

原本我以为正则错就错了呗,最多就是正则替换不成功,功能没有,为啥还给我整成空白的呢?我仔细查了下 PHP 官方文档,原来 preg_replace_callback 函数的返回是这样的:

如果 subject 是一个数组, preg_replace_callback() 返回一个数组,其他情况返回字符串。错误发生时返回 null

厄,错误发生时返回 null,第一次知道,一下子无言以对,原来之前正则都是成功了,我都没有去处理错误的情况,真的是。

然后 preg_replace 也是一样的情况,错误发生时返回 null

所以我写了一个函数 wpjam_preg_replace,同时实现  preg_replace_callbackpreg_replace 的正则替换功能(它们的参数差不多,一个是回调,一个是替换的字符串),如果发生错误时,不是返回 null,而是返回原始 $subject

function wpjam_preg_replace($pattern, $replace, $subject, $limit=-1, &$count=null, $flags=0){
	if(is_closure($replace)){
		$result	= preg_replace_callback($pattern, $replace, $subject, $limit, $count, $flags);
	}else{
		$result	= preg_replace($pattern, $replace, $subject, $limit, $count);
	}

	if(is_null($result)){
		trigger_error(preg_last_error_msg());
		return $subject;
	}

	return $result;
}

如果发生了错误,并且在 log 中打印出具体的错误信息,方便查看原因,看看能不能优化正则什么的。这里有个限制,preg_replace_callback 的回调函数只能是闭包,因为同时要支持两个函数的原因,使用闭包比较容易判断。

有了这个函数之后,即使发生正则错误,至少还能显示页面,这也算是一种防御性编程(防御性编程是一种编程实践,旨在编写代码以抵御或处理潜在的错误和异常情况,以提高代码的健壮性和可靠性)。😆

微信公众号竟然防爬了,那就升级一下同步公众号文章到博客的 WordPress 插件「WPJAM GrabMP」

微信公众号竟然升级系统,给他的公众号文章页面加上了防爬功能,现在如果没有做任何处理直接使用 wp_remote_get 获取自己公众号的文章页,得到是如下的页面:

我简单试了一下,给 wp_remote_get 加上 User-Agent

$mp_html	= wpjam_remote_request($mp_url, ['headers' => ['User-Agent' => $user_agent ?: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36',]]);

然后就可以了,微信这防爬是典型的简单的防一下,意思到了就好。😂

为了防止微信对 User-Agent 有要求,我给「WPJAM GrabMP」加上「User Agent」选项,让使用者也可以自定义,不过他有个默认值,就是上面这个,最新的 Chrome 浏览器的 User Agent:

最后还是简单介绍一下「WPJAM GrabMP」插件:

怎么快速同步自己公众号文章到 WordPress 博客,还有公众号文章里的图片因为微信防盗链,要一张一张下载然后再上传到 WordPress 媒体库,非常很麻烦,所以我写了一个插件「WPJAM GrabMP」来实现一键同步公众号文章到 WordPress 博客:

1. 安装之后,在 WordPree 文章管理菜单下面出现一个抓取图文的子菜单:

2. 点击之后,就可以进入公众号图文抓取界面:

3. 首先输入公众号图文的链接,User Agent 使用默认就好,如果抓取不成功,可以试试一些其他的 User Agent,然后选择文章状态选择「保存我草稿,修改后发布」还是「无需修改,立即发布」。

选择保存为草稿,则点击「一键抓取」按钮之后,就会进入抓取的文章的编辑页面,看看有什么问题,比如抓取下来的图文格式会不会太乱等等,可以自己去编辑修正一下,然后再发布,甚至还选择定时发布。

选择立即发布,则点击「一键抓取」按钮之后,就会直接发布,然后跳转到前台的文章详情页面,直接可以看到前台显示的效果了,当然看到显示效果不好,也可以回到后台,文章编辑页面再次修改。

4. 接着就是外部图片的处理,勾选「将公众号图文中的图片保存到媒体库」之后,系统就会在抓取图文的时候,自动将公众号图文的图片全部抓取到 WordPress 本地媒体库。

如果你博客开启了 CDN 功能,图片也会自动镜像到云存储,然后自动加速,没有开启 CDN 也没有问题,至少媒体库也有了图片。😄

另外公众号图文中的图片默认是640宽显示的,然后你觉这样图片太小了,还可以选择抓取原图,方便对图片有更高追求的同学。

5. 最后点击「一键抓取」按钮就会自动生成一篇文章,插件会自动抓取公众号文章的标题,摘要,然后把头图作为文章的特色图片,内容部分,该插件做了些处理,将视频转成 qqv shortcode。

这样一篇公众号的文章就同步到 WordPress 博客了,对了,该插件需要你先安装 WPJAM Basic 插件和微信机器人高级版才行。

对了,这次更新也要更新一下微信机器人高级版

Cursor 另类应用 — 逆向分析

hacker

昨天登录后台的时候,发现 loginpress 的设置界面挂了,所有的数据样式都是 hidden。让 deepseek 给分析了一通,都是废话,没什么卵用。

今天上午直接让 cursor 分析了一下代码,让给出解决方案,发现依然没什么效果:

不过查看页面元素的时候发现了一段提示:

<tr class="secret_key_v2_invisible" style="display: none;"><th scope="row"><label for="loginpress_setting[secret_key_v2_invisible]">Secret Key</label></th><td><input type="text" class="regular-text" id="loginpress_setting[secret_key_v2_invisible]" name="loginpress_setting[secret_key_v2_invisible]" value=""><p class="description">Get <a href="https://www.google.com/recaptcha/admin" target="_blank"> reCaptcha</a> secret key. <br> <span class="alert-note">Make sure you are adding right  secret key for this domain. If it's incorrect may be you'r not able to access your website.</span></p></td></tr>

让 cusour 分析了一通,依然没什么效果:

不过此时已经基本确认还是授权的问题了,基于上面的废话改起来难度较大,搜索了一下,找了一个新版本的 loginpress pro。

https://wpe98.com/loginpress-pro-nulled/

按照文件的方法直接添加 hook 代码:

<?php
function bypass_license_verification() {
    add_filter('loginpress_license_check', '__return_true');
    add_action('admin_notices', function() {
        echo '<div class="notice notice-success"><p>License successfully nulled for demonstration purposes!</p></div>';
    });
}
add_action('init', 'bypass_license_verification');
?>

此时后台显示的确 ok 了,虽然功能已经激活了,但是页面看起来有些蛋疼,显示没授权: 

根据提示信息搜索就会发现代码位于loginpress-pro 2/classes/loginpress-main.php

大概浏览下代码,发现基本数据都在所谓的授权信息中license_data的结构内,直接让 cursor 给生成一个结构:

此时直接修改授权代码为:

public static function get_registration_data() {
        $license_data = array(
            'success' => true|false,      // 布尔值,表示许可证验证是否成功
            'license' => 'valid',         // 字符串,许可证状态,可能的值包括: valid, invalid, expired, revoked, missing, site_inactive, item_name_mismatch, no_activations_left
            'error' => '',               // 字符串,如果有错误时的错误代码
            'expires' => '2050-10-10',             // 字符串,许可证过期日期,可以是具体日期或 'lifetime'
            'price_id' => 4,            // 整数,许可证价格ID,用于确定许可证类型:
                                        // 1 = Personal
                                        // 2 = Small Business
                                        // 3 或 6 = Agency
                                        // 4 = Ultimate
                                        // 7 = Startup
        );
return $license_data;
}

测试了一下没效果,继续看代码,发现外面还套嵌了一层,cursor 给继续处理一下:

继续调整代码为:

$result = array(
            'license_key' => '',         // 字符串,许可证密钥
            'license_data' => array(     // 数组,许可证详细数据
                'success' => true|false,      // 布尔值,表示许可证验证是否成功
                'license' => 'valid',         // 字符串,许可证状态,可能的值包括: valid, invalid, expired, revoked, missing, site_inactive, item_name_mismatch, no_activations_left
                'error' => '',               // 字符串,如果有错误时的错误代码
                'expires' => '2050-10-10',             // 字符串,许可证过期日期,可以是具体日期或 'lifetime'
                'price_id' => 4,            // 整数,许可证价格ID,用于确定许可证类型:
                                            // 1 = Personal
                                            // 2 = Small Business
                                            // 3 或 6 = Agency
                                            // 4 = Ultimate
                                            // 7 = Startup
            ),
            'error_message' => '',      // 字符串,错误信息
        );
        return $result;

此时再看效果,就完美啦:

 

The post Cursor 另类应用 — 逆向分析 appeared first on obaby@mars.

PIVOT Vol.14 折纸战士

本刊物不定期发布,推荐通过 RSS 订阅:https://anotherdayu.com/feed/

IMG_1488.jpg

「Mac App Comparisons – 2025 Update : r/macapps」

这个帖子收录并对比了几个常用 macOS 软件类别,这几个类别中我比较喜欢的是这些:

关联:My App Defaults 2023,这两年我的软件使用习惯还是有挺多变化的。

|

「WordPress 批量导出 Markdown」

评论尸制作的 WordPress 批量导出 Markdown 插件,用于网站备份很实用。

我还会定期用 SiteSucker for macOS 备份 html 格式,好处是可以保留网页样式和图片。

|

「MCG-NKU/NSFC-LaTex」

开源的国家自然科学基金 LaTex 模版。

|

「Keldos-Li/typora-latex-theme」

为中文小论文优化的 Typora 样式,以浙大论文要求为模版,用户也可以自行修改。

cover

|

「公民对话手册」

八条基本的公民对话原则。可能是源于捷克斯洛伐克的公民论坛,但具体由谁提出并不明确。部分中文资料认为是哈维尔提出的,但英文资料并没有相关信息。

  1. 对话的目的是寻求真理,不是为了斗争;
  2. 不做人身攻击;
  3. 保持主题;
  4. 辩论时要用证据;
  5. 不要坚持错误不改;
  6. 要分清对话与只准自己讲话的区别;
  7. 对话要有记录;
  8. 尽量理解对方。

关联:对该领域感兴趣《罗伯特议事规则》也值得一读。

|

「Readest」

挺简洁的电子书阅读器。用起来比 Calibre 简单,但 macOS 版有一些小 Bug,重启过几次。

Readest Banner

|

「What is Model Context Protocol (MCP)? 」

模型上下文协议(Model Context Protocol,MCP)是一种开创性的开放协议,它彻底简化了人工智能与外部工具和数据源的集成方式。与传统API需要为每个服务编写单独集成不同,MCP提供了一个标准化的”连接器”,允许AI模型通过单一协议访问多种工具和服务。

MCP支持实时双向通信,使AI模型能够动态发现和交互工具,既可以查询信息也可以触发操作,类似于为AI应用提供了一个通用的”USB-C端口”,极大提高了开发效率和系统灵活性。

What is MCP?

|

「大学生活质量指北」

一个由Telegram频道发起的资料汇总平台,旨在收集全球各高校在招生过程中通常不会明确说明但实际上对大学生活质量有重要影响的详细信息。

|

「Kami, for Origami」

一个我用不上,但觉得图标很好看的软件。

CleanShot 2025-03-13 at 15.32.19@2x

记得小时候有一本宝可梦折纸书,玩的特别开心,那时候还叫他们宠物小精灵。

cb37a18f1d79321cba2995721ea04faf

不知道现在的孩子还会看 折纸战士 吗?

如何构建安全的 WordPress 5:禁用搜索结果动态标题,防止 SEO 垃圾攻击

继续「如何构建安全的 WordPress」系列文章,这是 WordPress 搜索安全相关的第二篇,前面我们介绍了「限制搜索频率,防止搜索滥用攻击」,今天讲讲 WordPress 搜索第二个重大的安全隐患, SEO 垃圾攻击(SEO Spam)

SEO 垃圾攻击

什么是SEO 垃圾攻击(SEO Spam)

SEO 垃圾攻击(SEO Spam)​,也称为 ​搜索引擎投毒(Search Engine Poisoning)​,是指黑客或黑产通过操纵搜索引擎优化(SEO)技术,向目标网站注入垃圾内容或篡改网页元素(如标题、关键词、链接等),使其在搜索引擎结果中显示恶意或无关信息,从而误导用户或提升黑产网站的排名。如下(我做个演示):

图片

它还有一下几个行业通用术语

  • SEO Spam / SEO Poisoning:通过操纵页面元素(如标题、描述)提升黑产网站在搜索引擎中的可见性。
  • Title Tag Hijacking:直接劫持标题标签内容,属于 ​On-Page SEO 攻击 的一种。
  • Search Index Pollution:污染搜索引擎索引的恶意行为(Google 官方文档曾用此术语描述类似攻击)。

攻击者通过构造恶意搜索请求(如 ?s=黑产关键词+域名),利用 WordPress 默认的搜索结果页动态标题机制(例如 wp_title() 函数),将恶意内容注入到 <title> 标签中。这属于 ​注入攻击(Injection Attack)​ 的子类,但更贴近 ​SEO 滥用 场景。

为什么 WordPress 经常被这类攻击呢?因为WordPress 默认将搜索关键词动态插入标题(例如 搜索:{关键词} - 网站名),而黑产通过自动化工具高频请求含恶意关键词的搜索页(如 ?s=赌博网站),导致这些关键词被收录到搜索引擎索引中,甚至排名靠前。

这类攻击造成的损害也是很大的,一旦你的网站有这类情况,可能会被搜索引擎误判为关联黑产内容,导致网站降权或标记为恶意。万一用户通过搜索敏感词进入站点,可能触发安全平台(如 Google Safe Browsing)的警告。

静态化搜索结果标题

那么怎么办呢?其实很简单,禁用 WordPress 搜索结果动态标题,静态化搜索结果标题,​比如只显示「搜索结果」这四个字:

图片

WPJAM 搜索优化插件 已经集成了该功能,如下图所示,「搜索增强」的第三个选项「搜索结果页面标题不显示关键字,只显示「搜索结果」四个字」勾选上即可:

WPJAM 搜索优化插件 已经集上面所有的功能和相关代码,直接启用即可,点击查看 WPJAM 搜索优化插件 的详细介绍,Modular 主题也集成了,我会在介绍 WordPress 安全这系列文章的时候,将这些安全相关代码也整合到 Modular 主题中,争取打造最安全的 WordPress 主题。

如何在本地调试WordPress时忽略对wordpress.org的网络连接请求

本地调试WordPress时,为了保证代码的正确性,插件和主题作者往往会打开wp-config.php里的WP_DEBUG开关。如果您不知道这个开关,就不要往下看了。

define('WP_DEBUG', true);

这样PHP运行时的错误和警告就会以醒目的字体直接打印到网页上。
20250313_WP_local_debug_warning

但是这样会带来一个程序员的日经问题:是我的BUG我改,不是我的BUG莫挨老子!
按说WP这种成熟的产品是不会让用户看到警告和错误的。但是,由于众所周知的原因,WP内核、主题和插件升级所需要的WordPress的官网wordpress.org时灵时不灵,连不上的时候就会显示大面积的警告信息。
安装完成以后,后台这种需要连接到wordpress.org的地方大抵有4种:core update、theme update、 plugin update和translation api,出现在后台Dashboard、 Plugin、 Theme、 和Settings页面。其中Dashboard会调用前三种Update,Settings四种都会调用。
这些信息不仅是影响对于出错代码的判断(比如图中提示的“Cannot modify header information”,其实根本就不是本地header的问题),还会直接影响页面元素的渲染和操作。
那就必须要干掉它!

再次更新,

define('WP_HTTP_BLOCK_EXTERNAL', true);

这个宏屁用没用,还是得用我下面的方法。

开整。

//下面的action钩子调用的早,所以在加载主题或插件的时候就要直接remove掉,否则没机会了。
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
    remove_action('admin_init', '_maybe_update_core');
    remove_action('admin_init', '_maybe_update_plugins');
    remove_action('admin_init', '_maybe_update_themes');
    remove_action('init', 'wp_schedule_update_checks');

    //translations_api默认会返回false,之后会访问wordpress.org,返回空数组之后就不访问了。
    //Since 4.0.0
    add_filter('translations_api', '__return_empty_array');
}

//调试者作为admin,默认是有各种update权限的。这里令各种内部调用user_has_cap询问4种权限的结果强行置为false。
function _debug_ignore_wp_request ($allcaps, $caps, $args){
    $server_caps = array('install_languages', 'update_themes', 'update_plugins', 'update_core', 'install_themes', 'install_plugins');
    foreach ($caps as $cap) {
        if ( in_array($cap, $server_caps)) {
            $allcaps[$cap] = false;
        }
    }
    return $allcaps;
}

function my_admin_init {
    if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
        //下面的钩子很多不能移除得太早。
        //宁杀错不放过。
        remove_action('upgrader_process_complete', 'wp_update_plugins');
        remove_action('upgrader_process_complete', 'wp_update_themes');
        remove_action('load-plugins.php', 'wp_plugin_update_rows', 20);
        remove_action('load-themes.php', 'wp_theme_update_rows', 20);
        remove_action('load-plugins.php', 'wp_update_plugins');
        remove_action('load-themes.php', 'wp_update_themes');
        wp_unschedule_hook('wp_version_check');
        wp_unschedule_hook('wp_update_plugins');
        wp_unschedule_hook('wp_update_themes');

        remove_action('wp_version_check', 'wp_version_check');
        remove_action('load-plugins.php', 'wp_update_plugins');
        remove_action('load-update.php', 'wp_update_plugins');
        remove_action('load-update-core.php', 'wp_update_plugins');
        remove_action('wp_update_plugins', 'wp_update_plugins');
        remove_action('load-themes.php', 'wp_update_themes');
        remove_action('load-update.php', 'wp_update_themes');
        remove_action('load-update-core.php', 'wp_update_themes');
        remove_action('wp_update_themes', 'wp_update_themes');
        remove_action('update_option_WPLANG', 'wp_clean_update_cache', 10, 0);
        remove_action('wp_maybe_auto_update', 'wp_maybe_auto_update');
        add_filter('user_has_cap', '_debug_ignore_wp_request', 10, 3);
    }
}

add_action('admin_init','my_admin_init');

完事。这个世界清净了。


  • (1):农历每年冬至所在的月固定为十一月。如果两个冬至间有13次朔望,则该年产生闰月。13个月中,第一个没有二十四节气里的偶数节气的月份就是闰月。因为十一月是起调点,所以农历十二月和正月是不会出现闰月的,正月初一和第一个节气春分受的影响也很小。我数学不好,但查表得到的结果,从1950年到2069的120年间,闰年就是双春,双春就是闰年,一一对应,无一例外。闰月是典型的用太阳历调整月历的规则,所以农历是阴阳历而不是纯阴(月)历。

Memcached 和 Redis 有什么区别,做缓存 WordPress 用哪个好?

前面介绍了使用 Memcached 内存缓存来实现 WordPress 站点秒开,但是很多人问到了 Redis,就是做缓存 Redis 和 Memcached 有什么区别,用哪个更好?今天就给大家做一个简单介绍。

Memcached 和 Redis 有什么区别

首先从模型上看,Memcached 是一个分布式内存缓存系统,专注于简单的键-值对存储,设计简单易用,它不支持复杂数据类型,而 Redis 是一个内存数据结构存储,支持更多的数据结构(如列表、集合、排序集合、哈希等),不仅仅是简单的键-值对。

所以 Memcached 是为简单的读写操作优化的,适合需要快速缓存大量数据的场景,而 Redis 提供了丰富的数据操作功能,对复杂数据操作优化良好,同时也提供了高性能的读写速度,并且 Redis 支持数据持久化,可以将内存数据保存到磁盘,Memcached 没有持久性功能,所有数据都存储在内存中,服务器重启时数据就会丢失,作为缓存这个问题不大。

此外,它们还有一点比较大的区别,就是 Memcached 支持多线程,所以支持高并发访问,而 Redis 一般使用单线程模型,虽然通过 I/O 多路复用技术提供高吞吐量,这样就比较在秒杀等场景下使用,不需要考虑并发的问题,因为单线程。

简单做个功能特性对比表格:

特性MemcachedRedis
数据结构仅支持键值对(String)支持 String、List、Hash、Set 等
持久化不支持支持 RDB 快照和 AOF 日志
线程模型多线程(高并发读优)单线程(避免锁竞争,顺序执行)
内存管理预分配固定内存,LRU 淘汰支持内存淘汰策略,可配置虚拟内存
集群模式依赖客户端分片(如 Twemproxy)原生 Cluster 模式支持
适用场景简单键值缓存(如会话、HTML片段)缓存、消息队列、实时统计等复杂场景

Redis 的作者的建议

Redis 的作者 Salvatore Sanfilippo 曾经对这两种基于内存的数据存储系统进行过比较:

  1. Redis 支持服务器端的数据操作:Redis 相比 Memcached 来说,拥有更多的数据结构和并支持更丰富的数据操作,通常在 Memcached 里,你需要将数据拿到客户端来进行类似的修改再 set 回去。这大大增加了网络 IO 的次数和数据体积。在 Redis 中,这些复杂的操作通常和一般的 GET/SET 一样高效。所以,如果需要缓存能够支持更复杂的结构和操作,那么 Redis 会是不错的选择。
  2. 内存使用效率对比:使用简单的 key-value 存储的话,Memcached 的内存利用率更高,而如果 Redis 采用 hash 结构来做 key-value 存储,由于其组合式的压缩,其内存利用率会高于 Memcached。
  3. 性能对比:由于 Redis 只使用单核,而 Memcached 可以使用多核,所以平均每一个核上 Redis 在存储小数据时比 Memcached 性能更高。而在 100k 以上的数据中,Memcached 性能要高于 Redis,虽然 Redis 最近也在存储大数据的性能上进行优化,但是比起 Memcached,还是稍有逊色。

总结一下:Memcached 是解决简单缓存问题的可靠选择,而 Redis 通过提供更丰富的功能和各种各样的特性而优于 Memcached,这些特性对于解决复杂的场景更有优势。

WordPress 使用哪个做缓存好?

如果单纯作为内存缓存来使用,两者其实没有什么区别,那么为什么 WPJAM Basic 为什么使用 Memcached 呢?

这里有一份 4 核 CPU / 8G 内存的服务器上的测试数据:

操作Memcached QPSRedis QPS
GET 请求120,000+100,000+
SET 请求90,000+80,000+

可以看出在 WordPress 这样简单的键-值缓存,并且需要处理大量简单数据,Memcached 是一个更好的选择。

此外我们一开始就选择了 Memcached 做 WordPress 的内存缓存的存储介质,并且在使用 Memcached 做内存缓存过程中,针对出现的各种的问题,我也做了很多的优化,比如我们在后台「WPJAM」菜单下的「系统信息」中展示「Memcached」的各种信息。

Memcached 命中率

当然如果你已经使用了 Redis 做内存缓存或者更熟悉 Redis,WordPress 官方插件库也有很多第三方提供了 Redis 的 object-cache.php,和使用 Memcached 一样,只需要将对应的 object-cache.php 上传到 wp-content 目录即可。

此外也有小伙伴问,WPJAM Basic 会不会集成 Redis,让大家自己选,这个可以明确的说,目前作为简单缓存功能,Memcached 已经足够好用,不会再花时间集成 Redis。

最后还有个问题,Memcached 和 Redis 可以一起用吗?如果作为缓存,WordPress 只能选择一个,因为你上传谁的 object-cache.php,就是用谁得了。

但是不等于使用 Memcached 作为缓存,就不能使用 Redis 了,比如我们之前就利用 Redis 的一些特性做过一些开发,比如因为 Redis 单线程天然串行排队的特性,我们在花生小店秒杀的功能中就是使用 Redis 进行处理的,还有一些简单的消息队列的功能处理,也是基于 Redis 进行开发的。

简单总结

所以最后总结说一下,如果简单的 key-value 的内存缓存,建议使用 Memcached,WordPress 绝大部分站点也是使用 Memcached 进行缓存的,此外 WPJAM Basic 也对此优化得比较完善。

如果要进行复杂的程序开发,比如上面说的电商的秒杀功能 ,消息队列系统等,那么 Redis 才是发挥其长处的地方。

WordPress备份的内容及方法

为了防止意外发生,需要定期备份WordPress的数据,以下是我根据自己的需要整理的备份内容及方法:

1. 备份数据库

  • 使用插件:如Database Backup for WordPress插件,可自动备份数据库到电子邮箱。(频率:每周一次,自动)
  • 数据库操作:通过phpMyAdmin导出数据库文件。(频率:每年一次,手动)

2. 备份文章

  • 备份到博客托管平台:WordPress后台导出xml文件,然后导入到WordPress.com或者Blogger。(频率:每年一次,手动)
  • 电子邮件备份:使用电子邮件订阅博客服务(如follow.it),每次更新文章时,将会收到邮件。(频率:每次发布文章一次,自动)

3. 备份文件

  • 主题文件:备份wp-content/themes目录。
  • wp-config.php:包含数据库连接信息等重要配置。
  • .htaccess:用于URL重写等服务器配置。
  • robots.txt:搜索引擎规则。
  • favicon.ico:网站图标。
  • 上传文件:备份wp-content/uploads目录。因为我的图片全部是外链,不需要备份这个文件夹。
  • 手动备份:通过FTP或文件管理器下载文件。
  • 频率:每次修改后立即备份。

4. 备份外链图片

  • 查找包含图片的文章
    SELECT ID, post_title,guid FROM wp_posts WHERE post_type = 'post' AND post_content LIKE '%<img%';
  • 查找包含2张及以上图片的文章
    SELECT ID, post_title, guid FROM wp_posts WHERE post_type = 'post' AND (LENGTH(post_content) - LENGTH(REPLACE(post_content, '<img', ''))) / LENGTH('<img') >= 2;
  • 备份方法:手动将文章复制粘贴到国内各大平台,如微信号、知乎、豆瓣、头条号等,这些平台会自动将外链图片上传到自身的服务器。
  • 频率:不定期备份。

如何构建安全的 WordPress 2:隐藏登录失败时「未知用户名」和「密码不正确」错误信息

之前我们开启了如何构建安全的 WordPress 系列文章,并开启了第一篇:防止用户名暴露,我们通过 5 个地方的功能和代码,让 WordPress 登录名不会出现在任何页面上或者源代码中。

除此之外,其实还有一个地方还有可能让攻击者猜测到用户名是否正确,这个就是在登录界面,如果工具者使用暴力破解的方式尝试使用用户名的时候,WordPress 默认的错误信息,可以让攻击者获得正确的用户名。

默认情况下,在登录 WordPress 的时候,如果输入的用户名不存在,WordPress 会报「未知用户名」的错误:

「未知用户名」

如果用户名正确,密码错误的话,WordPress 会报「密码不正确」的错误:

「密码不正确」

这些错误提示信息可以让让攻击者知道快速定位用户名,确定了用户名,继续暴力破解获得密码就更加方便。

所以这些错误信息最好统一改成:「用户名或者密码错误」的错误信息,让攻击者猜去吧。

add_filter('wp_login_errors', function($errors){
	$error_code	= $errors->get_error_code();

	if(in_array($error_code, ['invalid_username', 'invalid_email', 'incorrect_password'])){
		$errors->remove($error_code);
		$errors->add($error_code, '用户名或者密码错误。');
	}

	return $errors;
});

还是那句话,安全是最重要的,所以一定要重视,除了防止用户名暴露,隐藏可以让攻击者确定用户名的错误信息是非常好的安全措施。

WPJAM 用户管理插件 已经集上面所有的功能和相关代码,直接启用即可,点击查看 WPJAM 用户管理插件的详细介绍,Modular 主题也集成了,我会在介绍 WordPress 安全这系列文章的时候,将这些安全相关代码也整合到 Modular 主题中,争取打造最安全的 WordPress 主题。

WordPress Newsletter 插件

前几天看到 拾月 开发了一个 RSS to Email 的服务,可以让读者订阅网站的 RSS feeds,0.002 元 / 封。

目前有 5 人民币的免费额度,对大部分博客来说,已经够用很久。

个人感觉这个服务很棒,不用花费额外精力配置,也不用再编辑一遍文本,都是自动化的,特别适合静态博客。

以此为契机,我搜了搜 WordPress 的插件商店,发现了 Newsletter

比起其他类似功能的插件,这个插件的优势是不需要注册,如果我保持 WordPress 版本不变,即使这个插件不更新维护,我依旧能使用。

设置很简单,如果 WordPress 配置过 SMTP 邮件转发,则可以直接下载使用该插件。

我目前使用的是免费版。可以展示近期的多篇博客,也可以每封邮件展示一篇博客全文。

CleanShot 2025-03-03 at 14.50.50@2x

Note: @JeffreyCalm 补充了一下非自建邮件服务(比如Gmail、Outlook)一天用 SMTP 发 200 封左右会被封停,自建的应该没有该限制。

自建邮箱则会有触达率的问题,目前大部分邮件服务商是白名单模式,新且小的 STMP 转发有可能被退信。

在 DeepSeek 的帮助下,我又给 WPJAM Basic 增加了几个函数!

对于程序员来说,写代码其实不难,反而最难的是给函数命名,这是困扰程序员最大的问题,很多程序员开玩笑说:编程5分钟,命名2小时。😂

比如之前网上就有一张图,反应了程序员编程的时候,具体在干嘛:

让 DeepSeek 给函数命名

首先我们先明确一下:什么样的函数名是一个好的名字呢?

好的函数命名应当简洁、清晰且易于理解,能够在不查看具体实现的情况下直观地反映出其功能和用途。

但实际上找到这样的命名并不容易,需要充分考虑变量、函数和类的功能、用途以及上下文环境,因此程序员需要花费大量时间思考如何为代码中的各个元素命名,以提高代码的可读性和可维护性。

那么如果我们让 DeepSeek 在我们给函数命名的时候,给我我们一些建议,是不是可以解决我们这个困扰呢? 或者说打开我们的思路呢?我们说干就干,首先是提示词,经过调试,下面是我的函数命名的提示词是:

我将发给你一段程序代码,你根据这段代码帮我提炼出函数的名称,函数名称的风格为下划线风格,然后函数应用于 WordPress,需要参考 WordPress 函数命名风格,并简单解释下为什么这么命名,如果可以请提供多一些选项以供选择,谢谢。

正好最近在发布 #WPJAM Basic# 新版的时候,为了方便,又增加了几个函数,比如下面,判断变量是不是闭包函数:

return $object instanceof Closure;

再来一个,如果变量回调函数,那就调用回调函数,否则就还是返回变量本生:

return $value && is_callable($value) ? $value(...$args) : $value;

如果自己也有想法,可以再在和他沟通一下:😄

WPJAM Basic 新增函数

所最后在 DeepSeek 的帮助下,WPJAM Basic 新版增加下面几个函数:

1. maybe_callback

如果变量是回调函数,则调用回调函数,否则返回变量本身:

if(!function_exists('maybe_callback')){
	function maybe_callback($value, ...$args){
		return $value && is_callable($value) ? $value(...$args) : $value;
	}
}

2. maybe_closure

类似于 maybe_callback,但是它判断是闭包函数才调用,其他一样:

if(!function_exists('maybe_closure')){
	function maybe_closure($value, ...$args){
		return $value && is_closure($value) ? $value(...$args) : $value;
	}
}

3. is_closure

怎么判断闭包函数呢?就有这个函数了:

if(!function_exists('is_closure')){
	function is_closure($object){
		return $object instanceof Closure;
	}
}

4. wpjam_pick

从对象或者数组中,根据 $keys 获取一个关联数组,类似 JS 工具库 underscore 或者 loadsh 的 _.pick 函数,如果是从数组中获取,其实和 WordPress 内置的 wp_array_slice_assoc 一样,只是命名这个更加简洁。

function wpjam_pick($arr, $keys){
	return is_object($arr) ? wpjam_array($keys, fn($i, $k)=> isset($arr->$k) ? [$k, $arr->$k] : null) : wp_array_slice_assoc($arr, $keys);
}

等我发布新版,就可以使用了!

强迫症

有时候真的不想开始干一些事情,因为一旦开始了就想着把所有的问题都解决掉。然而,要解决这些问题有的时候真挺痛苦的,苦不堪言。

最近其实乱七八糟的事情挺多的,之前一流的烂尾项目又开始折腾,导致自己现在一听到甲方的名字就 tm 反胃,所以有的时候也是在消极应对。

其实很多的事情,哪怕自己强迫症再严重,有的也解决不了。例如现在 wp 的后台提示有一项插件可以升级,但是点到插件页面或者更新页面又消失了,就跟幽灵一样。

昨天晚上提示邮件发送插件激活失败了,有新版本提示升级,看了下现在用的是 3 最新的已经到了 4,网上搜了一通没搜到免费下载的地方,最终花 4 块钱买了个下载地址下载安装了,不得不说这破解插件收费卖也的确是个好生意。每次装完插件就是要去掉各种收费插件的升级监测:

去掉之后一个省了加载时间,另外一个是免得提示升级,或者自动升级导致破解失败。同样,升级了一下 envira gallery 的插件,现在相册页面的独立链接的确能用了。也算是又修复了一个问题,最后连上篇文章中提到的那个错误也一起修复了。至此多数问题都解决了。

然而,还有个最恶心人的东西,就是之前构建的说说页面也有问题,创建的文章在说说页面无法播放视频:

这个破玩意儿看着就那么恶心,那个 video 跟傻屌一样显示了一行代码,本来想改页面模板,但是直接打开却又能播放:

具体播放则是调用了一堆 js:

新建页面模板,通过代码将上面的 js css 插入,然而最终失败了,不知道是代码问题还是神马智障问题。最终放弃。

此路行不通那就换别的方式吧,经过转换之后发现 h5 的 video 标签是可以播放的,可以直接插入 h5 的代码:

<video controls="controls" width="720" height="100%"><source src="https://h4ck.org.cn/wp-content/uploads/2025/02/c229677d-71e2-4dd5-86ab-b8137a086b801740010424255.mp4" type="video/mp4" />Your browser does not support the video tag.</video>

最起码说说页面能显示能播放了:

既然如此,那就通过 video 标签的形式插入吧,但是每次都得写这段代码太蛋疼了,直接修改 functions.php 给编辑器添加个按钮来干这件事情:

function add_video_button($wp_editor_id) {
    // 获取编辑器的 ID
    $editor_id = $wp_editor_id;

    // 添加按钮的 HTML 代码
    $button_html = '<button id="add-video-button" class="button"><img src="/img/h5_video.png" width=26 height=26 ></img>添加视频</button>';

    // 输出按钮的 HTML 代码
    echo $button_html;

    // 创建一个弹出窗口的 HTML 代码
    $popup_html = '
    <div id="video-popup" style="display: none; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: #fff; padding: 20px; border: 1px solid #ddd; border-radius: 10px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); width: 400px;">
        <h2 style="margin-top: 0;">添加视频</h2>
        <div style="margin-bottom: 20px;">
            <label style="display: inline-block; width: 80px; text-align: right; margin-right: 10px;">宽度:</label>
            <input id="video-width" type="text" value="100%" style="width: 200px; height: 30px; padding: 5px; border: 1px solid #ccc;">
        </div>
        <div style="margin-bottom: 20px;">
            <label style="display: inline-block; width: 80px; text-align: right; margin-right: 10px;">高度:</label>
            <input id="video-height" type="text" value="100%" style="width: 200px; height: 30px; padding: 5px; border: 1px solid #ccc;">
        </div>
        <div style="margin-bottom: 20px;">
            <label style="display: inline-block; width: 80px; text-align: right; margin-right: 10px;">视频地址:</label>
            <input id="video-src" type="text" style="width: 280px; height: 30px; padding: 5px; border: 1px solid #ccc;">
        </div>
        <div style="text-align: right;">
            <button id="video-submit" style="margin-right: 10px; width: 80px; height: 30px; background-color: #04a4cc; color: #fff; border: none; border-radius: 5px; cursor: pointer;">确定</button>
            <button id="video-cancel" style="width: 80px; height: 30px; background-color: #ccc; color: #666; border: none; border-radius: 5px; cursor: pointer;">取消</button>
        </div>
    </div>
    ';

    // 输出弹出窗口的 HTML 代码
    echo $popup_html;

    // 使用 JavaScript 为按钮添加点击事件
    ?>
    <script>

       jQuery(document).ready(function($) {
                $('#add-video-button').on('click', function(e) {
                        e.preventDefault();
                // 显示弹出窗口
                $('#video-popup').show();
            });

                $('#video-cancel').on('click', function(e) {
                        e.preventDefault();
                // 隐藏弹出窗口
                $('#video-popup').hide();
            });

                $('#video-submit').on('click', function(e) {
                        e.preventDefault();
                // 获取输入框的值
                var width = $('#video-width').val();
                var height = $('#video-height').val();
                var src = $('#video-src').val();

                // 如果输入框不为空
                if (width !== '' && height !== '' && src !== '') {
                    // 获取编辑器的内容
                    var editor = tinyMCE.get('<?php echo $editor_id; ?>');

                    // 如果编辑器存在
                    if (editor) {
                        // 向编辑器中插入内容
                        editor.execCommand('mceInsertContent', false, '<video controls="controls" width="' + width + '" height="' + height + '"><source src="' + src + '" type="video/mp4" />Your browser does not support the video tag.</video>');
                    } else {
                       // 如果使用的是文本模式编辑器
                        $('#<?php echo $editor_id; ?>').val($('#<?php echo $editor_id; ?>').val() + '<video controls="controls" width="' + width + '" height="' + height + '"><source src="' + src + '" type="video/mp4" />Your browser does not support the video tag.</video>');
                    }

                    // 隐藏弹出窗口
                    $('#video-popup').hide();
                }
            });
        });
    </script>
    <?php
}


// Hook 到 WordPress 的编辑器中
add_action('media_buttons', 'add_video_button', 11);



最终效果:

到这里,目前这次对于wp 的折腾算是基本完成了。然而,所有的插件,系统都在不断的升级,每次升级之后就会面临插件版本太旧的问题。

对于插件我倒是也想支持正版,不过那个价格的确让人有点不大好接受,一个插件一年几百块,好几个插件加起来都几千了,有这几千总感觉不能扔在这个地方,毕竟本来就不盈利。

暂时就这样吧,毕竟有的问题,哪怕强迫症也解决不了,就酱紫,由他去吧。

更新后插件地址:

https://github.com/obaby/Simple-microblogging-wordpress-plugin.git

WordPress 后台速度优化

昨天下午的时候,杜郎杜郎发消息,问有没有设么想干的事情,或者 wp 想要的插件。当时信誓旦旦的说没什么想写的东西呢。

等到了晚上的时候,发现wp 的后台加载速度变得贼慢,需要等待 N 秒才能打开,这就变得很奇怪,让自己一度以为是自己升级了 Envira Gellery 插件导致的,于是把插件版本回滚了。

但是,回滚之后速度并没有明显的改观,这就变得很恶心了。

还是老办法打开 query monitor,发现后台打开请求时间到了十几秒,主要问题在几个 http 请求上:

这几个 http 都超时了,访问的是 api.wordpress.org,直接在服务器上 curl 访问也有一定的概率会超时,即使修改 host 绑定 ip 之后改观依然不大。

并且这个 ip 地址全球解析都是一样的,也就是说没法更换 ip 地址来访问别的服务器。当然,要解决这个问题最直接的办法是直接禁用 wp 的更新检查,但是这个方法我并不是十分喜欢,毕竟有时候更新修复的是一些严重的漏洞。那么除此之外就只能坐以待毙了?

这个 ip 访问不稳定应该还是大墙导致的,既然如此,那么用自己的服务器反代应该会好一些。直接分配一个二级域名,到服务器进行反代:

location / {

        proxy_pass https://198.143.164.251;
        proxy_http_version 1.1;
proxy_set_header Accept-Encoding "";
proxy_set_header Host api.wordpress.org;

}

需要注意的是需要将 Host 设置为Host api.wordpress.org,否则访问的时候会直接跳到 wp 的首页。

修改 wp 的 update.php 文件:

将检查更新的地址替换掉,再次访问:

此时请求的域名就变成自己的域名了,并且超时的问题基本解决掉。剩下的就是两个慢查询:

这两个是 wp 后台登录的保护插件导致的,看下数据库已经记录了 28 万条:

 

清空记录之后,一切就正常了。

只剩下一个错误,这个目前影响不大,就先不管了。

然而,在看到有两个更新,在点更新的时候又崩了。

提示的 object cache 导致的,这个插件用的版本还是比较老的,网上找个新版本,发现处理的并不彻底,各种提示信息以及按钮不能用,自己尝试修改了一下,去掉了一些验证。自己折腾到十一点多,有点困了,于是就找到了杜郎。

然而,事情貌似没那么简单,早上看了一下,插件已经自己停止了:

并且 enable cache 的按钮是灰的,还是授权校验没通过导致的。

至于这个怎么解决,只能仔细研究代码了,或者靠杜郎杜郎研究代码,嘻嘻。

不过得赞一下杜郎杜郎给提供的头图视频啊,还是蛮惊艳的。效果出奇的好呢。

最终在独狼的提示下,感觉还是修改license.php文件靠谱,object cache pro 1.22如果出现授权为 invalid,将文件替换为下面的内容即可:

温馨提示: 此处隐藏内容需要发表评论,并且审核通过后才能查看。
(发表评论请勾选 在此浏览器中保存我的显示名称、邮箱地址和网站地址,以便下次评论时使用。
(请仔细检查自己的昵称和评论内容,以免被识别为垃圾评论而导致无法正常审核。)

 

需要别人登录你的 WordPress,再也不需要给账号密码了,现在可以给「一次登录链接」了!

前面我们介绍「为什么你的 WordPress 站点老是被黑?」的时候,说到大胡子和我卖 Modular 主题,我们的售后是很负责的,😎 会在用户允许的情况下,进入后台帮忙解决,这时候我们需要对方提供一下后台的账号密码,然后就接触到了很多简单到令人发指的密码,所以网站就被黑了。

说到要求对方提供账号密码这个事情,有用户提出,其实给人账号密码也很不安全,最好是创建一个新的管理员账号,这样就不会不小心暴露自己常用密码。

一次登录链接

但是创建一个新的管理员账号也是麻烦,用完又要删除或者去修改密码。那么有没有更好的方法呢?今天想到一个好方法,就是给某个用户创建「一次登录链接」,只能使用一次,这样就不用担心「售后」的时间。✌️

我就把该功能增加到「用户管理」功能,默认是开启的:

然后在用户列表就会有「生成链接」的操作,我把原来的「生成重置密码链接」一起合并进来:

点击之后,链接类型选择「一次登录」,链接有效期默认是 3 个小时,意思是 3 个小时内该链接点击都可以登录,过了就不行。

然后复制该链接,发送给帮你解决问题的好人,就可以了。

WPJAM「用户管理」

这次一次登录链接功能,我集成到了 WPJAM 这个「用户管理」插件中,它是 WordPress 果酱知识星球福利插件,加入「WordPress果酱」知识星球(长按下图二维码)即可下载:

为什么你的 WordPress 站点老是被黑?根本就没啥复杂的原因,就是因为……

因为你的 WordPress 密码太简单了,坏人根本都不用什么牛逼工具或者利用什么 0day 漏洞,只要简单撞下库就能破解!

为什么这么说呢?

因为大胡子和我卖 Modular 主题,我们的售后是很负责的,除了在群里回答问题之外,一些用户复杂的问题,在说不清楚的情况下,我们会在用户允许的情况下,进入后台帮忙解决,甚至他们站点被黑了也会找我们帮忙解决,这时候我们需要对方提供一下后台的账号密码,然后就接触到了很多简单到令人发指的密码。😅

这些密码简单到什么程度,请看下面截图:

所以根本不用在讲什么大道理,这么多赤裸裸和血淋淋的事实,大家应该明白为什么 WordPress 会被黑吧。如果你的密码还是那么简单,快去改一下密码,不然下次被黑可能就是你了。😂

并且 WordPress 后台也会提示你的密码是否足够复杂了,如果是 123456 这种,就会显示非常弱:

如果是累下面这种 WordPress 自动生成的,则会显示强:

建议大家都一定要设置成「强」的密码!

最后大家来看看我们的 Modular 主题,我们售后很负责的。另外你有没有朋友,使用很简单密码的那种,来分享你朋友简单的密码。😁

如果基于 DeepSeek 开发 WordPress 的插件,它自己会选择什么功能?

今年最火的就是 DeepSeek 了,各种新闻,把英伟达的股票都干没了10 几个点。我也在想做一个基于 DeepSeep 的 WordPress 插件,但是做什么方向的的功能呢?要不这个功能也让 DeepSeek 帮我们也想想?

DeepSeek 的使用和 ChatGPT 之类其他的 AI 工具是有区别,他是基于推理型的大模型,而不是指令型的大模式,所以使用 DeepSeek 根本不需要提示词,直接就好了。

所以我的问题就直接把自己的目的告诉,我想写个 DeepSeek 的插件,需要给些功能灵感:

我想基于 DeepSeek 写个 WordPress 插件,在方向上,基于你对自己理解,你觉得可以做那些功能呢,你可以给我一些灵感吗?

然后我 开启了深度思考模式,DeepSeek 给出了它对这个问题的推理过程:

然后他给出了自己的建议,它还非常贴心的分成几个小标题,一共提供内容生产力、智能交互增强、数据智能分析和效率增强功能四大方向,每个方向还提供了2 个小功能,大家看看这些功能建议如何,并且它还非常贴心的提供技术实现要点,以及如何赚钱,也就是商业化建议

基于 DeepSeek 的能力和 WordPress 生态需求,以下是几个值得探索的插件开发方向,按优先级排序并附具体实现思路:


一、内容生产力工具(核心场景)

  1. AI 文章助手
    • 自动草稿生成:根据用户输入关键词自动生成结构化大纲(支持Markdown)
    • 智能续写/改写:通过浮动工具栏实现选中内容的优化/扩写/简写
    • SEO 增强:实时分析内容并推荐关键词密度、生成meta描述
    • 技术实现:结合Gutenberg编辑器API + 内容缓存机制降低API调用成本
  2. 多模态内容生成
    • 基于文本描述自动生成特色图片(需集成DeepSeek-Visual)
    • 智能生成文章配图说明文字(ALT文本优化)
    • 自动创建信息图描述文本

二、智能交互增强

  1. 对话式知识库
    • 将网站文档/产品目录转化为可对话的知识库
    • 实现路径:定期爬取指定页面内容构建向量数据库
    • 示例场景:客户服务机器人、产品FAQ交互
  2. 实时评论互动
    • 智能回复用户评论(可设置白名单词库限制)
    • 情感分析自动标记高风险评论
    • 支持预设行业话术模板(电商/教育等)

三、数据智能分析

  1. 流量内容洞察
    • 结合GA数据生成自然语言分析报告
    • 自动识别高跳出率页面的内容问题
    • 预测内容生命周期并提供更新建议
  2. 竞品内容监测
    • 定期抓取竞品RSS进行摘要对比
    • 生成差异化创作建议(需配置代理抓取)

四、效率增强功能

  1. 智能翻译工作流
    • 一键生成多语言版本并保持SEO结构
    • 支持术语表维护和翻译风格预设
    • 实现:WPML兼容 + 增量翻译缓存
  2. 自动化运营
    • 定期自动生成节日营销文案
    • 社交媒体帖子自动生成与排期
    • 结合Zapier实现跨平台自动化

技术实现要点

  1. 性能优化
    • 实现内容缓存池(基于文章ID的版本控制)
    • 支持异步队列处理长文本任务
    • 本地语义相似度计算减少API调用
  2. 安全合规
    • 内容审核过滤层(可对接DeepSeek审核API)
    • 用户数据脱敏处理
    • GDPR兼容设计(数据暂存策略)
  3. 扩展架构
    • 提供webhook接入点
    • 开发REST API扩展模块
    • 支持与WooCommerce等流行插件的数据打通

商业化建议

  • 分层定价策略
    • 免费版:基础内容生成(限次/水印)
    • 专业版:高级分析+多语言(订阅制)
    • 企业版:私有化部署+定制模型
  • 流量变现
    • 内置AI写作模版市场
    • 对接第三方云服务返佣
    • 提供A/B测试数据服务

建议初期聚焦内容生成核心场景,采用「AI功能+SEO工具」组合拳切入市场,后续通过用户行为数据分析逐步扩展智能运营功能。可参考Jarvis(Conversion.ai)的增长路径,但需注意WordPress生态的特殊性,强化与经典插件(Yoast SEO、Elementor)的兼容性。


大家觉得如何?希望首先实现哪个方向的插件?可以给我留言,我争取2 月份就先做个简单的插件出来给大家用用。😁

DMIT 多款美西 3 网优化的 VPS 补货了,年付仅需 39.9 美元起!

还是先简单介绍下 DMIT,DMIT 成立于2017,是一家海外 VPS 的厂商,主营中国香港、美国洛杉矶、日本东京等地区的 VPS,拥有对国内访问友好(CN2 GIA+CMIN2)的优化路线,稳定不掉速,并且基本也不超售,是著名VPS厂商搬瓦工(Bandwagonhost)的上游之一。

DMIT 39.9

为了方便大家理解,先对线路的名称做下说明:😄

  • CN2GIA 是指中国电信的高端优化路线
  • CMIN2 是指中国移动的高端优化路线

下面是这次 DMIT 这次的优惠的套餐:

LAX.EB.WEE(3网CMI2)推荐

  • 1vCPU(EPYC 9654)
  • 1GB RAM
  • 20GB SSD
  • 1000GB /月流量(1Gbps)
  • 1 IPv4 & 1 IPv6 /64
  • 39.9美元/年

测试 IP:154.17.226.2

购买链接:https://www.dmit.io/aff.php?aff=9154&pid=188

LAX.EB.CORONA(3网CMI2)

  • 1vCPU(EPYC 9654)
  • 1GB RAM
  • 20GB SSD
  • 2000GB /月流量(2Gbps)
  • 1 IPv4 & 1 IPv6 /64
  • 49.9美元/年

测试 IP:154.17.226.2

购买链接:https://www.dmit.io/aff.php?aff=9154&pid=218

LAX.Pro.MALIBU(3网CN2GIA)

  • 1vCPU(EPYC 9654)
  • 1GB RAM
  • 20GB SSD
  • 1000GB /月流量(1Gbps)
  • 1 IPv4 & 1 IPv6 /64
  • 49.9美元/年

测试 IP:154.17.2.12

购买链接:https://www.dmit.io/aff.php?aff=9154&pid=186

DMIT 测评

我们对 LAX.EB.WEE(3网CMI2)做了下基本的测试,首先是 全国 TCPing(测试IP:154.17.226.2),可以说是一片绿油油(晚间测试):

探针表现也非常稳定,三网平稳,高峰期无波澜,全天候 PING 值基本没啥变动(如果是普通路线的话,晚高峰期会 Ping 值高,降速严重)。

再看下 IP 质量报告:

YABS

# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #
#              Yet-Another-Bench-Script              #
#                     v2025-01-01                    #
# https://github.com/masonr/yet-another-bench-script #
# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #
 
Wed Jan 15 08:57:41 PM UTC 2025
 
Basic System Information:
---------------------------------
Uptime     : 0 days, 0 hours, 48 minutes
Processor  : AMD EPYC 9654 96-Core Processor
CPU cores  : 1 @ 2396.398 MHz
AES-NI     : ✔ Enabled
VM-x/AMD-V : ✔ Enabled
RAM        : 958.7 MiB
Swap       : 1024.0 MiB
Disk       : 19.6 GiB
Distro     : Debian GNU/Linux 12 (bookworm)
Kernel     : 6.1.0-21-amd64
VM Type    : KVM
IPv4/IPv6  : ✔ Online / ✔ Online
 
IPv6 Network Information:
---------------------------------
ISP        : DMIT Cloud Services
ASN        : AS906 DMIT Cloud Services
Host       : DMIT Cloud Services
Location   : Los Angeles, California (CA)
Country    : United States
 
fio Disk Speed Tests (Mixed R/W 50/50) (Partition /dev/vda1):
---------------------------------
Block Size | 4k            (IOPS) | 64k           (IOPS)
  ------   | ---            ----  | ----           ---- 
Read       | 62.54 MB/s   (15.6k) | 1.07 GB/s    (16.7k)
Write      | 62.65 MB/s   (15.6k) | 1.07 GB/s    (16.8k)
Total      | 125.19 MB/s  (31.2k) | 2.15 GB/s    (33.6k)
           |                      |                     
Block Size | 512k          (IOPS) | 1m            (IOPS)
  ------   | ---            ----  | ----           ---- 
Read       | 1.02 GB/s     (1.9k) | 1.01 GB/s      (987)
Write      | 1.07 GB/s     (2.1k) | 1.07 GB/s     (1.0k)
Total      | 2.09 GB/s     (4.0k) | 2.08 GB/s     (2.0k)
 
iperf3 Network Speed Tests (IPv4):
---------------------------------
Provider        | Location (Link)           | Send Speed      | Recv Speed      | Ping           
-----           | -----                     | ----            | ----            | ----           
Clouvider       | London, UK (10G)          | 674 Mbits/sec   | 543 Mbits/sec   | 129 ms         
Leaseweb        | Singapore, SG (10G)       | 697 Mbits/sec   | 642 Mbits/sec   | 166 ms         
Leaseweb        | NYC, NY, US (10G)         | 984 Mbits/sec   | 748 Mbits/sec   | 63.2 ms        
 
iperf3 Network Speed Tests (IPv6):
---------------------------------
Provider        | Location (Link)           | Send Speed      | Recv Speed      | Ping           
-----           | -----                     | ----            | ----            | ----           
Clouvider       | London, UK (10G)          | 713 Mbits/sec   | 601 Mbits/sec   | 129 ms         
Leaseweb        | Singapore, SG (10G)       | 745 Mbits/sec   | 705 Mbits/sec   | 166 ms         
Leaseweb        | NYC, NY, US (10G)         | 987 Mbits/sec   | 697 Mbits/sec   | 63.0 ms        
 
Geekbench 5 Benchmark Test:
---------------------------------
Test            | Value                         
                |                               
Single Core     | 1551                          
Multi Core      | 1539                          
Full Test       | https://browser.geekbench.com/v5/cpu/23265464
 
Geekbench 6 Benchmark Test:
---------------------------------
Test            | Value                         
                |                               
Single Core     | 1585                          
Multi Core      | 938                           
Full Test       | https://browser.geekbench.com/v6/cpu/9953190
 
YABS completed in 17 min 56 sec

融合怪

-------------------------------------VPS融合怪测试-------------------------------------
版本:v0.1.4
测评频道: https://t.me/vps_reviews
Go项目地址:https://github.com/oneclickvirt/ecs
Shell项目地址:https://github.com/spiritLHLS/ecs
--------------------------------------系统基础信息--------------------------------------
 CPU 型号            : AMD EPYC 9654 96-Core Processor @ 2396.398 MHz
 CPU 数量            : 1 Virtual CPU(s)
 CPU 缓存            : 512 KB
 AES-NI              : ✔️ Enabled
 VM-x/AMD-V/Hyper-V  : ✔️ Enabled
 内存                : 283.62 MB / 958.71 MB
 气球驱动            : ✔️ Enabled
 虚拟内存 Swap       : 0.00 MB / 1024.00 MB
 硬盘空间            : 3.69 GB / 19.60 GB
 启动盘路径          : /dev/vda1
 系统                : debian 12.9 [x86_64] 
 内核                : 6.1.0-21-amd64
 系统在线时间        : 0 days, 00 hours, 34 minutes
 时区                : UTC
 负载                : 0.17 / 0.10 / 0.03
 虚拟化架构          : KVM
 NAT类型             : Full Cone
 TCP加速方式         : bbr
 IPV4 ASN            : AS906 DMIT
 IPV4 Location       : Los Angeles / California / United States
 IPV6 ASN            : AS906 DMIT
 IPV6 Location       : Los Angeles / California / United States
 IPv6 子网掩码       : /64
--------------------------------CPU测试-通过sysbench测试--------------------------------
1 线程测试(单核)得分:   4364.81
--------------------------------内存测试-通过sysbench测试---------------------------------
单线程顺序写速度: 30915.78 MB/s(32.42K IOPS, 5s)
单线程顺序读速度: 46886.73 MB/s(49.16K IOPS, 5s)
-----------------------------------硬盘测试-通过fio测试-----------------------------------
测试路径      块大小   读测试(IOPS)            写测试(IOPS)            总和(IOPS)
/root         4k       62.55 MB/s(15.6k)       62.66 MB/s(15.7k)       125.21 MB/s(31.3k)      
/root         64k      1.07 GB/s(16.6k)        1.07 GB/s(16.7k)        2.14 GB/s(33.4k)        
/root         512k     1.02 GB/s(1995)         1.08 GB/s(2101)         2.10 GB/s(4096)         
/root         1m       1.01 GB/s(989)          1.08 GB/s(1055)         2.09 GB/s(2044)         
-------------------------------------跨国流媒体解锁--------------------------------------
IPV4:
============[ 跨国平台 ]============
Dazn                      Banned
Disney+                   NO (forbidden-location)
Netflix                   Restricted (Originals Only)
Netflix CDN               US
YouTube Region            YES (Region: US)
YouTube CDN               LAX
Amazon Prime Video        YES (Region: US)
Paramount+                YES
TVBAnywhere+              YES (Region: US)
IQiYi                     YES (Region: US)
Viu.com                   YES
Spotify Registration      NO
Steam Store               YES (Community Available) (Region: US)
ChatGPT                   YES (Region: US)
Sora                      YES (Region: US)
Gemini                    YES (Region: USA)
MetaAI                    YES (Region: US)
Wikipedia Editability     NO
Reddit                    NO
TikTok                    YES (Region: US)
Bing Region               YES (Risky) (Region: US)
Instagram Licensed Audio  YES
KOCOWA                    YES
SonyLiv                   NO (Proxy Detected) (Region: US)
OneTrust                  YES (Region: US CALIFORNIA)
GoogleSearch              YES
-------------------------------------三网回程线路检测-------------------------------------
北京电信 219.141.140.10  移动CMIN2  [精品线路] 
北京联通 202.106.195.68  移动CMIN2  [精品线路] 联通4837   [普通线路] 
北京移动 221.179.155.161 移动CMIN2  [精品线路] 
上海电信 202.96.209.133  移动CMIN2  [精品线路] 电信163    [普通线路] 
上海联通 210.22.97.1     移动CMIN2  [精品线路] 
上海移动 211.136.112.200 移动CMIN2  [精品线路] 
广州电信 58.60.188.222   移动CMIN2  [精品线路] 电信163    [普通线路] 
广州联通 210.21.196.6    移动CMIN2  [精品线路] 联通4837   [普通线路] 
广州移动 120.196.165.24  移动CMIN2  [精品线路] 
成都电信 61.139.2.69     移动CMIN2  [精品线路] 
成都联通 119.6.6.6       移动CMIN2  [精品线路] 联通4837   [普通线路] 
成都移动 211.137.96.205  移动CMIN2  [精品线路] 
-------------------------------------三网回程路由检测-------------------------------------
[NextTrace API] preferred API IP - 104.21.48.1 - 51.02ms - Misaka.LAX
广州电信 - ICMP v4 - traceroute to 58.60.188.222, 30 hops max, 52 byte packets
0.24 ms      AS906      [DMIT-BB]          Anycast, Anycast, DMIT.com 
0.64 ms      AS906      [DMIT-BB]          美国, 加利福尼亚, 洛杉矶, DMIT.com 
0.78 ms      AS906      [DMIT-BB]          美国, 加利福尼亚, 洛杉矶, DMIT.com 
126.91 ms    AS58807    [CMIN2-NET]        美国, 加利福尼亚, 洛杉矶, cmi.chinamobile.com  移动
126.17 ms    AS58807    [CMIN2-NET]        中国, 上海, cmi.chinamobile.com  移动
127.55 ms    AS9808     [CMNET]            中国, 上海, chinamobileltd.com  移动
127.09 ms    AS9808     [CMNET]            中国, 上海, chinamobileltd.com  移动
128.02 ms    AS9808     [CMNET]            中国, 上海, chinamobileltd.com 
167.80 ms    AS9808     [CMNET]            中国, 广东, 广州, chinamobileltd.com  移动
158.20 ms    AS9808     [CMNET]            中国, 广东, 广州, chinamobileltd.com  移动
*
207.43 ms    AS4134     [CHINANET-BB]      中国, 广东, 广州, www.chinatelecom.com.cn  电信
156.82 ms    AS134774   [CHINANET-GD]      中国, 广东, 深圳, chinatelecom.cn  电信
*
161.06 ms    AS4134                        中国, 广东, 深圳, www.chinatelecom.com.cn  电信
广州联通 - ICMP v4 - traceroute to 210.21.196.6, 30 hops max, 52 byte packets
0.22 ms      AS906      [DMIT-BB]          Anycast, Anycast, DMIT.com 
0.48 ms      AS906      [DMIT-BB]          美国, 加利福尼亚, 洛杉矶, DMIT.com 
0.84 ms      AS906      [DMIT-BB]          美国, 加利福尼亚, 洛杉矶, DMIT.com 
126.73 ms    AS58807    [CMIN2-NET]        美国, 加利福尼亚, 洛杉矶, cmi.chinamobile.com  移动
126.09 ms    AS58807    [CMIN2-NET]        中国, 上海, cmi.chinamobile.com  移动
126.20 ms    AS9808     [CMNET]            中国, 上海, chinamobileltd.com  移动
126.14 ms    AS9808     [CMNET]            中国, 上海, chinamobileltd.com  移动
126.98 ms    AS9808     [CMNET]            中国, 上海, chinamobileltd.com  移动
154.14 ms    AS9808     [CMNET]            中国, 广东, 广州, chinamobileltd.com  移动
153.71 ms    AS9808     [CMNET]            中国, 广东, 广州, chinamobileltd.com  移动
269.49 ms    AS4837     [CU169-BACKBONE]   中国, 广东, 广州, chinaunicom.cn 
*
167.66 ms    AS17816    [APNIC-AP]         中国, 广东, 深圳, chinaunicom.cn  联通
181.77 ms    AS17623    [APNIC-AP]         中国, 广东, 深圳, chinaunicom.cn  联通
168.55 ms    AS17623                       中国, 广东, 深圳, chinaunicom.cn  联通
广州移动 - ICMP v4 - traceroute to 120.196.165.24, 30 hops max, 52 byte packets
0.23 ms      AS906      [DMIT-BB]          Anycast, Anycast, DMIT.com 
2.24 ms      AS906      [DMIT-BB]          美国, 加利福尼亚, 洛杉矶, DMIT.com 
0.64 ms      AS906      [DMIT-BB]          美国, 加利福尼亚, 洛杉矶, DMIT.com 
126.17 ms    AS58807    [CMIN2-NET]        美国, 加利福尼亚, 洛杉矶, cmi.chinamobile.com  移动
126.09 ms    AS58807    [CMIN2-NET]        中国, 上海, cmi.chinamobile.com  移动
126.11 ms    AS9808     [CMNET]            中国, 上海, chinamobileltd.com  移动
126.24 ms    AS9808     [CMNET]            中国, 上海, chinamobileltd.com  移动
126.56 ms    AS9808     [CMNET]            中国, 上海, chinamobileltd.com  移动
148.94 ms    AS9808     [CMNET]            中国, 北京, chinamobileltd.com  移动
150.48 ms    AS9808     [CMNET]            中国, 北京, chinamobileltd.com  移动
*
152.08 ms    AS56040    [APNIC-AP]         中国, 广东, 深圳, gd.10086.cn  移动
--------------------------------------就近节点测速--------------------------------------
位置            上传速度        下载速度        延迟            丢包率          
Speedtest.net   1041.71 Mbps    998.97 Mbps     0.33 ms         0.0%            
洛杉矶          1047.87 Mbps    1001.83 Mbps    0.67 ms         0.0%            
法兰克福        556.37 Mbps     885.65 Mbps     148.49 ms       0.0%            
联通上海5G      723.41 Mbps     375.84 Mbps     151.79 ms       2.2%            
联通Wu Xi       808.67 Mbps     803.87 Mbps     149.33 ms       0.0%            
电信浙江        594.87 Mbps     604.07 Mbps     147.60 ms       0.0%
电信浙江        597.95 Mbps     618.77 Mbps     134.21 ms       0.0% 
移动Beijing     903.87 Mbps     388.01 Mbps     149.03 ms       0.0%            
----------------------------------------------------------------------------------
花费          : 8 分 31 秒
时间          : Wed Jan 15 20:52:03 UTC 2025
----------------------------------------------------------------------------------

DMIT 总结

  • 性能:DMIT升级过一次配置,CPU性能非常不错,磁盘 IO 也是 nvme 水准;
  • 线路:三网 CMIN2 回程(移动高端优化线路),无晚高峰波动,稍逊于电信 CN2GIA,奈何 CMIN2 给的太多了(流量);
  • 灵度:DMIT 是2017 成立的大厂了和瓦工一类的,灵度无需担心;
  • 价格:39.9 美元/年的价格,1T 的三网 CMIN2 回程,价格相当不错!
  • 直达链接:https://www.dmit.io/aff.php?aff=9154&pid=188

WordPress 是如何缓存的?对象缓存(Object Cache)详细介绍和使用!

任何技术要彻底了解它是怎么工作的,则要去了解它的机制和原理,WordPress 优化也是一样,如果要深度理解如何优化 WordPress,那么就要去了解 WordPress 对象缓存的原理和机制。

所以那么今天就来详细讲解一下 WordPress 缓存的底层原理对象缓存(Object Cache),以及在开发的时候如何使用它对 WordPress 进行加速。

WordPress 对象缓存和服务器设置

WordPress 对象缓存(英文名是:Object Cache)就是 WordPress 的缓存机制,它的主要功能是把数据库查询结果或者复杂运算的结果按照 Key-Value 这样的方式存储到对象里面,此外 WordPress 还支持按照 Group 来按组划分,以避免缓存内容的冲突。下次进行同样操作的时候,可以让直接从这个对象中取出数据,不用重复到数据库中或者其他外部获取数据。

WordPress 对象缓存和服务器设置关系很大,如果系统开启了 #Memcached# 内存缓存,则这个对象是直接存入到内存,在数据未过期之前,以后再次读取这个数据都是直接从内存中读取的,这样效率和速度都非常快的。

如果服务器不支持内存缓存的话,则只能保证在当前页面(PHP同个进程下)下同样的查询或者操作不再重复从数据库中读取了。

WordPress 对象缓存的函数

WordPress 对象缓存技术使用是非常简单的,其核心就是掌握下面下面这四个函数:

  • 添加数据到缓存中:
    wp_cache_add($key, $data, $group='', $expire=0)
  • 设置数据到缓存中:
    wp_cache_set($key, $data, $group='', $expire=0)
  • 获取缓存中的数据:
    wp_cache_get($key, $group='', $force=false, &$found=null)
  • 删除缓存中的数据:
    wp_cache_delete($key, $group='')

这四个函数会涉及到参数我罗列到一起简单讲下,下面知道个大概,可以收藏,方便使用的时候回来查看,重点还是后面的应用:

参数解释
$key数据在缓存中的健名
$data要缓存的数据,获取和删除函数无需用这个参数
$group缓存要添加到的组
$expire过期时间,可选参数,获取和删除函数无需用这个参数
如果是默认缓存,这个参数没用,如果是内存缓存,是设置缓存的时间。
单位是秒,默认为0(0 的意思就是永远,不会自动过期)
$force这个是获取缓存函数独有的函数,设置为 true 则强制使用持久缓存更新本地缓存
$found这个也是获取缓存函数独有的函数,它是一个引用参数,用于存储是否在缓存中找到 key,可以用于消除返回 false 的歧义

使用 WordPress 对象缓存

下面以我以 WordPress 相关文章为例,讲讲如何使用 WordPress 对象缓存。

我们知道 WordPress 相关文章插件是通过 tag 和分类来获取相关文章,文章使用相同的 tag 和分类越多,则认为为相关性越强,这样就需要进行多个表联合查询来获取相关文章,连表查询效率一般是比较差的。比如下面是一个比较通用的从数据库中查找相关文章的函数:

function wpjam_get_related_posts($post_id){
	global $wpdb;

	$term_ids   = wp_get_post_terms($post_id, ['category', 'post_tag'], ['fields' => 'ids']);
	$terms_ids  = implode(',', $term_ids);

	$related_posts = $wpdb->get_results("
		SELECT object_id, COUNT(*) as count
		FROM $wpdb->term_relationships
		WHERE term_taxonomy_id IN ($terms_string) AND object_id != $post_id
		GROUP BY object_id
		ORDER BY count DESC
		LIMIT 10"
	);

	foreach($related_posts as &$post){
		$post = get_post($post->object_id);
	}

	return $related_posts;
}

上面的函数,首先获取文章的标签和分类,然后基于使用相同的标签和分类的数量,通过 SQL 获取相似度最高的 10 篇文章的 ID,然后再相应获取对应的文章(这里为了简化,一般应该要根据文章 ID 批量文章,防止同时多条 SQL 请求)。

但是另外一方面,一篇文章,如果它的标签和分类没有修改的话,那么它的相关文章在一段时间内是不会变动的,所以相关文章的功能就非常适合使用 WordPress 对象缓存进行缓存加速加速。

我们就可以使用 wp_cache_set 函数就是把把相关文章的数据写入缓存的例子,使用当前 post_id 作为 key,related_posts 作为 group,缓存时间为一个小时,即 3600 秒。

$related_posts_data = wpjam_get_related_posts($post->ID);
wp_cache_set($post->ID,$related_posts_data,'related_posts',3600);

把数据存到缓存对象之后,在显示相关文章的时候,就可以使用 wp_cache_get 调用这个对象缓存来使用。

一般的流程是这样的,首先检查下是否已经有相应的缓存,如果你要的信息没有在缓存中,或者已经过期,wp_cache_get() 会返回 false,这时,你就要去数据库中重新获取这些信息,否则就返回在缓存中的信息。

$related_posts_data = wp_cache_get($post->ID,'related_posts');

if(false === $related_posts_data){
	$related_posts_data = wpjam_get_related_posts($post->ID);
	wp_cache_set($post->ID,$related_posts_data,'related_posts',3600);
}

因为设置了一个小时,相关文章的数据就失效,再次显示的时候会重新请求,,如果你在后台更改了设置,需要立即清理缓存,可以通过相关的 Hook 使用 wp_cache_delete 进行清理:

wp_cacache_delete($post->ID,'related_posts');

这里只是简单删除一下,更详细怎么使用 Hook 的例子,可以去 #WPJAM Basic# 的相关文章扩展中查看详情。

WPJAM 终极方法

通过上面的例子,看到使用 object_cache 都是首先要使用 wp_cache_get 函数去获取,如果不存在,再使用 wp_cache_set 函数去存储,有没有更加方便的方法呢?

有的,#WPJAM Basic# 提供了一个 wpjam_cache 的方法,可以将这个过程合并了,比如上面的例子,可以通过下面的代码实现:

$related_posts_data = wpjam_cache($post->ID,'related_posts', fn()=> wpjam_get_related_posts($post->ID), 3600);

它有四个参数,前面两个和 wp_cache_get() 函数一样,第三个参数是一个回调函数,它会在对象缓存不存在的时候被调用,获取数据并存到缓存中,从而实现自动实现缓存的过程,第四个是缓存时长。可以说除了第三个参数之外,其他参数和 wp_cache_xxx 函数的参数基本一致,使用也更加简洁,是一种高阶函数的写法。

总结

WordPress 对象缓存(Object Cache)是 WordPress 缓存机制,是深入了解对 WordPress 优化的基础,如果要熟悉 WordPress 开发和应用,都要有掌握好他。此外,WPJAM Basic 集成的 wpjam_cache 函数进一步提高使用效率,只需一步就实现 WordPress 对象缓存。


WPJAM Basic 插件已经集成了 Memcached,下载 WPJAM Basic 之后,将 wpjam-basic/template/ 目录下的 object-cache.php 文件复制到 wp-content 目录下即可。

「用户管理」:一键实现用户名称优化,用户安全增强,自定义头像等多项功能 WordPress 插件

这是基于 WPJAM Basic 的超强的 WordPress 用户管理的插件,有多强大呢,首先看后台的设置界面:

可以说它把 WordPress 相关的用户管理功能都集成了,简单数一数就实现了十多个 WordPress 用户相关功能:

  1. 屏蔽个性化设置
  2. 屏蔽姓氏和名字设置
  3. 取消显示名称设置
  4. 开启别名设置
  5. 隐藏用户登录名
  6. 开启登录次数限制
  7. 用户最后登录时间
  8. 取消「应用程序密码」
  9. 按注册时间排序
  10. 以此身份登陆
  11. 生成密码重置链接
  12. 自定义用户头像
  13. 默认用户头像

下面我们分成五大模块分别来介绍 WPJAM 的「用户管理插件」具体实现了那些功能:

屏蔽个性化设置

WordPress后台个人资料用户可以设置「可视化编辑器」,「语法高亮」,「配色方案」,「键盘快捷键」,「工具栏」,「语言」等这些个性化选项,如下图:

这些选项 WordPress 都是存储到 usermeta 表里面,如果 WordPress 有大量的用户,每个用户会占用7个选项,那么 usermeta 表很快就会爆炸。

比如我运营的 WordPress 站点,有几十万用户,usermeta 表的数据如果不清理的话,已经千万级了,查点东西都慢的要死,如果你和我有一样的困扰,那就可以在插件中勾选实现屏蔽用户的个性化设置,直接采用使用系统全局的默认值。然后还可以根据自己的需求删除这些选项。

用户名称优化

在默认情况下,WordPress 后台个人资料页面中,关于用户的姓名相关的设置是这样的:

是不是有点繁琐,并且很多字段也是存到 usermeta 表中的,我个人觉得关于用户昵称的设置,尽量简洁就好,所以名字和姓氏一般就不需要用户输入,公开显示的名字直接为昵称就好了,所以插件首先提供了下面两个选项:

  • 屏蔽姓名设置:屏蔽了姓氏和名字设置,简化后台个人资料界面设置。
  • 显示名称设置:取消显示名称选择器,直接使用昵称作为显示名称。

另外插件还支持开启了别名设置,是的,我们不仅仅做减法,偶尔也做下加法,这里可以让用户可以编辑自己的别名(user_nicename),这样只要不使用和登录名相同的别名,作者文章链接就不会暴露用户名,当然没有设置别名,插件还是有安全选项来实现防止用户名暴露。

所以优化之后最终的用户界面非常简洁,如下所示:

安全增强

WordPres 用户安全增强体现在两个地方,首先是隐藏登录名,不要让攻击者猜到用户名,然后是开启登录限制,防止密码被暴力破解,插件也提供这两方面的选项:

首先说一下如何隐藏登录名,如果用户没有修改过别名(user_nicename),那么他的别名和登录名(user_login)是一样的,然后作者文章链接或者其他地方就会暴露登录名,为了进一步防止登录名暴露,我们提供了隐藏登录名的选项:

勾选「防止登录名暴露」之后,如果用户的 user_nicenameuser_login 是一样的情况下:

1. 作者文章链接使用 author_id 代替 user_nicename,并且原来的作者链接直接设置为 404 页面,防止用户名暴露

2. user_login 不出现在 body_classcomment_class 中。

3. 隐藏登录失败时候未知用户名和密码不正确的错误信息,这两种情况都显示「用户名或者密码错误」,让攻击者猜去。😁

4. 取消作者相关的 sitemap 以及 REST API 中可以查看所有发布过文章的用户信息列表的中的登录名。

如果真的被攻击者猜到了登录名,那么我们还可以开启登录限制,限制登录失败次数,这样就可以防止密码被暴力破解了,进一步做到安全。

功能增强

除了安全增强之外,我们还增加了一个小功能和屏蔽一个功能,分别是记录用户最后登录时间和取消「应用程序密码」功能:

首先新增记录用户最后登录时间,用户登录之后,在后台用户列表就会显示该用户的最后登录时间,并且支持按照用户最后登录时间进行排序。

默认情况下在后台个人资料页面可以设置「应用程序密码」:

应用程序密码允许通过非交互式系统(例如 XML-RPC 或 REST API)进行身份验证,而无需提供您的实际密码。应用密码可以随时撤销。它们不能用于通过传统方式登录您的网站。

很多人看到这个其实是稀里糊涂,简单说他就是用于 APP 或者小程序通过接口来登录的,但是基本上来说,我们用不到这个功能,所以默认建议屏蔽它。

后台用户列表

对于管理员经常使用的用户列表,也新增一些功能和操作:

首先用户可以除了可以按照上面提示按照最后登录事件排序之外,也可以按照用户注册时间排序,只要你勾选了用户列表里的第一个选项,此外在用户列表页面新增两个操作「以此身份登陆」和「生成密码重置链接」:

如果你是 WordPress 开发者,「以此身份登陆」这个功能特别实用,在用户列表界面,管理员可以轻松以用户的身份登录后台,这样用户说他碰到什么问题,就可以直接登录他的账号去看了,而不是问他要账号密码,这个多难为情啊。😳

WordPress 原来「发送密码重置邮件」这个功能是直接发送密码重置邮件给用户,用户在邮箱里面直接点击操作,改成「生成密码重置链接」,则管理员直接获取密码重置链接,可以通过微信或者其他的社交媒体工具发给用户。

头像设置

在后台个人资料页,用户可以自定义自己的头像。

如果用户没有设置头像,管理员可以设置默认头像,然后随机给用户使用:

最后用户头像还多加一个选项,就是如果用户已经在 Gravatar 里面设置了头像怎么办?有两个选项,从默认中随机选一个,继续使用 Gravatar 的设置。

总结

通过上面的介绍,是不是非常强大,目前我所有用户相关的功能整合到 WPJAM-User 的插件中,只需后台简单的勾选就可以实现绝大部分用户安全和管理相关的功能。


「WordPress果酱」知识星球福利插件基于 WPJAM Basic 开发,加入「WordPress果酱」知识星球,即可下载:

插件 简介
抓取公众号图文

支持一键同步微信公众号文章到 WordPress 博客,并支持一键将文章中所有图片都下载到 WordPress 媒体库。

搜索优化

WordPress 最强的搜索优化插件,支持限制每个 IP 每分钟搜索次数,达到上限之后屏蔽搜索时长,还可以限制搜索关键词的长度,搜索结果页面限制只显示「搜索结果」,还有以下搜索功能增强:

1. 只搜索文章标题,不搜索文章内容和摘要。
2. 当搜索关键词为空时重定向到首页,只有一篇文章时重定向到文章
3. 后台文章列表支持搜索ID。
4. 支持搜索自定义字段。

编辑器优化

一键增强 WordPress 经典 TinyMCE 编辑器:

1. 增加下划线,背景颜色,两端对齐,字体和大小设置,以及内容分页按钮。
2. 新增插入表格功能。
3. 直接插入屏幕截图。

标题设置

一键设置 WordPress 所有页面的页面标题,通过规则方式让博主可以自定义 WordPres 首页,分类,文章类型,文章详情都所有页面的页面标题。

登录优化

一键优化 WordPress 登录注册界面,并支持第三方账号登录和绑定,目前已经支持微信公众号(所有类型),微信小程序,手机号码第三方平台。

内容模板

实现在内容中插入一段共用的内容模板,通过短代码(shortcode)的方式来实现的,支持统一修改,目前支持普通的内容模板,表格内容模板和卡片内容模板三种类型。

用户管理

最强 WordPress 一键用户管理插件,一键实现以下12个功能:

1. 屏蔽个性化设置
2. 屏蔽姓氏和名字设置
3. 取消显示名称设置
4. 开启别名设置
5. 隐藏用户登录名
6. 开启登录次数限制
7. 用户最后登录时间
8. 按注册时间排序
9. 以此身份登陆
10. 生成密码重置链接
11. 自定义用户头像
12. 默认用户头像

分类管理

这是一个全能的 WordPress 分类管理插件:

1. 层式管理分类
2. 限制分类层级
3. 分类拖动排序
4. 使用数字固定链接
5. 首页文章支持分类过滤
6. 后台文章列表支持分类筛选过滤
7. 后台文章列表支持分类多重筛选

评论增强

这是一个 WordPress 评论增强插件,支持评论置顶,评论点赞和按照点赞数排序。

图片集

1. 给媒体创建个分类「图片集 | collection」
2. 图片分类限制为二级
3. 取消图片编辑入口
4. 附件页面直接图片链接。

配置器

全自动 WordPress 配置器,不用一行代码就可以开发。
支持自定义文章类型,自定义字段,自定义分类,分类选项,全局选项。

Script Loader

通过恢复 WordPress 联合加载方式来优化 WordPress 后台脚本加载。

外部链接

将文章或评论中的外部链接加上安全提示的中间页。
让用户确认之后再跳转,并还支持添加 nofollow rel 属性。

话题标签

文章中插入 #话题标签#。
如果是内部链接,直接跳转,
标签或者分类,则自动转换成标签或分类链接,
否则跳转到搜索链接。

格式文章

在 WordPress 实现真正的文章格式

草稿分享

一键生成草稿临时分享链接
并可设置分享链接的有效期

文章专题

设置文章专题,并在文章末尾显示一个文章专题列表。

文章隐藏

设置文章在列表⻚不显示,并且可以根据不同平台进行设置

Meta Data

可视化管理 WordPress Meta 数据,支持所有内置的 Meta 数据:
Post Meta,Term Meta,User Meta 和 Comment Meta。

站点选项

查看和管理所有非 WordPress 系统自动生成的站点选项。
如果你觉得某个选项无用,可以直接删除它。

后台论坛

WordPress 后台论坛,支持创建帖子,分组,消息。

微信小程序

微信小程序 WordPress 基础插件,包含基础类库和管理。

微信群二维码

轮询显示微信群二维码,突破微信群100人限制。

文章置顶

支持置顶文章排序和分类文章置顶的 WordPress 插件

静态文件

一键合并 WordPress 插件和主题的 JS 和 CSS 文件,加快页面加载速度

Debug

一键检测 WordPress 运行效率。

需要别人登录你的 WordPress,再也不需要给账号密码了,现在可以给「一次登录链接」了!

前面我们介绍「为什么你的 WordPress 站点老是被黑?」的时候,说到大胡子和我卖 Modular 主题,我们的售后是很负责的,😎 会在用户允许的情况下,进入后台帮忙解决,这时候我们需要对方提供一下后台的账号密码,然后就接触到了很多简单到令人发指的密码,所以网站就被黑了。

说到要求对方提供账号密码这个事情,有用户提出,其实给人账号密码也很不安全,最好是创建一个新的管理员账号,这样就不会不小心暴露自己常用密码。

一次登录链接

但是创建一个新的管理员账号也是麻烦,用完又要删除或者去修改密码。那么有没有更好的方法呢?今天想到一个好方法,就是给某个用户创建「一次登录链接」,只能使用一次,这样就不用担心「售后」的时间。✌️

我就把该功能增加到「用户管理」功能,默认是开启的:

然后在用户列表就会有「生成链接」的操作,我把原来的「生成重置密码链接」一起合并进来:

点击之后,链接类型选择「一次登录」,链接有效期默认是 3 个小时,意思是 3 个小时内该链接点击都可以登录,过了就不行。

然后复制该链接,发送给帮你解决问题的好人,就可以了。

WPJAM「用户管理」

这次一次登录链接功能,我集成到了 WPJAM 这个「用户管理」插件中,它是 WordPress 果酱知识星球福利插件,加入「WordPress果酱」知识星球(长按下图二维码)即可下载:

Bearblog 风格点赞按钮

** 本文基于 第三夏尔Booooombenji 的 Hugo 插件代码,修改为 WordPress 插件:DayuGuo/bear-style-like-button

功能

在 WordPress 的文章类型页面下方添加两个按钮:「点赞」和「支持」。

  • 「点赞」:参考 Bearblog 点赞风格,以简洁版向上箭头为图标,配上一个轻柔的跳动动画。设置界面支持导出点赞数据。
  • 「支持」:可在 WordPress 插件设置中修改链接,跳转到特定页面。

效果见本文下方,大家可以试试。

安装

本插件可在 Github Releases 中 下载:DayuGuo/bear-style-like-button ,并在 WordPress 后台上传安装。

如有任何疑问可在评论区留言。

为什么你的 WordPress 站点老是被黑?根本就没啥复杂的原因,就是因为……

因为你的 WordPress 密码太简单了,坏人根本都不用什么牛逼工具或者利用什么 0day 漏洞,只要简单撞下库就能破解!

为什么这么说呢?

因为大胡子和我卖 Modular 主题,我们的售后是很负责的,除了在群里回答问题之外,一些用户复杂的问题,在说不清楚的情况下,我们会在用户允许的情况下,进入后台帮忙解决,甚至他们站点被黑了也会找我们帮忙解决,这时候我们需要对方提供一下后台的账号密码,然后就接触到了很多简单到令人发指的密码。😅

这些密码简单到什么程度,请看下面截图:

所以根本不用在讲什么大道理,这么多赤裸裸和血淋淋的事实,大家应该明白为什么 WordPress 会被黑吧。如果你的密码还是那么简单,快去改一下密码,不然下次被黑可能就是你了。😂

并且 WordPress 后台也会提示你的密码是否足够复杂了,如果是 123456 这种,就会显示非常弱:

如果是累下面这种 WordPress 自动生成的,则会显示强:

建议大家都一定要设置成「强」的密码!

最后大家来看看我们的 Modular 主题,我们售后很负责的。另外你有没有朋友,使用很简单密码的那种,来分享你朋友简单的密码。😁

如果基于 DeepSeek 开发 WordPress 的插件,它自己会选择什么功能?

今年最火的就是 DeepSeek 了,各种新闻,把英伟达的股票都干没了10 几个点。我也在想做一个基于 DeepSeep 的 WordPress 插件,但是做什么方向的的功能呢?要不这个功能也让 DeepSeek 帮我们也想想?

DeepSeek 的使用和 ChatGPT 之类其他的 AI 工具是有区别,他是基于推理型的大模型,而不是指令型的大模式,所以使用 DeepSeek 根本不需要提示词,直接就好了。

所以我的问题就直接把自己的目的告诉,我想写个 DeepSeek 的插件,需要给些功能灵感:

我想基于 DeepSeek 写个 WordPress 插件,在方向上,基于你对自己理解,你觉得可以做那些功能呢,你可以给我一些灵感吗?

然后我 开启了深度思考模式,DeepSeek 给出了它对这个问题的推理过程:

然后他给出了自己的建议,它还非常贴心的分成几个小标题,一共提供内容生产力、智能交互增强、数据智能分析和效率增强功能四大方向,每个方向还提供了2 个小功能,大家看看这些功能建议如何,并且它还非常贴心的提供技术实现要点,以及如何赚钱,也就是商业化建议

基于 DeepSeek 的能力和 WordPress 生态需求,以下是几个值得探索的插件开发方向,按优先级排序并附具体实现思路:


一、内容生产力工具(核心场景)

  1. AI 文章助手
    • 自动草稿生成:根据用户输入关键词自动生成结构化大纲(支持Markdown)
    • 智能续写/改写:通过浮动工具栏实现选中内容的优化/扩写/简写
    • SEO 增强:实时分析内容并推荐关键词密度、生成meta描述
    • 技术实现:结合Gutenberg编辑器API + 内容缓存机制降低API调用成本
  2. 多模态内容生成
    • 基于文本描述自动生成特色图片(需集成DeepSeek-Visual)
    • 智能生成文章配图说明文字(ALT文本优化)
    • 自动创建信息图描述文本

二、智能交互增强

  1. 对话式知识库
    • 将网站文档/产品目录转化为可对话的知识库
    • 实现路径:定期爬取指定页面内容构建向量数据库
    • 示例场景:客户服务机器人、产品FAQ交互
  2. 实时评论互动
    • 智能回复用户评论(可设置白名单词库限制)
    • 情感分析自动标记高风险评论
    • 支持预设行业话术模板(电商/教育等)

三、数据智能分析

  1. 流量内容洞察
    • 结合GA数据生成自然语言分析报告
    • 自动识别高跳出率页面的内容问题
    • 预测内容生命周期并提供更新建议
  2. 竞品内容监测
    • 定期抓取竞品RSS进行摘要对比
    • 生成差异化创作建议(需配置代理抓取)

四、效率增强功能

  1. 智能翻译工作流
    • 一键生成多语言版本并保持SEO结构
    • 支持术语表维护和翻译风格预设
    • 实现:WPML兼容 + 增量翻译缓存
  2. 自动化运营
    • 定期自动生成节日营销文案
    • 社交媒体帖子自动生成与排期
    • 结合Zapier实现跨平台自动化

技术实现要点

  1. 性能优化
    • 实现内容缓存池(基于文章ID的版本控制)
    • 支持异步队列处理长文本任务
    • 本地语义相似度计算减少API调用
  2. 安全合规
    • 内容审核过滤层(可对接DeepSeek审核API)
    • 用户数据脱敏处理
    • GDPR兼容设计(数据暂存策略)
  3. 扩展架构
    • 提供webhook接入点
    • 开发REST API扩展模块
    • 支持与WooCommerce等流行插件的数据打通

商业化建议

  • 分层定价策略
    • 免费版:基础内容生成(限次/水印)
    • 专业版:高级分析+多语言(订阅制)
    • 企业版:私有化部署+定制模型
  • 流量变现
    • 内置AI写作模版市场
    • 对接第三方云服务返佣
    • 提供A/B测试数据服务

建议初期聚焦内容生成核心场景,采用「AI功能+SEO工具」组合拳切入市场,后续通过用户行为数据分析逐步扩展智能运营功能。可参考Jarvis(Conversion.ai)的增长路径,但需注意WordPress生态的特殊性,强化与经典插件(Yoast SEO、Elementor)的兼容性。


大家觉得如何?希望首先实现哪个方向的插件?可以给我留言,我争取2 月份就先做个简单的插件出来给大家用用。😁

WordPress 是如何缓存的?对象缓存(Object Cache)详细介绍和使用!

任何技术要彻底了解它是怎么工作的,则要去了解它的机制和原理,WordPress 优化也是一样,如果要深度理解如何优化 WordPress,那么就要去了解 WordPress 对象缓存的原理和机制。

所以那么今天就来详细讲解一下 WordPress 缓存的底层原理对象缓存(Object Cache),以及在开发的时候如何使用它对 WordPress 进行加速。

WordPress 对象缓存和服务器设置

WordPress 对象缓存(英文名是:Object Cache)就是 WordPress 的缓存机制,它的主要功能是把数据库查询结果或者复杂运算的结果按照 Key-Value 这样的方式存储到对象里面,此外 WordPress 还支持按照 Group 来按组划分,以避免缓存内容的冲突。下次进行同样操作的时候,可以让直接从这个对象中取出数据,不用重复到数据库中或者其他外部获取数据。

WordPress 对象缓存和服务器设置关系很大,如果系统开启了 #Memcached# 内存缓存,则这个对象是直接存入到内存,在数据未过期之前,以后再次读取这个数据都是直接从内存中读取的,这样效率和速度都非常快的。

如果服务器不支持内存缓存的话,则只能保证在当前页面(PHP同个进程下)下同样的查询或者操作不再重复从数据库中读取了。

WordPress 对象缓存的函数

WordPress 对象缓存技术使用是非常简单的,其核心就是掌握下面下面这四个函数:

  • 添加数据到缓存中:
    wp_cache_add($key, $data, $group='', $expire=0)
  • 设置数据到缓存中:
    wp_cache_set($key, $data, $group='', $expire=0)
  • 获取缓存中的数据:
    wp_cache_get($key, $group='', $force=false, &$found=null)
  • 删除缓存中的数据:
    wp_cache_delete($key, $group='')

这四个函数会涉及到参数我罗列到一起简单讲下,下面知道个大概,可以收藏,方便使用的时候回来查看,重点还是后面的应用:

参数解释
$key数据在缓存中的健名
$data要缓存的数据,获取和删除函数无需用这个参数
$group缓存要添加到的组
$expire过期时间,可选参数,获取和删除函数无需用这个参数
如果是默认缓存,这个参数没用,如果是内存缓存,是设置缓存的时间。
单位是秒,默认为0(0 的意思就是永远,不会自动过期)
$force这个是获取缓存函数独有的函数,设置为 true 则强制使用持久缓存更新本地缓存
$found这个也是获取缓存函数独有的函数,它是一个引用参数,用于存储是否在缓存中找到 key,可以用于消除返回 false 的歧义

使用 WordPress 对象缓存

下面以我以 WordPress 相关文章为例,讲讲如何使用 WordPress 对象缓存。

我们知道 WordPress 相关文章插件是通过 tag 和分类来获取相关文章,文章使用相同的 tag 和分类越多,则认为为相关性越强,这样就需要进行多个表联合查询来获取相关文章,连表查询效率一般是比较差的。比如下面是一个比较通用的从数据库中查找相关文章的函数:

function wpjam_get_related_posts($post_id){
	global $wpdb;

	$term_ids   = wp_get_post_terms($post_id, ['category', 'post_tag'], ['fields' => 'ids']);
	$terms_ids  = implode(',', $term_ids);

	$related_posts = $wpdb->get_results("
		SELECT object_id, COUNT(*) as count
		FROM $wpdb->term_relationships
		WHERE term_taxonomy_id IN ($terms_string) AND object_id != $post_id
		GROUP BY object_id
		ORDER BY count DESC
		LIMIT 10"
	);

	foreach($related_posts as &$post){
		$post = get_post($post->object_id);
	}

	return $related_posts;
}

上面的函数,首先获取文章的标签和分类,然后基于使用相同的标签和分类的数量,通过 SQL 获取相似度最高的 10 篇文章的 ID,然后再相应获取对应的文章(这里为了简化,一般应该要根据文章 ID 批量文章,防止同时多条 SQL 请求)。

但是另外一方面,一篇文章,如果它的标签和分类没有修改的话,那么它的相关文章在一段时间内是不会变动的,所以相关文章的功能就非常适合使用 WordPress 对象缓存进行缓存加速加速。

我们就可以使用 wp_cache_set 函数就是把把相关文章的数据写入缓存的例子,使用当前 post_id 作为 key,related_posts 作为 group,缓存时间为一个小时,即 3600 秒。

$related_posts_data = wpjam_get_related_posts($post->ID);
wp_cache_set($post->ID,$related_posts_data,'related_posts',3600);

把数据存到缓存对象之后,在显示相关文章的时候,就可以使用 wp_cache_get 调用这个对象缓存来使用。

一般的流程是这样的,首先检查下是否已经有相应的缓存,如果你要的信息没有在缓存中,或者已经过期,wp_cache_get() 会返回 false,这时,你就要去数据库中重新获取这些信息,否则就返回在缓存中的信息。

$related_posts_data = wp_cache_get($post->ID,'related_posts');

if(false === $related_posts_data){
	$related_posts_data = wpjam_get_related_posts($post->ID);
	wp_cache_set($post->ID,$related_posts_data,'related_posts',3600);
}

因为设置了一个小时,相关文章的数据就失效,再次显示的时候会重新请求,,如果你在后台更改了设置,需要立即清理缓存,可以通过相关的 Hook 使用 wp_cache_delete 进行清理:

wp_cacache_delete($post->ID,'related_posts');

这里只是简单删除一下,更详细怎么使用 Hook 的例子,可以去 #WPJAM Basic# 的相关文章扩展中查看详情。

WPJAM 终极方法

通过上面的例子,看到使用 object_cache 都是首先要使用 wp_cache_get 函数去获取,如果不存在,再使用 wp_cache_set 函数去存储,有没有更加方便的方法呢?

有的,#WPJAM Basic# 提供了一个 wpjam_cache 的方法,可以将这个过程合并了,比如上面的例子,可以通过下面的代码实现:

$related_posts_data = wpjam_cache($post->ID,'related_posts', fn()=> wpjam_get_related_posts($post->ID), 3600);

它有四个参数,前面两个和 wp_cache_get() 函数一样,第三个参数是一个回调函数,它会在对象缓存不存在的时候被调用,获取数据并存到缓存中,从而实现自动实现缓存的过程,第四个是缓存时长。可以说除了第三个参数之外,其他参数和 wp_cache_xxx 函数的参数基本一致,使用也更加简洁,是一种高阶函数的写法。

总结

WordPress 对象缓存(Object Cache)是 WordPress 缓存机制,是深入了解对 WordPress 优化的基础,如果要熟悉 WordPress 开发和应用,都要有掌握好他。此外,WPJAM Basic 集成的 wpjam_cache 函数进一步提高使用效率,只需一步就实现 WordPress 对象缓存。


WPJAM Basic 插件已经集成了 Memcached,下载 WPJAM Basic 之后,将 wpjam-basic/template/ 目录下的 object-cache.php 文件复制到 wp-content 目录下即可。

My App Defaults 2024

记录一下过去一年的常用应用,明年此时再更新,观察是否有所改变。

📨 Mail Client: 我使用 Gmail,网易邮箱和QQ邮箱,所有邮箱在 PC 都用网页端,移动端使用各自官方 App。
📮 Mail Server: 如上。
📝 Notes: Obsidian 是主力笔记软件和数字花园发布站点TiddlyWiki 是个人维基发布站点,轻度使用 Notion 和 AnyType。
✅ To-Do: 我的待办事项记录在 Obsidian 内。
📷 iPhone Android Photo Shooting: 使用 vivo X200 Pro 系统自带相机。
🟦 Photo Management: OneDrive 和 Google Photos。
📆 Calendar: PC 端和移动端均使用系统默认日历。
📁 Cloud File Storage: 使用 OneDrive、百度云盘、夸克云盘、阿里云盘、InifiniCLOUD、阿里云 OSS 以及一部分自建存储。
📖 RSS: 目前没有使用 RSS 订阅工具,短暂试用过 follow
🙍🏻‍♂️ Contacts: 使用系统自带联系人应用。
🌐 Browser: PC 端和移动端均主力使用 Chrome,辅助 Firefox。
💬 Chat: 微信、QQ、Telegram 以及一些不以即时通讯为目的的社交应用。
🔖 Bookmarks: 主要记录在 Chrome 的阅读清单和 Obsidian 的笔记内。
📑 Read It Later: 如上。
📜 Word Processing: 写作工具主要是 Obsidian,偶尔使用 Notion 和 AnyType 辅助,极端情况下使用 Notepad– 和记事本。
📈 Spreadsheets: Microsoft Excel 和 Google Sheets。
📊 Presentations: 较少使用,主要为 Microsoft Powerpoint。
🛒 Shopping Lists: vivo 的原子笔记。
🍴 Meal Planning: 不会做饭。
💰 Budgeting and Personal Finance: Notion。
📰 News: IT之家、微博新闻、公众号订阅、即刻、X。
🎵 Music: Apple Music 和 QQ音乐。
🎤 Podcasts: 不听播客。
🔐 Password Management: 脑子。

以下是小胡文章中提到的 extra categories 部分:

✈ VPN: PC 端使用 Clash Verge,移动端使用 Surfboard
😘 Blog Platform: WordPress
⌨ Text input: PC 端使用系统自带微软输入法,小鹤双拼,移动端使用 Gboard 和 vivo 输入法 Pro。
📖 Translation app: Google 翻译和 DeepL 翻译。
📚 Reading app: 主力是微信读书,辅助 Kindle App 和学习版 ePub 文件以及实体书。
🔧 Screenshot app: PC 端和移动端均使用系统自带截图软件。
🌁 Image Hosting: 阿里云 OSS。
☁ VPS Hosting: 老薛主机CloudCone。(第一个链接是我的 aff 链接,第二个链接是小胡的 aff 链接)

除了以上 app 之外,在我国日常生活中还有许多平台类 app,如淘宝、滴滴、各类政务和银行 app 等等。有些做得很不错,有些就是一坨屎,但不得不用。当然微信和钉钉是不得不用的两坨最大的屎。

DMIT 多款美西 3 网优化的 VPS 补货了,年付仅需 39.9 美元起!

还是先简单介绍下 DMIT,DMIT 成立于2017,是一家海外 VPS 的厂商,主营中国香港、美国洛杉矶、日本东京等地区的 VPS,拥有对国内访问友好(CN2 GIA+CMIN2)的优化路线,稳定不掉速,并且基本也不超售,是著名VPS厂商搬瓦工(Bandwagonhost)的上游之一。

DMIT 39.9

为了方便大家理解,先对线路的名称做下说明:😄

  • CN2GIA 是指中国电信的高端优化路线
  • CMIN2 是指中国移动的高端优化路线

下面是这次 DMIT 这次的优惠的套餐:

LAX.EB.WEE(3网CMI2)推荐

  • 1vCPU(EPYC 9654)
  • 1GB RAM
  • 20GB SSD
  • 1000GB /月流量(1Gbps)
  • 1 IPv4 & 1 IPv6 /64
  • 39.9美元/年

测试 IP:154.17.226.2

购买链接:https://www.dmit.io/aff.php?aff=9154&pid=188

LAX.EB.CORONA(3网CMI2)

  • 1vCPU(EPYC 9654)
  • 1GB RAM
  • 20GB SSD
  • 2000GB /月流量(2Gbps)
  • 1 IPv4 & 1 IPv6 /64
  • 49.9美元/年

测试 IP:154.17.226.2

购买链接:https://www.dmit.io/aff.php?aff=9154&pid=218

LAX.Pro.MALIBU(3网CN2GIA)

  • 1vCPU(EPYC 9654)
  • 1GB RAM
  • 20GB SSD
  • 1000GB /月流量(1Gbps)
  • 1 IPv4 & 1 IPv6 /64
  • 49.9美元/年

测试 IP:154.17.2.12

购买链接:https://www.dmit.io/aff.php?aff=9154&pid=186

DMIT 测评

我们对 LAX.EB.WEE(3网CMI2)做了下基本的测试,首先是 全国 TCPing(测试IP:154.17.226.2),可以说是一片绿油油(晚间测试):

探针表现也非常稳定,三网平稳,高峰期无波澜,全天候 PING 值基本没啥变动(如果是普通路线的话,晚高峰期会 Ping 值高,降速严重)。

再看下 IP 质量报告:

YABS

# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #
#              Yet-Another-Bench-Script              #
#                     v2025-01-01                    #
# https://github.com/masonr/yet-another-bench-script #
# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #
 
Wed Jan 15 08:57:41 PM UTC 2025
 
Basic System Information:
---------------------------------
Uptime     : 0 days, 0 hours, 48 minutes
Processor  : AMD EPYC 9654 96-Core Processor
CPU cores  : 1 @ 2396.398 MHz
AES-NI     : ✔ Enabled
VM-x/AMD-V : ✔ Enabled
RAM        : 958.7 MiB
Swap       : 1024.0 MiB
Disk       : 19.6 GiB
Distro     : Debian GNU/Linux 12 (bookworm)
Kernel     : 6.1.0-21-amd64
VM Type    : KVM
IPv4/IPv6  : ✔ Online / ✔ Online
 
IPv6 Network Information:
---------------------------------
ISP        : DMIT Cloud Services
ASN        : AS906 DMIT Cloud Services
Host       : DMIT Cloud Services
Location   : Los Angeles, California (CA)
Country    : United States
 
fio Disk Speed Tests (Mixed R/W 50/50) (Partition /dev/vda1):
---------------------------------
Block Size | 4k            (IOPS) | 64k           (IOPS)
  ------   | ---            ----  | ----           ---- 
Read       | 62.54 MB/s   (15.6k) | 1.07 GB/s    (16.7k)
Write      | 62.65 MB/s   (15.6k) | 1.07 GB/s    (16.8k)
Total      | 125.19 MB/s  (31.2k) | 2.15 GB/s    (33.6k)
           |                      |                     
Block Size | 512k          (IOPS) | 1m            (IOPS)
  ------   | ---            ----  | ----           ---- 
Read       | 1.02 GB/s     (1.9k) | 1.01 GB/s      (987)
Write      | 1.07 GB/s     (2.1k) | 1.07 GB/s     (1.0k)
Total      | 2.09 GB/s     (4.0k) | 2.08 GB/s     (2.0k)
 
iperf3 Network Speed Tests (IPv4):
---------------------------------
Provider        | Location (Link)           | Send Speed      | Recv Speed      | Ping           
-----           | -----                     | ----            | ----            | ----           
Clouvider       | London, UK (10G)          | 674 Mbits/sec   | 543 Mbits/sec   | 129 ms         
Leaseweb        | Singapore, SG (10G)       | 697 Mbits/sec   | 642 Mbits/sec   | 166 ms         
Leaseweb        | NYC, NY, US (10G)         | 984 Mbits/sec   | 748 Mbits/sec   | 63.2 ms        
 
iperf3 Network Speed Tests (IPv6):
---------------------------------
Provider        | Location (Link)           | Send Speed      | Recv Speed      | Ping           
-----           | -----                     | ----            | ----            | ----           
Clouvider       | London, UK (10G)          | 713 Mbits/sec   | 601 Mbits/sec   | 129 ms         
Leaseweb        | Singapore, SG (10G)       | 745 Mbits/sec   | 705 Mbits/sec   | 166 ms         
Leaseweb        | NYC, NY, US (10G)         | 987 Mbits/sec   | 697 Mbits/sec   | 63.0 ms        
 
Geekbench 5 Benchmark Test:
---------------------------------
Test            | Value                         
                |                               
Single Core     | 1551                          
Multi Core      | 1539                          
Full Test       | https://browser.geekbench.com/v5/cpu/23265464
 
Geekbench 6 Benchmark Test:
---------------------------------
Test            | Value                         
                |                               
Single Core     | 1585                          
Multi Core      | 938                           
Full Test       | https://browser.geekbench.com/v6/cpu/9953190
 
YABS completed in 17 min 56 sec

融合怪

-------------------------------------VPS融合怪测试-------------------------------------
版本:v0.1.4
测评频道: https://t.me/vps_reviews
Go项目地址:https://github.com/oneclickvirt/ecs
Shell项目地址:https://github.com/spiritLHLS/ecs
--------------------------------------系统基础信息--------------------------------------
 CPU 型号            : AMD EPYC 9654 96-Core Processor @ 2396.398 MHz
 CPU 数量            : 1 Virtual CPU(s)
 CPU 缓存            : 512 KB
 AES-NI              : ✔️ Enabled
 VM-x/AMD-V/Hyper-V  : ✔️ Enabled
 内存                : 283.62 MB / 958.71 MB
 气球驱动            : ✔️ Enabled
 虚拟内存 Swap       : 0.00 MB / 1024.00 MB
 硬盘空间            : 3.69 GB / 19.60 GB
 启动盘路径          : /dev/vda1
 系统                : debian 12.9 [x86_64] 
 内核                : 6.1.0-21-amd64
 系统在线时间        : 0 days, 00 hours, 34 minutes
 时区                : UTC
 负载                : 0.17 / 0.10 / 0.03
 虚拟化架构          : KVM
 NAT类型             : Full Cone
 TCP加速方式         : bbr
 IPV4 ASN            : AS906 DMIT
 IPV4 Location       : Los Angeles / California / United States
 IPV6 ASN            : AS906 DMIT
 IPV6 Location       : Los Angeles / California / United States
 IPv6 子网掩码       : /64
--------------------------------CPU测试-通过sysbench测试--------------------------------
1 线程测试(单核)得分:   4364.81
--------------------------------内存测试-通过sysbench测试---------------------------------
单线程顺序写速度: 30915.78 MB/s(32.42K IOPS, 5s)
单线程顺序读速度: 46886.73 MB/s(49.16K IOPS, 5s)
-----------------------------------硬盘测试-通过fio测试-----------------------------------
测试路径      块大小   读测试(IOPS)            写测试(IOPS)            总和(IOPS)
/root         4k       62.55 MB/s(15.6k)       62.66 MB/s(15.7k)       125.21 MB/s(31.3k)      
/root         64k      1.07 GB/s(16.6k)        1.07 GB/s(16.7k)        2.14 GB/s(33.4k)        
/root         512k     1.02 GB/s(1995)         1.08 GB/s(2101)         2.10 GB/s(4096)         
/root         1m       1.01 GB/s(989)          1.08 GB/s(1055)         2.09 GB/s(2044)         
-------------------------------------跨国流媒体解锁--------------------------------------
IPV4:
============[ 跨国平台 ]============
Dazn                      Banned
Disney+                   NO (forbidden-location)
Netflix                   Restricted (Originals Only)
Netflix CDN               US
YouTube Region            YES (Region: US)
YouTube CDN               LAX
Amazon Prime Video        YES (Region: US)
Paramount+                YES
TVBAnywhere+              YES (Region: US)
IQiYi                     YES (Region: US)
Viu.com                   YES
Spotify Registration      NO
Steam Store               YES (Community Available) (Region: US)
ChatGPT                   YES (Region: US)
Sora                      YES (Region: US)
Gemini                    YES (Region: USA)
MetaAI                    YES (Region: US)
Wikipedia Editability     NO
Reddit                    NO
TikTok                    YES (Region: US)
Bing Region               YES (Risky) (Region: US)
Instagram Licensed Audio  YES
KOCOWA                    YES
SonyLiv                   NO (Proxy Detected) (Region: US)
OneTrust                  YES (Region: US CALIFORNIA)
GoogleSearch              YES
-------------------------------------三网回程线路检测-------------------------------------
北京电信 219.141.140.10  移动CMIN2  [精品线路] 
北京联通 202.106.195.68  移动CMIN2  [精品线路] 联通4837   [普通线路] 
北京移动 221.179.155.161 移动CMIN2  [精品线路] 
上海电信 202.96.209.133  移动CMIN2  [精品线路] 电信163    [普通线路] 
上海联通 210.22.97.1     移动CMIN2  [精品线路] 
上海移动 211.136.112.200 移动CMIN2  [精品线路] 
广州电信 58.60.188.222   移动CMIN2  [精品线路] 电信163    [普通线路] 
广州联通 210.21.196.6    移动CMIN2  [精品线路] 联通4837   [普通线路] 
广州移动 120.196.165.24  移动CMIN2  [精品线路] 
成都电信 61.139.2.69     移动CMIN2  [精品线路] 
成都联通 119.6.6.6       移动CMIN2  [精品线路] 联通4837   [普通线路] 
成都移动 211.137.96.205  移动CMIN2  [精品线路] 
-------------------------------------三网回程路由检测-------------------------------------
[NextTrace API] preferred API IP - 104.21.48.1 - 51.02ms - Misaka.LAX
广州电信 - ICMP v4 - traceroute to 58.60.188.222, 30 hops max, 52 byte packets
0.24 ms      AS906      [DMIT-BB]          Anycast, Anycast, DMIT.com 
0.64 ms      AS906      [DMIT-BB]          美国, 加利福尼亚, 洛杉矶, DMIT.com 
0.78 ms      AS906      [DMIT-BB]          美国, 加利福尼亚, 洛杉矶, DMIT.com 
126.91 ms    AS58807    [CMIN2-NET]        美国, 加利福尼亚, 洛杉矶, cmi.chinamobile.com  移动
126.17 ms    AS58807    [CMIN2-NET]        中国, 上海, cmi.chinamobile.com  移动
127.55 ms    AS9808     [CMNET]            中国, 上海, chinamobileltd.com  移动
127.09 ms    AS9808     [CMNET]            中国, 上海, chinamobileltd.com  移动
128.02 ms    AS9808     [CMNET]            中国, 上海, chinamobileltd.com 
167.80 ms    AS9808     [CMNET]            中国, 广东, 广州, chinamobileltd.com  移动
158.20 ms    AS9808     [CMNET]            中国, 广东, 广州, chinamobileltd.com  移动
*
207.43 ms    AS4134     [CHINANET-BB]      中国, 广东, 广州, www.chinatelecom.com.cn  电信
156.82 ms    AS134774   [CHINANET-GD]      中国, 广东, 深圳, chinatelecom.cn  电信
*
161.06 ms    AS4134                        中国, 广东, 深圳, www.chinatelecom.com.cn  电信
广州联通 - ICMP v4 - traceroute to 210.21.196.6, 30 hops max, 52 byte packets
0.22 ms      AS906      [DMIT-BB]          Anycast, Anycast, DMIT.com 
0.48 ms      AS906      [DMIT-BB]          美国, 加利福尼亚, 洛杉矶, DMIT.com 
0.84 ms      AS906      [DMIT-BB]          美国, 加利福尼亚, 洛杉矶, DMIT.com 
126.73 ms    AS58807    [CMIN2-NET]        美国, 加利福尼亚, 洛杉矶, cmi.chinamobile.com  移动
126.09 ms    AS58807    [CMIN2-NET]        中国, 上海, cmi.chinamobile.com  移动
126.20 ms    AS9808     [CMNET]            中国, 上海, chinamobileltd.com  移动
126.14 ms    AS9808     [CMNET]            中国, 上海, chinamobileltd.com  移动
126.98 ms    AS9808     [CMNET]            中国, 上海, chinamobileltd.com  移动
154.14 ms    AS9808     [CMNET]            中国, 广东, 广州, chinamobileltd.com  移动
153.71 ms    AS9808     [CMNET]            中国, 广东, 广州, chinamobileltd.com  移动
269.49 ms    AS4837     [CU169-BACKBONE]   中国, 广东, 广州, chinaunicom.cn 
*
167.66 ms    AS17816    [APNIC-AP]         中国, 广东, 深圳, chinaunicom.cn  联通
181.77 ms    AS17623    [APNIC-AP]         中国, 广东, 深圳, chinaunicom.cn  联通
168.55 ms    AS17623                       中国, 广东, 深圳, chinaunicom.cn  联通
广州移动 - ICMP v4 - traceroute to 120.196.165.24, 30 hops max, 52 byte packets
0.23 ms      AS906      [DMIT-BB]          Anycast, Anycast, DMIT.com 
2.24 ms      AS906      [DMIT-BB]          美国, 加利福尼亚, 洛杉矶, DMIT.com 
0.64 ms      AS906      [DMIT-BB]          美国, 加利福尼亚, 洛杉矶, DMIT.com 
126.17 ms    AS58807    [CMIN2-NET]        美国, 加利福尼亚, 洛杉矶, cmi.chinamobile.com  移动
126.09 ms    AS58807    [CMIN2-NET]        中国, 上海, cmi.chinamobile.com  移动
126.11 ms    AS9808     [CMNET]            中国, 上海, chinamobileltd.com  移动
126.24 ms    AS9808     [CMNET]            中国, 上海, chinamobileltd.com  移动
126.56 ms    AS9808     [CMNET]            中国, 上海, chinamobileltd.com  移动
148.94 ms    AS9808     [CMNET]            中国, 北京, chinamobileltd.com  移动
150.48 ms    AS9808     [CMNET]            中国, 北京, chinamobileltd.com  移动
*
152.08 ms    AS56040    [APNIC-AP]         中国, 广东, 深圳, gd.10086.cn  移动
--------------------------------------就近节点测速--------------------------------------
位置            上传速度        下载速度        延迟            丢包率          
Speedtest.net   1041.71 Mbps    998.97 Mbps     0.33 ms         0.0%            
洛杉矶          1047.87 Mbps    1001.83 Mbps    0.67 ms         0.0%            
法兰克福        556.37 Mbps     885.65 Mbps     148.49 ms       0.0%            
联通上海5G      723.41 Mbps     375.84 Mbps     151.79 ms       2.2%            
联通Wu Xi       808.67 Mbps     803.87 Mbps     149.33 ms       0.0%            
电信浙江        594.87 Mbps     604.07 Mbps     147.60 ms       0.0%
电信浙江        597.95 Mbps     618.77 Mbps     134.21 ms       0.0% 
移动Beijing     903.87 Mbps     388.01 Mbps     149.03 ms       0.0%            
----------------------------------------------------------------------------------
花费          : 8 分 31 秒
时间          : Wed Jan 15 20:52:03 UTC 2025
----------------------------------------------------------------------------------

DMIT 总结

  • 性能:DMIT升级过一次配置,CPU性能非常不错,磁盘 IO 也是 nvme 水准;
  • 线路:三网 CMIN2 回程(移动高端优化线路),无晚高峰波动,稍逊于电信 CN2GIA,奈何 CMIN2 给的太多了(流量);
  • 灵度:DMIT 是2017 成立的大厂了和瓦工一类的,灵度无需担心;
  • 价格:39.9 美元/年的价格,1T 的三网 CMIN2 回程,价格相当不错!
  • 直达链接:https://www.dmit.io/aff.php?aff=9154&pid=188

如何修改 Advanced Media Offloader 使其可以批量将历史文件上传至对象存储?

Advanced Media Offloader 提供了 Bulk Offload 功能,可以实现将历史的文件上传到对象存储中,从而降低本地的存储压力,使得站点自身变得无状态。

但其默认的 Bulk Offload 功能每次只能加载 50 个图片,如果附件太多,则需要点击 N 次,十分麻烦。

image 6


不过,可以通过简单的修改,来实现一次上传,将多个图片进行 Offload。

在 WordPress 后台的插件管理器中,找到 Advanced Media Offloader 插件,并将includes/BulkOffloadHandler.php文件打开,找到其中的 get_unoffloaded_attachments 函数,修改函数定义中的 $batch_size = 50 为你想要的大小即可使其一次批量加载多个文件了。

image 8
修改位置

修改后效果:

image 7

新年给博客迁新服

✨1/8日更新:3天AWS新服体验不佳,吃灰已久的Jetpack宕机监控功能3天下来跳了几次,已迁至阿里云港服。从 🇸🇬🇯🇵 再到 🇭🇰,博客站物理位置离自己更近了👏


博客重新上线时用的是Amazon Lightsail最低标准,配置是512MB内存 2vCPU,每月3刀,一个WordPress小博客站点够用了。用了一段时间有了折腾后发现不够用,就单单一次上传多个图片就能给整爆失联,得重启服务器恢复。后来干脆快照形式搬迁至1GB内存 2vCPU配置,每月5刀,用到现在没出现什么问题,期间亚马逊AWS还涨过一次价至7刀。

以上用的实例位置均在新加坡,期间有博友发现其无法畅通访问得挂梯子并告诉我(其实我自己用的网络环境中并没有遇到过,网络运营商处理这些在我看来有点玄学)。之后就心念着想换位置,理想位置是香港,毕竟是没有备案的最佳选择。还有一个想换的原因是用Bitnami栈打包的Apache服,怎么说呢,Bitnami非常好非常安全非常稳定,但对我来说太麻烦了,修改一些文件权限要整来整去,一些服务版本的更新还得大动干戈,就想换成原味。主要是自己的懒惰,就一直搁着。

新年嘛,就趁新年第一个周末给站点搬家。看了阿里云ECS和腾讯云CVM,最终选择了老东家亚马逊。亚马逊的EC2有港服,但没港服的Lightsail它更便宜!选了和原来一样的配置7刀/月,不同的是位置从新加坡换到了日本,离中国近一点哈哈,经过测试真的是快了一点~阿里云和腾讯云的轻量应用服务器也便宜且有港服,但当我看到“建站内容也是受限制的,出现违规域名会被封禁。”时总觉得会缺少点什么,虽然自己爱国守法,但还是算了,这些年使用过和正在使用的服全是外面的,也无所谓运营商玄学,就对搬回来这欲望并不是那么强烈。

周六上午就开好实例,用Debian12作服务器系统,习惯了Debian,很好。下午只需要旧服备份数据新服搭建环境后一气呵成。然而过程中出了一些状况,需要放下手头其他事,搁置了已经进行到一半的搬迁事宜。当时就连把域名解析回旧服ip从而恢复访问的操作都不想做,出现502 404 TIMED OUT之类已经无所谓了,因为儿子生病了。

周六当天儿子出现两次呕吐症状,第一次呕吐物比较少,里面有少许上午吃的水果。期间儿子还说过自己肚子痛痛,但我们仅凭他当时精神状态很正常,并就有没太多处理,只是揉揉肚子和各种无知的揣测原因。隔三四个小时后出现第二次呕吐,我们这时才意识到问题的严重性,并立马带他去医院,医生给的诊断结果是小儿病毒性肠炎。晚上儿子就出现发热症状,又是一个不眠夜。第二天还在发热,但属于低烧范围,已经不会再呕吐,也说肚子不痛痛了,状态也不错。

周日下午才有完全属于自己的时间接着去处理搬新服后续的事,算是比较顺利。出现问题是服务器莫名过载让网站无法访问,SSH也连接不上且持续很长时间,得重启服务器恢复。线索来源于“PHP message:Connection refused”,先排查插件发现W3TC所使用的缓存方式会导致此问题,Redis与Memcached都试过但问题依旧,干脆先停用,反正新服速度不错。病根应该是php,先搁置,等有空再处理~ //已解决,PHP权限问题

Lightsail真的很Light很轻量,CPU给压的死死的,便宜嘛,这货持续高负载就卡挂。属于突增型,就是说你平时使用CPU的利用率低于10%时(性能基准,实例配置不同基准百分比不同),能积累一种“能量”,当CPU利用率高于10%时,累积的“能量”就会消耗,如果持续高负载直至“能量”耗尽,CPU最大利用率就会压回10%,这就是为什么会挂掉的原因。以上是我对突增型服务器的理解,也罢,够用!

2025年了,看到大家都在写总结,晒清单,立新年Flag,由衷佩服大家的行动力,这是身为一个博主应该拥有的积极人生态度啊,反观自己真的是弱爆了。我属于是佛系,博客更新频率低,写的东西也属于肤浅的记录。时间是有的,陪小朋友、玩游戏、刷手机是我工作时间以外最放松的时候,所以不想“浪费”在写博文上。偶尔打开Follow看看大家写了啥,说真的点开订阅也成为另一种心理负担,因为每次点开后这么多的未读文章,每篇都想点进去瞄一眼,这时间就刷刷走了~

「用户管理」:一键实现用户名称优化,用户安全增强,自定义头像等多项功能 WordPress 插件

这是基于 WPJAM Basic 的超强的 WordPress 用户管理的插件,有多强大呢,首先看后台的设置界面:

可以说它把 WordPress 相关的用户管理功能都集成了,简单数一数就实现了十多个 WordPress 用户相关功能:

  1. 屏蔽个性化设置
  2. 屏蔽姓氏和名字设置
  3. 取消显示名称设置
  4. 开启别名设置
  5. 隐藏用户登录名
  6. 开启登录次数限制
  7. 用户最后登录时间
  8. 取消「应用程序密码」
  9. 按注册时间排序
  10. 以此身份登陆
  11. 生成密码重置链接
  12. 自定义用户头像
  13. 默认用户头像

下面我们分成五大模块分别来介绍 WPJAM 的「用户管理插件」具体实现了那些功能:

屏蔽个性化设置

WordPress后台个人资料用户可以设置「可视化编辑器」,「语法高亮」,「配色方案」,「键盘快捷键」,「工具栏」,「语言」等这些个性化选项,如下图:

这些选项 WordPress 都是存储到 usermeta 表里面,如果 WordPress 有大量的用户,每个用户会占用7个选项,那么 usermeta 表很快就会爆炸。

比如我运营的 WordPress 站点,有几十万用户,usermeta 表的数据如果不清理的话,已经千万级了,查点东西都慢的要死,如果你和我有一样的困扰,那就可以在插件中勾选实现屏蔽用户的个性化设置,直接采用使用系统全局的默认值。然后还可以根据自己的需求删除这些选项。

用户名称优化

在默认情况下,WordPress 后台个人资料页面中,关于用户的姓名相关的设置是这样的:

是不是有点繁琐,并且很多字段也是存到 usermeta 表中的,我个人觉得关于用户昵称的设置,尽量简洁就好,所以名字和姓氏一般就不需要用户输入,公开显示的名字直接为昵称就好了,所以插件首先提供了下面两个选项:

  • 屏蔽姓名设置:屏蔽了姓氏和名字设置,简化后台个人资料界面设置。
  • 显示名称设置:取消显示名称选择器,直接使用昵称作为显示名称。

另外插件还支持开启了别名设置,是的,我们不仅仅做减法,偶尔也做下加法,这里可以让用户可以编辑自己的别名(user_nicename),这样只要不使用和登录名相同的别名,作者文章链接就不会暴露用户名,当然没有设置别名,插件还是有安全选项来实现防止用户名暴露。

所以优化之后最终的用户界面非常简洁,如下所示:

安全增强

WordPres 用户安全增强体现在两个地方,首先是隐藏登录名,不要让攻击者猜到用户名,然后是开启登录限制,防止密码被暴力破解,插件也提供这两方面的选项:

首先说一下如何隐藏登录名,如果用户没有修改过别名(user_nicename),那么他的别名和登录名(user_login)是一样的,然后作者文章链接或者其他地方就会暴露登录名,为了进一步防止登录名暴露,我们提供了隐藏登录名的选项:

勾选「防止登录名暴露」之后,如果用户的 user_nicenameuser_login 是一样的情况下:

1. 作者文章链接使用 author_id 代替 user_nicename,并且原来的作者链接直接设置为 404 页面,防止用户名暴露

2. user_login 不出现在 body_classcomment_class 中。

3. 隐藏登录失败时候未知用户名和密码不正确的错误信息,这两种情况都显示「用户名或者密码错误」,让攻击者猜去。😁

4. 取消作者相关的 sitemap 以及 REST API 中可以查看所有发布过文章的用户信息列表的中的登录名。

如果真的被攻击者猜到了登录名,那么我们还可以开启登录限制,限制登录失败次数,这样就可以防止密码被暴力破解了,进一步做到安全。

功能增强

除了安全增强之外,我们还增加了一个小功能和屏蔽一个功能,分别是记录用户最后登录时间和取消「应用程序密码」功能:

首先新增记录用户最后登录时间,用户登录之后,在后台用户列表就会显示该用户的最后登录时间,并且支持按照用户最后登录时间进行排序。

默认情况下在后台个人资料页面可以设置「应用程序密码」:

应用程序密码允许通过非交互式系统(例如 XML-RPC 或 REST API)进行身份验证,而无需提供您的实际密码。应用密码可以随时撤销。它们不能用于通过传统方式登录您的网站。

很多人看到这个其实是稀里糊涂,简单说他就是用于 APP 或者小程序通过接口来登录的,但是基本上来说,我们用不到这个功能,所以默认建议屏蔽它。

后台用户列表

对于管理员经常使用的用户列表,也新增一些功能和操作:

首先用户可以除了可以按照上面提示按照最后登录事件排序之外,也可以按照用户注册时间排序,只要你勾选了用户列表里的第一个选项,此外在用户列表页面新增两个操作「以此身份登陆」和「生成密码重置链接」:

如果你是 WordPress 开发者,「以此身份登陆」这个功能特别实用,在用户列表界面,管理员可以轻松以用户的身份登录后台,这样用户说他碰到什么问题,就可以直接登录他的账号去看了,而不是问他要账号密码,这个多难为情啊。😳

WordPress 原来「发送密码重置邮件」这个功能是直接发送密码重置邮件给用户,用户在邮箱里面直接点击操作,改成「生成密码重置链接」,则管理员直接获取密码重置链接,可以通过微信或者其他的社交媒体工具发给用户。

头像设置

在后台个人资料页,用户可以自定义自己的头像。

如果用户没有设置头像,管理员可以设置默认头像,然后随机给用户使用:

最后用户头像还多加一个选项,就是如果用户已经在 Gravatar 里面设置了头像怎么办?有两个选项,从默认中随机选一个,继续使用 Gravatar 的设置。

总结

通过上面的介绍,是不是非常强大,目前我所有用户相关的功能整合到 WPJAM-User 的插件中,只需后台简单的勾选就可以实现绝大部分用户安全和管理相关的功能。


「WordPress果酱」知识星球福利插件基于 WPJAM Basic 开发,加入「WordPress果酱」知识星球,即可下载:

插件 简介
抓取公众号图文

支持一键同步微信公众号文章到 WordPress 博客,并支持一键将文章中所有图片都下载到 WordPress 媒体库。

搜索优化

WordPress 最强的搜索优化插件,支持限制每个 IP 每分钟搜索次数,达到上限之后屏蔽搜索时长,还可以限制搜索关键词的长度,搜索结果页面限制只显示「搜索结果」,还有以下搜索功能增强:

1. 只搜索文章标题,不搜索文章内容和摘要。
2. 当搜索关键词为空时重定向到首页,只有一篇文章时重定向到文章
3. 后台文章列表支持搜索ID。
4. 支持搜索自定义字段。

编辑器优化

一键增强 WordPress 经典 TinyMCE 编辑器:

1. 增加下划线,背景颜色,两端对齐,字体和大小设置,以及内容分页按钮。
2. 新增插入表格功能。
3. 直接插入屏幕截图。

标题设置

一键设置 WordPress 所有页面的页面标题,通过规则方式让博主可以自定义 WordPres 首页,分类,文章类型,文章详情都所有页面的页面标题。

登录优化

一键优化 WordPress 登录注册界面,并支持第三方账号登录和绑定,目前已经支持微信公众号(所有类型),微信小程序,手机号码第三方平台。

内容模板

实现在内容中插入一段共用的内容模板,通过短代码(shortcode)的方式来实现的,支持统一修改,目前支持普通的内容模板,表格内容模板和卡片内容模板三种类型。

用户管理

最强 WordPress 一键用户管理插件,一键实现以下12个功能:

1. 屏蔽个性化设置
2. 屏蔽姓氏和名字设置
3. 取消显示名称设置
4. 开启别名设置
5. 隐藏用户登录名
6. 开启登录次数限制
7. 用户最后登录时间
8. 按注册时间排序
9. 以此身份登陆
10. 生成密码重置链接
11. 自定义用户头像
12. 默认用户头像

分类管理

这是一个全能的 WordPress 分类管理插件:

1. 层式管理分类
2. 限制分类层级
3. 分类拖动排序
4. 使用数字固定链接
5. 首页文章支持分类过滤
6. 后台文章列表支持分类筛选过滤
7. 后台文章列表支持分类多重筛选

评论增强

这是一个 WordPress 评论增强插件,支持评论置顶,评论点赞和按照点赞数排序。

图片集

1. 给媒体创建个分类「图片集 | collection」
2. 图片分类限制为二级
3. 取消图片编辑入口
4. 附件页面直接图片链接。

配置器

全自动 WordPress 配置器,不用一行代码就可以开发。
支持自定义文章类型,自定义字段,自定义分类,分类选项,全局选项。

Script Loader

通过恢复 WordPress 联合加载方式来优化 WordPress 后台脚本加载。

外部链接

将文章或评论中的外部链接加上安全提示的中间页。
让用户确认之后再跳转,并还支持添加 nofollow rel 属性。

话题标签

文章中插入 #话题标签#。
如果是内部链接,直接跳转,
标签或者分类,则自动转换成标签或分类链接,
否则跳转到搜索链接。

格式文章

在 WordPress 实现真正的文章格式

草稿分享

一键生成草稿临时分享链接
并可设置分享链接的有效期

文章专题

设置文章专题,并在文章末尾显示一个文章专题列表。

文章隐藏

设置文章在列表⻚不显示,并且可以根据不同平台进行设置

Meta Data

可视化管理 WordPress Meta 数据,支持所有内置的 Meta 数据:
Post Meta,Term Meta,User Meta 和 Comment Meta。

站点选项

查看和管理所有非 WordPress 系统自动生成的站点选项。
如果你觉得某个选项无用,可以直接删除它。

后台论坛

WordPress 后台论坛,支持创建帖子,分组,消息。

微信小程序

微信小程序 WordPress 基础插件,包含基础类库和管理。

微信群二维码

轮询显示微信群二维码,突破微信群100人限制。

文章置顶

支持置顶文章排序和分类文章置顶的 WordPress 插件

静态文件

一键合并 WordPress 插件和主题的 JS 和 CSS 文件,加快页面加载速度

Debug

一键检测 WordPress 运行效率。

给博客增加 文章归档 和 年度统计 功能

终于在建站11年的当下终于给博客增加了文章归档页。
是基于 Rank Math SEO 插件的 Sitemap Settings 功能实现了一个简单的文章归档页。
顺带在文章归档页内塞了一个额外的网站数据年度统计功能。
大概长这样:文章归档


起因 为什么想要加文章归档页了

起因是在《WindowTabs: 让几乎一切 Windows 窗口支持多标签功能》一文下,博友 ddw2019 在评论中提到我的站点“没有找到 Archive 页面,一个个翻页起来,感觉还是有点点费劲的呀。”

之前我一直感觉文章归档页的感知不强,我认为它的主要意义和好处是:系统化整理文章、提高可发现性、增强用户体验、SEO优化、展示创作历程这 5 个方面。

毕竟现在右侧有文章分类、随机文章、热门文章三个模块。系统化整理文章提高可发现性性上已经足够了。
SEO 优化上文章归档页固然归可以帮助搜索引擎更好地抓取和索引博客内容,不过在已经有 xml 站点地图的时候,文章归档页对于提供博客的 SEO 优化上作用不大,相较这种 html 格式站点地图,xml 格式的站点地图对搜索引擎会更加友好一些。

不过嘛,确实考虑到博客里确实是缺少一个展示创作历程和增强用户体验的东西。于是在2024年的年底,终于在建站 11 年后决定加上这个东西。

思考 实现文章归档页的方案

那么现在问题来了,如何多快好省的实现文章归档页 Archive 呢?
从这个博客的可以称之为极简的风格上估计大家都能看出,我并不太喜欢在美化折腾博客页面上消耗过多精力。

  • 方案一 网友 ddw2019 的博客中写到的方案 年度归档插件
    好处是省事的多,装个插件的事情。缺点是又双叒叕需要多装一个插件了,博客速度又要被拖累。
  • 方案二 利用现有插件 Rank Math SEO 的站点地图功能实现。
    好处是利用了现有插件,少装了一个插件,缺点是样式就简陋的多了,样式的自定义空间也小的多。

  • 方案三 自己实现一个页面
    优点是更加轻量,样式完全可以自定义。缺点是自己写东西需要费更多的时间。

权衡利弊后,我决定先用方案二顶上,先解决有无问题再说。

开干 实现文章归档

以下的必要前提是:你要有装 Rank Math SEO 这个插件,并且开启了他的 Sitemap 组件。
这里我只介绍必要的操作,如果想了解更多一点,这里有篇不错的文章 《家庭数据中心系列Rank Math SEO设置与优化-无敌的个人博客》

  1. 新建一个页面,起名叫文章归档并把固定链接设置为ex.your.domain/archives并发布。
    (是的,内容为空就行)
  2. 进入博客后台,左侧找到 Rank Math SEO 的 Sitemap Settings 部分,切换到 HTML Sitemap 标签,并开启开关。

  3. 将 Display Format (显示模式)设置为 Page 也就是页面模式。如果你想在文章归档页放入额外的东西,也可以设置为 Shortcode 模式,这样上一步时,需要在你想要插入文章归档页的地方写短代码[rank_math_html_sitemap] 即可。

  4. Sort by (排序方式),既然是文章归档页,那自然是选 Published Date (基于发表日期)啦。并且开启下边的 Show Dates (显示日期),这样文章后面就会显示发布日期了。

  5. Item Titles (项目标题),作为文章归档页,建议选 Item Titles (文章标题)而不是 SEO Titles (SEO用标题)这两者的区别是:SEO用标题是给搜索引擎和搜索结果用户看的,可能会比实际的文章标题会有些奇妙的拉长和缩短。比如文章实际标题很长,但是 SEO 标题可能会为了能保证在搜索结果页把关键词凸显出来会相对减少次要描述。也就是说 Item Titles (文章标题)更能反映文章内容。

  6. 最后保存即可,现在前边设定的固定链接看到一个比较简陋的,文章归档页了。
    类似本站这样:文章归档 (https://www.tjsky.net/archives)

增强 增加博客年度数据统计功能

本来事情就该结束了,结果中午的时候,我又在博友圈里看到了 ts小陈 的文章:《为WordPress网站添加年度数据汇总
我发现,“诶,这个东西不错嘛,可以很直观的展现每年博客的发展数据。”
随后尝试直接套用代码,然后果不其然的发现:事情并没有那么简单。
毕竟我现在用的主题上次更新已经是2022年了,主题并没有完美支持页面模板php文件。
并不能像他原文介绍的那样:

  • 将php文件上传到你主题的页面模板文件夹(pages文件夹)
  • 创建新页面选择该模板-年度数据
  • 发布页面,搞定。

于是我又研究了一下WordPress这个页面模板php文件应该怎么写,以及他代码具体是做了什么。
重新写了适配自己主题的页面模板文件。主要修改点是三个

  • 修改一下样式适配博客主题
    主要是套用原有page页的代码,改一个新的模板文件。还有些小修改,比如表格做成圆角啊,表格改个主题色啊,属于毫无技术含量的修改。
  • 修改其中统计字数的函数str_word_count()mb_strlen()
    中文不用空格来分隔单词,对于中文字符串,str_word_count()会将两个标点之间的整个字符串都视为一个单词,mb_strlen()则会根据当前PHP设定的编码自适应用基于UTF8或gbk等编码正确统计字数。所以改一下得到准确的字数统计。

//修改前的代码,在原文文件的第79行
word_count = str_word_count(strip_tags(content)); // 去除HTML标签后计算字数

//修改后的代码
word_count = mb_strlen(strip_tags(content)); // 去除HTML标签后计算中文字数

大部分面板和一键脚本部署的 PHP 应该默认就开了 mb_strlen 这个函数,不过对于用虚拟主机的可能需要注意下,这个 PHP 函数不一定被启用了。

  • 把缓存改成1天,30天有些长了。

原文写的是”数据使用 Memcached 缓存”,让人以为只能用于 Memcached。不过实际上,如果你用 Redis 或者其他什么缓存,只要你装了对应的缓存插件,比如用 Redis 并且装了 Redis Object Cache。可以保证wp_cache_get()wp_cache_set() 函数能正常工作就不需要注释掉缓存代码,不然每次都现场计算一次,这性能浪费不小。

最终效果如下图

很直观的数据
2017年上一个博客被我rm -rf */干没了之后,在 17 年 12月 底重建,18 年还在保持正常的更新,可惜博客没啥人看(看评论数量),外在驱动力不足 导致 19 ~ 21 年我基本上没更新过博客,21 年底,因为一些机缘巧合博客收获了一波较大流量,加之因为这个机缘巧合重新拾起写代码的乐趣,重新开始恢复正常的更新频率。

The post 给博客增加 文章归档 和 年度统计 功能 appeared first on 秋风于渭水.

做公众号,学会排版,写一篇很「美」的文章!

继续我们「做公众号」系列的文章,今天讲讲如何学会给文章排版写一篇很「美」的文章!如果你是第一次看到这篇文章,这是这个系列之前的两篇文章:

我们这些略懂一些 SEO 的草根站长(😳)都知道,一篇文章的内核都是内容,写的好的内容,读起来如沐春风,非常舒服,但是承载内容的页面的如果没有布局和排版,广告位横飞,混乱不堪,使得明明很好的内容,变得一点阅读的兴趣都没有。

对于做公众号的人来说也是一样的,学会排版也是非常重要的一个技能,一些公众号文章,排版清晰,文字间距适当,读起来毫无压力。而一些公众号的文章,文字密密麻麻,也没有任何段落章节划分,完全没有读下去的勇气。😅

如果你已经阅读过我「做公众号」系列的文章,你一定对我这两篇文章的排版还算是不错吧,段落章节都非常清晰,图片和字体都做了一些小的设计,我今天就讲解一下我是如何给公众号排版的。

文字

一篇文章,最重要的是文字,使用什么字体,行距多少合适呢?都会对阅读造成非常大的影响。

如果你仔细看,就会发现我文章的文字都比较细,这个主要是为了方便阅读,现在手机的分辨率都很高,对于细的字体也会渲染得不错,使用比较细的字体让文章整体效果看起来会清爽很多。

下面就是我使用的字体列表:

body{ font-family: Roboto, Oxygen, Ubuntu, Cantarell, PingFangSC-light, PingFangTC-light, "Open Sans", "Helvetica Neue", "sans-serif"; }

除此之外,我还把字体颜色设置纯黑色,因为字体比较细,所以看起来不会那么黑,然后行距设置为 1.6,字体设置为 16px,这样一眼看上去就非常清晰:

body{ color: #000000; font-size: 16px; line-height: 1.6; }

作为对比,如果行距设置为 1,字体设置为 14px 的,会显示成什么样呢?不多打一段文字了,就拿这段文字来设置了,大家看看,是不是立刻看起来密密麻麻的感觉,阅读感明显就差了不止一个档次吧!

通过对比,是不是很明显感觉到不同文字的样式对阅读影响非常大。😁

一级子标题

接着我觉得一篇文章最重要的是标题,我们写技术类文章,喜欢通过子标题将文章划分得更加清晰,用户也能够首先通过一二级子标题大概知道文章的脉络和重点。

当然除了技术类文章,其他类型的文章也可以通过这类子标题划分的模式让用户清晰知道自己读到那里,对于作者,也能让自己将文章写得更有逻辑和条理。

如上所示,我是给一级子标题颜色设置成青蓝色,并且加上大概 10 像素颜色淡一些的线,同时这条线向上推了一些,放到标题后面形成阴影的感觉,然后二级子标题的颜色设置成草绿色,阴影的感觉同样处理,如下所示:

二级子标题

之前我试过子标题下面加一条线,但是感觉不是那么好看,经过各种测试和比较,终于改成现在这个样子,感觉明显一下高级多了。😄

大家觉得呢?

此外一般来说文章有一二级子标题就已经足够了,如果文章有三级子标题,当然也可以按照同样的方式设置,颜色根据自己喜好选择即可。

图片

图片算是第三重要吧,我目前只是做了简单的一些设置,效果先看上面两种子标题样式比较的图片,我把文章中的图片都设置了 6px 半径的阴影效果,这样图片有点发光的效果,比较好看。😊

你觉得呢?

因为我写技术文章比较多,很多截图,有些截图,可能边缘是白色,可能会和内容混了,这个阴影效果处理的方式也可以明显把这种截图明显区别开。

当然图片还有一些相册,多张图片的样式等,可能需要处理,我暂时还没有用到,如果之后我要处理了,我也会再加上去。

表格

除了「文字」、「标题」和「图片」这三大件之外,技术类的文章可能还会比较多用到表格,我针对微信公众号,也特别优化了一下表格的显示,算是一个 bonus 的功能吧:

插件简介
标题设置一键设置 WordPress 所有页面的页面标题。
通过规则方式让博主可以自定义 WordPres 首页,分类,文章类型,文章详情都所有页面的页面标题。
登录优化一键优化 WordPress 登录注册界面。
并支持第三方账号登录和绑定,目前已经支持微信公众号(所有类型),微信小程序,手机号码第三方平台。
内容模板实现在内容中插入一段共用的内容模板。
通过短代码(shortcode)的方式来实现的,支持统一修改,目前支持普通的内容模板,表格内容模板和卡片内容模板三种类型。

如上所示,如果没有回车,都会一行显示,除了第一列之外,其他列支持滚动,这样在手机上看的时候,在保持表格优雅的同时,让用户不仅能够快速预览表格内容,也可以看完表格内容。

代码

最后技术性的文章的怎么可能少的了代码呢,所以代码样式是非常重要的,我也是做了一些优化,如上面文字样式代码的样式效果,怎么样?我再去搞一段 PHP 代码给大家演示一下:

add_action('plugins_loaded', function(){	// 所有插件都已经加载
	if(!did_action('wpjam_loaded')){		// 确保已加载 WPJAM Basic 插件
		return;
	}

	$fields	= [
		'seo_title'			=> ['title'=>'SEO标题',	'type'=>'text',	'class'=>'large-text',	'placeholder'=>'不填则使用标题'],
		'seo_description'	=> ['title'=>'SEO描述',	'type'=>'textarea'],
		'seo_keywords'		=> ['title'=>'SEO关键字','type'=>'text',	'class'=>'large-text']
	];

	wpjam_register_post_option('seo', [
		'title'			=> 'SEO设置',	// 自定义选项标题
		'context'		=> 'side',		// 显示在文章编辑页的侧边
		'list_table'	=> true,		// 后台文章列表页也支持弹窗设置
		'page_title'	=> 'SEO设置',	// 文章列表点击弹窗的标题
		'fields'		=> $fields
	]);
});

怎么样,效果很不错吧。你对写一篇很「美」的文章有什么看法,欢迎在公众号的留言来发表你的看法。

哦,对了,我是把这些样式都写在了「我爱水煮鱼」博客主题中,写公众号的时候,在 WordPress 后台写好,然后直接一键复制到公众号即可,非常快捷,并且样式也全带过去了。当然了,你也可以在公众号后台,把自己常用的样式保存为模板,下次直接直接使用模板来写文章,也是可以的。😄

最后再说一句:「我爱水煮鱼」博客主题我放在了「WordPress 果酱」的知识星球,你加入之后即可获取。

企业建站,就用 WordPress Modular 主题!

企业建站其实可以一个一个模块「组装」起来的,这样企业站点的需求就变成了不同模块的定制

Modular 主题提供几十个我们这些年理解的企业站点所需的模块,那么在大部分情况下,通过一个主题就能类似于淘宝店铺装修那样,就能够很快构建成一个完全不同风格的企业站点了。

所以企业建站首先需要的是一款深度自定义与模块化设计的 WordPress 企业主题

Modular 主题除了 WPJAM Basic 插件之外,还集成两个独立的插件:

首先是页面模块装修插件,通过它无需再写一行代码,只需要在后台设置装修页面:无需再写一行代码即可一键模块化装修 WordPress 页面

然后是完全自定义的表单插件,可以在后台自定义表单的字段,就可以生成自己所需的表单,用户提交之后,后台可以自动收集:整波大的, Modular 主题集成了我们压箱底的表单插件!

东西好不好,还是要用户说了算:

无需 Element Pro 就可以实现装修效果,并且页面还能秒开,这样的 WordPress 主题见过吗?

总结一下,可以说 Modular 主题完全是为了企业建站而生的

如果你是一家企业的 IT 负责人,通过这个主题,自己设计一下图片就能快速完成企业交给你的任务,再加上 WordPress 本身的易用性,这款主题可以说让你每天的「摸鱼」时间成倍增加。😁

如果你是一个平时接接单给企业做个小网站的自由职业者,这款主题可以让你快速赚到钱,你完全不用操心代码的事情只需要沟通清楚企业的需求,找到对应的模块搭建进去即可,让你只需要800块钱的成本就能够构建5000-10000的企业站点

最后的最后,Modular(模块化)主题是一个付费的主题,基于 WPJAM Basic 插件构建,原价2680 元,现在只需 688 元就能构建一个完全个性化的企业站点,购买请点击链接:https://wpjam.com/go/modular

WordPress外链跳转到中间页

记得之前还在Wordpress的时候,曾经捣鼓了一个跳转页(原文章链接),后来换成Typecho后,用的是姜先森的主题,也就直接用着他的跳转方式。回到Wordpress(后简称WP)后,就一直没弄,刚好中午闲逛,又让我看到了其它博主的跳转页,感觉不错,那就赶紧“作业抄起来”。

这个跳转页参照了空白大佬的,太多技术性的咱就不说了,都是抄作业,下面就细说一下步骤:

  • 在网站根目录下新建一个文件夹,例如 mygo ,再在里面新建几个文件如: go.js go.html go.css ,跳转页的图片自己抠一下吧。
  • go.js文件内容:
function checkParent(element, classNames) {
    while (element) {
        if (element.classList && classNames.some(cn => element.classList.contains(cn))) {
            return true;
        }
        element = element.parentElement;
    }
    return false;
}
var excludedClasses = ['card-link', 'friend-item', 'contact-item', 'footer-item']; // 排除的 a 标签类名
window.addEventListener('load', () => {
    document.body.addEventListener('click', function (e) {
        let target = e.target;

        // 确保点击的目标是 <a> 标签
        while (target && target.nodeName !== 'A') {
            target = target.parentNode;
        }

        // 如果是 <a> 标签并且满足以下条件才触发跳转逻辑
        if (target && target.nodeName === 'A' &&
            target.href && // 确保有 href 属性
            target.href !== '#' && // 排除返回顶部链接
            !checkParent(target, excludedClasses) && // 排除特定类名
            !target.href.startsWith('javascript:') && // 排除 javascript: 链接
            !target.href.includes('zfei.net') && // 排除特定域名
            !target.href.includes('057000.xyz') &&
            target.hostname !== window.location.hostname) { // 仅针对外部链接
            e.preventDefault();

            // Base64 编码目标链接
            let encodedUrl = btoa(target.href);
            let url = '/mygo/go.html?target=' + encodedUrl;

            // 在新窗口中打开跳转页面
            window.open(url, '_blank');
        }
    });
});
  • go.html文件内容:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="go.css">
    <title>即将离开知非博客</title>
</head>
<body>
<div class="tiaozhuan-all">
    <div class="tiaozhuan-nrong">
        <div class="tiaozhuan-title">您即将离开 『 知非博客 』 ,跳转到以下外部链接</div>
        <div id="tiaozhuan-link"></div>
        <div class="tiaozhuan-info">请自行识别该链接是否安全,并保管好个人信息。</div>
        <div class="tiaozhuan-button"><a href='' id='direct-link'>继续访问</a></div>
    </div>
</div>
<script>
    const params = new URLSearchParams(window.location.search);
    const encodedTarget = params.get('target');
    const target = atob(encodedTarget); // 使用 atob 进行 Base64 解码
    if (target) {
        document.getElementById('direct-link').href = target;
        document.getElementById('tiaozhuan-link').textContent = '' + target; // 直接显示目标地址    
    } else {
        console.error('未指定重定向目标。');
    }
</script>
</body>
</html>
  • go.css文件内容:
body {
    background: #ececec;
}
.tiaozhuan-all {
    position: relative;
    box-shadow: rgba(0, 0, 0, 0.25) 0px 25px 50px -10px;
    border-radius: 10px;
    background-image: url('go.png');
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    color: #666;
    word-break: break-all;
    max-width: 700px;
    height: 350px;
    text-align: center;
    font-size: 0.85rem;
    overflow: hidden;
    margin: 100px auto 0;
    @include breakpoint('small') {
        aspect-ratio: 2 / 1;
        height: auto;
    }
}
.tiaozhuan-nrong {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    padding: 20px 20px 30px 20px;
}
.tiaozhuan-title {
    font-size: 1.3rem;
    color: #222;
    line-height: 1.4;
    margin-bottom: 4px;
}
.tiaozhuan-info {
    margin-top: 6px;
}
.tiaozhuan-button {
    margin-top: 20px;
}
.tiaozhuan-button a {
    color: #fc9151;
    border-radius: 4px;
    padding: 10px 30px;
    font-size: .85rem;
    border: 0.5px solid #fc9151;
    display: inline-block;
    text-decoration: none;
}
  • 最后在主题的 footer.php 中添加一段代码:
    <script src="/mygo/go.js"></script>

    其实,对于我们浏览体验来说,这样子操作等于多了一步跳转,体验上总归是不好,但为了愉快的玩耍博客,稳妥一点还是需要的。如果觉得跳转中间页很烦人,浏览器可以装个 Skip Redirect 插件,告别所有网站的中间页跳转,直接抵达目标地址。
    哈哈,跳转功能只运行了几个小时让我撤掉了,正如Jeffer.Z大佬说的:

    有备案加是对的,如果不需要备案就无所谓了,我反正是不加,影响大家跳转流畅度感觉

所以说作为一个没有备案的网站,这种影响大家畅游网络的事宜,确实就不需要了,如果是备案网站的话,建议还是加一个跳转,虽然不太友好,但碍于现实也没什么好办法。

WordPress 插件-NeoDB Integration 书影音展示页面

将 NeoDB 书影音记录整合到 WordPress 中 实现了将 NeoDB 观影记录添加到 WordPress 页面中,展示页面:NeoDB 书影音

但流程较为复杂,本文将 Cloudflare worker 和 functions.php 整合成了 WordPress 插件,进一步简化流程。

本人无相关代码经验,插件由 ChatGPT 协助生成,时代真的变了。

使用方法

NeoDB API Developer Console 中点击Test Access Token,并 Generate 一个 NeoDB Bearer Token,示例:Th2121_qs-8agMAlSrkE_tzBbcvjsdkjtlCtr9QHX321312312Ytzo8_YmOxjxg

在终端(Terminal)或命令提示符(Command Prompt)中输入以下代码,将 YOUR_TOKEN 替换为 NeoDB Bearer Token。

curl -H "Authorization: Bearer YOUR_TOKEN" https://neodb.social/api/me

下载 NeoDB Integration 插件: https://github.com/DayuGuo/NeoDB-wordpress-Integration/releases/tag/gotest

在 WordPress 中安装并激活该插件。

在 Settings-NeoDB Settings 中输入 NeoDB Bearer Token。

在 WordPress 页面或文章中,使用以下短代码来显示数据:{neodb_page},使用时请将{}符号,换成[]。

Settings-NeoDB Settings 中可调整显示的内容、手动更新和清理数据库。

效果示例

https://anotherdayu.com/neodb/

另,附上我的 NeoDB主页:https://neodb.social/users/anotherdayu/,和 mastodon 账号:https://mastodon.social/@anotherdayu

新版本

1.2 – Jack,NeoDB WordPress 插件优化

1.3 – 皮小辛,WordPress 插件-NeoDB Integration优化(1.3版本)

参考资料

将 NeoDB 书影音记录整合到 WordPress 中

朋友们,已将该功能整合成一个WordPress插件,可直接看这篇 WordPress 插件-NeoDB Integration 书影音展示页面,更简单易用。

这两篇文章合在一起,是我第一次使用 ChatGPT 协助制作 WordPress 插件的心路历程。

NeoDB 是一个开源免费的书影音收藏社区平台,详情见:NeoDB | 书影音标记 – 豆瓣、GoodReads 和 Google Book 的替代品

本文参考 hcplantern 的 将 NeoDB 记录整合到 Hugo 中 ,实现了将 NeoDB 观影记录添加到 WordPress 页面中,展示页面:NeoDB 书影音

获取 NeoDB Bearer Token

NeoDB API Developer Console 中点击Test Access Token,并 Generate 一个 NeoDB Bearer Token,示例:Th2121_qs-8agMAlSrkE_tzBbcvjsdkjtlCtr9QHX321312312Ytzo8_YmOxjxg

在终端(Terminal)或命令提示符(Command Prompt)中输入以下代码,将 YOUR_TOKEN 替换为 NeoDB Bearer Token。

curl -H "Authorization: Bearer YOUR_TOKEN" https://neodb.social/api/me

设置 Cloudflare worker

注册 Cloudflare worker,点击 Create,创建一个 worker。

最初会展示一个 Hello World 基础案例,点击 Continue to project – Settings – Variables and Secrets。

添加一个环境变量(Environment Variables):

  • Type:text
  • Variable name:NEODB_TOKEN
  • Value:NeoDB Bearer Token,示例:H13121_qs-8agMAlSrkE_tzBbcvjsdkjtlCtr9QHX321312312Ytzo8_YmOxjxg

点击右上角的 Edit code,删除 worker.js 中全部代码,并将 hcplantern 提供的代码(如下)复制黏贴进去。

const myBearer = NEODB_TOKEN; // Assuming 'NEODB_TOKEN' is set in your Cloudflare Worker's environment variables

addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})

async function handleRequest(request) {
try {
console.log(myBearer)
const url = new URL(request.url);
const category = url.pathname.substring(1);

// Optionally, handle query parameters (e.g., page number)
const page = url.searchParams.get('page') || '1';
// Available values : wishlist, progress, complete
const type = url.searchParams.get('type') || 'complete';

let dbApiUrl = `https://neodb.social/api/me/shelf/${type}?category=${category}&page=${page}`;
const response = await fetch(dbApiUrl, {
method: 'get',
headers: {
'Accept': 'application/json',
'Authorization': `Bearer ${myBearer}`
}
});

// Check if the response from the API is OK (status code 200-299)
if (!response.ok) {
throw new Error(`API returned status ${response.status}`);
}

// Optionally, modify or just forward the API's response
const data = await response.json();
return new Response(JSON.stringify(data), {
headers: { 'Content-Type': 'application/json' },
status: response.status
});

} catch (error) {
// Handle any errors that occurred during the fetch
return new Response(error.message, { status: 500 });
}
}const myBearer = NEODB_TOKEN; // Assuming 'NEODB_TOKEN' is set in your Cloudflare Worker's environment variables

addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})

async function handleRequest(request) {
try {
console.log(myBearer)
const url = new URL(request.url);
const category = url.pathname.substring(1);

// Optionally, handle query parameters (e.g., page number)
const page = url.searchParams.get('page') || '1';
// Available values : wishlist, progress, complete
const type = url.searchParams.get('type') || 'complete';

let dbApiUrl = `https://neodb.social/api/me/shelf/${type}?category=${category}&page=${page}`;
const response = await fetch(dbApiUrl, {
method: 'get',
headers: {
'Accept': 'application/json',
'Authorization': `Bearer ${myBearer}`
}
});

// Check if the response from the API is OK (status code 200-299)
if (!response.ok) {
throw new Error(`API returned status ${response.status}`);
}

// Optionally, modify or just forward the API's response
const data = await response.json();
return new Response(JSON.stringify(data), {
headers: { 'Content-Type': 'application/json' },
status: response.status
});

} catch (error) {
// Handle any errors that occurred during the fetch
return new Response(error.message, { status: 500 });
}
}

然后点击 Deploy 部署即可。

注意在这一步中,需要复制保留左侧 Preview 下方的网址,示例 https://xyz-hall-ohxu.user.workers.dev/

WordPress Shortcode

在 WordPress 管理后台,导航到“外观” -> “主题编辑器”。

找到并编辑当前主题的 functions.php 文件。

将以下代码添加到 functions.php 文件中。这段代码创建了一个名为 neodb 的短代码。

注意:将代码中的 https://your-worker-url/ 替换为 Cloudflare worker 中的 https://xyz-hall-ohxu.user.workers.dev/

function neodb_shortcode($atts) {
$atts = shortcode_atts(
array(
'category' => 'book',
'type' => 'complete',
),
$atts,
'neodb'
);

$category = $atts['category'];
$type = $atts['type'];

$url = sprintf('https://your-worker-url/%s?type=%s', $category, $type);

$response = wp_remote_get($url);
if (is_wp_error($response)) {
return '数据获取失败';
}

$body = wp_remote_retrieve_body($response);
$data = json_decode($body, true);

if (empty($data['data'])) {
return '没有找到相关数据';
}

ob_start();
?>
<div class="item-gallery">
<?php foreach (array_slice($data['data'], 0, 10) as $value): ?>
<?php $item = $value['item']; ?>
<div class="item-card">
<a class="item-card-upper" href="<?php echo esc_url($item['id']); ?>" target="_blank" rel="noreferrer">
<img class="item-cover" src="<?php echo esc_url($item['cover_image_url']); ?>" alt="<?php echo esc_attr($item['display_title']); ?>">
</a>
<div class="rate">
<?php if (!empty($item['rating'])): ?>
<span><b><?php echo esc_html($item['rating']); ?></b>🌟</span>
<br>
<span class="rating-count"><?php echo esc_html($item['rating_count']); ?>人评分</span>
<?php else: ?>
<span>暂无🌟</span>
<br>
<span class="rating-count"><?php echo esc_html($item['rating_count']); ?>人评分</span>
<?php endif; ?>
</div>
<h3 class="item-title"><?php echo esc_html($item['display_title']); ?></h3>
</div>
<?php endforeach; ?>
</div>
<style>
.item-gallery {
display: flex;
padding: 0 1rem;
overflow-x: scroll;
align-items: baseline;
}
.item-card {
display: flex;
flex-direction: column;
flex: 0 0 17%;
margin: 0 0.5rem 1rem;
border-radius: 5px;
transition: transform 0.2s;
width: 8rem;
}
.item-card:hover {
transform: translateY(-5px);
}
.rate {
text-align: center;
}
.rating-count {
font-size: 0.8rem;
color: grey;
}
.item-cover {
width: 100%;
min-height: 3rem;
border: 2px solid transparent;
}
.item-title {
font-size: 1rem;
text-align: center;
margin: 0;
}
</style>
<?php
return ob_get_clean();
}
add_shortcode('neodb', 'neodb_shortcode');

使用代码

在 WordPress 页面或文章中,使用以下短代码来显示数据:

CleanShot 2024-12-20 at 00.09.10@2x.png

book 可以替换为 movie, tv, podcast, music, game, performance,展示更多数据。

type 可选 wishlist 和 complete,展示想看和看过的内容。

效果示例:https://anotherdayu.com/neodb/

CleanShot 2024-12-19 at 23.56.56@2x.png

另,附上我的 NeoDB主页:https://neodb.social/users/anotherdayu/,和 mastodon 账号:https://mastodon.social/@anotherdayu

没事敲打一下自己的博客

从Typecho转回Wordpress也有段时间了,也算是各种折腾吧,以往的习惯都是用Debian+LNMP(或者有时懒了,直接就整BT了),Typecho用着轻巧、访问也快,但耐不住俺们这爱折腾的心理,所以这不就又整上Wordpress了呗,既然来了,那就再重新开始折腾一下吧。

这次回到WP,大部分是因为林海草原大佬的一句评论:

我看你说wp运行卡卡的,我推荐你用openlitespeed替代nginx或Apache,运行wp绝对流畅。如果你用宝塔,可以安装openlitespeed。如果想换成其他面板,推荐你用cyberpanel面板,安装好以后它自带openlitespeed。在有openlitespeed存在的情况下,再安装wp以后速度飞快,不比typecho逊色,甚至比typecho还快。

就是因为这一句评论,俺们又耐不住……,所以这不就整起来了,主题选的是设计笔记的Wing,上一次用的也是这家的Adams主题(也是非常喜欢),至于后端当然是林海大佬推荐的Cyberpanel+Litespeed了,自我感觉还是不错的(也有可能是主题作者本身设计的就很优秀,因为在我另外一个测试站点跑起来速度也不错,用的是Docker装的WP)。

边刷剧边写,确实抖不出多少水了,当然就咱这点水准,真让我专业写,估计也好不到哪里去,哈哈。《深潜》这部剧是冲着成毅来的,这帅哥只要不暴雷,他的剧我还是蛮喜欢的,比如说《莲花楼》,不啰嗦了,我还是先刷剧吧。

「搜索优化」:防止搜索攻击,限制搜索频率,增强搜索能力,WordPress 一键式搜索优化增强插件

在 WordPress 进行搜索是一个常见的操作,而 WordPress 搜索的底层其实就是使用 MySQL like 语法去检索文章的标题摘要内容查出相关的文章。

一般情况 WordPress 这样搜索没有什么大的问题,可能中文分词会存在一些语义理解的小问题,但是通过多次修改关键字多搜索几次总能找到想要的文章。

WordPress 搜索存在的问题

如果碰到攻击,WordPress 的搜索就有很大的问题,因为 WordPress 搜索的链接是 https://blog.wpjam.com/?s=关键词,攻击者只要使用脚本不停的切换关键字,就会造成系统不停去数据库搜索查询,缓存都救不了!

而这样 MySQL Like 查询相对来说是比较耗时的,这就存在被攻击的漏洞,并且攻击时使用的关键字都是随机的,生成的缓存键都是不同,这时候缓存都救不了。

另外 WordPress 只是简单使用 MySQL like 语法去检索文章的标题,摘要和内容来查出相关的文章,没有别的选项,能不能只搜索标题?能不能搜索ID,甚至搜索自定义字段等。

WordPress 最强的搜索优化插件

WPJAM 的「搜索优化」插件就能为了这些功能而实现的,在碰到搜索攻击的时候,可以去限制甚至关闭 WordPress 的搜索,然后一方面,它还提供很多的选项增强 WordPress 的搜索功能。

「搜索优化」插件安装之后,在「WPJAM」菜单的「文章设置」子菜单下就有「搜索优化」标签页,点击进入即可设置搜索优化的功能:

搜索范围

首先该插件可以设置搜索范围:

可以设置文章类型支持在那些文章类型中搜索,如果不设置,WordPress 会使用默认的方式。

其次可以设置哪些用户可以进行搜索,这里有三个选项,默认「所有用户都可以搜索」,然后也可以设置「仅限登录用户搜索」,甚至还可以「关闭站点搜索功能」,这个功能在站点受到攻击的时候,可能会帮到你。

搜索限制

第二大的功能是对搜索功能进行限制:

做站点最重要的就是安全,如上图所示,首先支持限制每个 IP 每分钟搜索多少次,达到上限之后屏蔽多少分钟。在遭受搜索攻击的时候,甚至可以直接关闭搜索,最后还可以设置管理员搜索功能不受影响。

下图就是用户搜索达到上限之后,用户再次搜索之后页面显示的效果:

微信公众号的搜索也可以搜索限制,只要使用#微信机器人#的自定义回复,插件就会自动检测每个公众号用户的搜索次数:

#果酱小程序#也支持搜索限制,达到搜索上限之后,同样会报错:

嗯,「WPJAM」出品的插件很多功能有关联,但也不影响单独使用,非常方便。

此外还可以设置「搜索关键词最大长度」,太长的关键字其实搜索不出什么东西,并且还增加系统的搜索负担,所以可以选择直接屏蔽了事。这个长度的规则还是:一个汉字算两个,一个英文单词算两个,空格不算,所以大家设置的时候注意下,别搞错了。

此外为了防止不怀好意的人来瞎搞,还可以设置「不允许搜索禁用词」。禁用词是在「设置」-「讨论」-「禁止使用的评论关键字」中设置的。

当然了,最后不要限制都把自己给限制了,所以最后还有个选项,可以开启:「站点管理员搜索功能不受上面这些条件限制」。

搜索增强

我们在给一些客户做定制开发的时候,也会经常碰到一些搜索的优化,比如能不能只针对文章标题进行搜索,能不能搜索自定义字段等等,这些功能「搜索优化」插件都实现了:

首先是重定向功能,开始的时候,就会:当关键词为空时重定向到首页,只有一篇文章时重定向到文章。这个功能原本是集成在 #WPJAM Basic# 中,我写了「搜索优化」插件之后,就整和到一起了,做强做大 WPJAM「搜索优化」插件。😁

接着是我命名为「标签搜索功能」,当关键词和分类/标签/自定义分类相同时,直接展示对应的文章。

搜索结果页面标题不显示关键字,只显示「搜索结果」四个字」,这个功能大家第一眼看可能感觉没啥,其实这个功能非常重要的,这里要特别讲解一下,为什么要做这个呢?

这是因为一些 WordPress 的站点的搜索结果页面被黑产会刷了,他们把自己的网站名字和域名刷到搜索结果的页面标题上:

图片

当然上面限制了搜索关键字长度之后,在一定程度上也限制了刷搜索结果的可能性,但是要继续杜绝这种事情,通过把搜索结果页面的标题只显示「搜索结果」则可以完全的防止住,因为无论搜索搜什么,都是显示「搜索结果」这四个字:

图片


只搜索文章标题,不搜索文章内容和摘要」:字面意思,懂的吧?😂

后台文章列表支持ID搜索,如123,多个ID用「,」分隔开,如12,34,56,这个在后台要定位某篇文章 ID 的时候特别有用。

支持搜索自定义字段,功能要别注意一下,开启之后搜索效率会明显下降,然后这个功能勾选之后,还可以选择是在所有自定义字段中搜索还是在指定的自定义字段(输入 meta_key )中搜索。

WPJAM「搜索优化」

WPJAM 这个「搜索优化」是不是很强大,关于 WordPress 搜索相关的功能,我都会整合到这个插件中。

它是 WordPress 果酱知识星球福利插件,加入「WordPress果酱」知识星球(长按下图二维码)即可下载:


「WordPress果酱」知识星球福利插件基于 WPJAM Basic 开发,加入「WordPress果酱」知识星球,即可下载:

插件 简介
抓取公众号图文

支持一键同步微信公众号文章到 WordPress 博客,并支持一键将文章中所有图片都下载到 WordPress 媒体库。

搜索优化

WordPress 最强的搜索优化插件,支持限制每个 IP 每分钟搜索次数,达到上限之后屏蔽搜索时长,还可以限制搜索关键词的长度,搜索结果页面限制只显示「搜索结果」,还有以下搜索功能增强:

1. 只搜索文章标题,不搜索文章内容和摘要。
2. 当搜索关键词为空时重定向到首页,只有一篇文章时重定向到文章
3. 后台文章列表支持搜索ID。
4. 支持搜索自定义字段。

编辑器优化

一键增强 WordPress 经典 TinyMCE 编辑器:

1. 增加下划线,背景颜色,两端对齐,字体和大小设置,以及内容分页按钮。
2. 新增插入表格功能。
3. 直接插入屏幕截图。

标题设置

一键设置 WordPress 所有页面的页面标题,通过规则方式让博主可以自定义 WordPres 首页,分类,文章类型,文章详情都所有页面的页面标题。

登录优化

一键优化 WordPress 登录注册界面,并支持第三方账号登录和绑定,目前已经支持微信公众号(所有类型),微信小程序,手机号码第三方平台。

内容模板

实现在内容中插入一段共用的内容模板,通过短代码(shortcode)的方式来实现的,支持统一修改,目前支持普通的内容模板,表格内容模板和卡片内容模板三种类型。

用户管理

最强 WordPress 一键用户管理插件,一键实现以下12个功能:

1. 屏蔽个性化设置
2. 屏蔽姓氏和名字设置
3. 取消显示名称设置
4. 开启别名设置
5. 隐藏用户登录名
6. 开启登录次数限制
7. 用户最后登录时间
8. 按注册时间排序
9. 以此身份登陆
10. 生成密码重置链接
11. 自定义用户头像
12. 默认用户头像

分类管理

这是一个全能的 WordPress 分类管理插件:

1. 层式管理分类
2. 限制分类层级
3. 分类拖动排序
4. 使用数字固定链接
5. 首页文章支持分类过滤
6. 后台文章列表支持分类筛选过滤
7. 后台文章列表支持分类多重筛选

评论增强

这是一个 WordPress 评论增强插件,支持评论置顶,评论点赞和按照点赞数排序。

图片集

1. 给媒体创建个分类「图片集 | collection」
2. 图片分类限制为二级
3. 取消图片编辑入口
4. 附件页面直接图片链接。

配置器

全自动 WordPress 配置器,不用一行代码就可以开发。
支持自定义文章类型,自定义字段,自定义分类,分类选项,全局选项。

Script Loader

通过恢复 WordPress 联合加载方式来优化 WordPress 后台脚本加载。

外部链接

将文章或评论中的外部链接加上安全提示的中间页。
让用户确认之后再跳转,并还支持添加 nofollow rel 属性。

话题标签

文章中插入 #话题标签#。
如果是内部链接,直接跳转,
标签或者分类,则自动转换成标签或分类链接,
否则跳转到搜索链接。

格式文章

在 WordPress 实现真正的文章格式

草稿分享

一键生成草稿临时分享链接
并可设置分享链接的有效期

文章专题

设置文章专题,并在文章末尾显示一个文章专题列表。

文章隐藏

设置文章在列表⻚不显示,并且可以根据不同平台进行设置

Meta Data

可视化管理 WordPress Meta 数据,支持所有内置的 Meta 数据:
Post Meta,Term Meta,User Meta 和 Comment Meta。

站点选项

查看和管理所有非 WordPress 系统自动生成的站点选项。
如果你觉得某个选项无用,可以直接删除它。

后台论坛

WordPress 后台论坛,支持创建帖子,分组,消息。

微信小程序

微信小程序 WordPress 基础插件,包含基础类库和管理。

微信群二维码

轮询显示微信群二维码,突破微信群100人限制。

文章置顶

支持置顶文章排序和分类文章置顶的 WordPress 插件

静态文件

一键合并 WordPress 插件和主题的 JS 和 CSS 文件,加快页面加载速度

Debug

一键检测 WordPress 运行效率。

静风说更换域名及网址301重定向

一、 为什么要换域名

目前这个域名用了快十年了,域名注册的时间看起来还挺有意义,是2015年5月5日。当时移动端还没有兴起,我的大部分网上冲浪的时间是在电脑端,于是注册了一个三拼(三个全拼的汉语拼音)的域名,用电脑的键盘输起来很顺手(当时对域名的要求就是没有数字和下划线)。后来移动端越来越发达,手机使用的时间也越来越长,电脑使用得越来越少。这时在手机上输入博客的网址,显得很不方便,12个字母总是输错,输起来也着急。于是就萌生了把博客换成更短的域名。

思来想去,最终确定了jfsay.com这个域名,因为jfsay和博客的名称「静风说」相对应。Jasmine看到后说,为什么不用jfs.com,更短更好记。我笑说,这个我们买不起。

在输入jfsay时,发现输入法默认出来的结果是「减肥少熬夜」,竟然是劝人注重健康的,也合我意。

二、 购买域名

jfsay.com这个域名被人注册了,这几天突然看到可以注册,于是和Jasmine商量后,决定购买了。我找了好多家域名注册商对比价格,最后发现Spaceship 最便宜,5.87美元,折合人民币是42.73元。

三、 主机空间绑定新域名

域名解析很容易,添加一条A记录到主机的IP地址就可以了。主机空间绑定新域名时,却遇到了问题,提示无法绑定新的域名。问了主机商才知道,我是入门型的套餐,只能绑定一个域名。我只好把主机空间的域名改成新域名。很快,新的域名可以正常访问博客了。

四、老域名301重定向到新域名

下面要做的是把老域名301重定向到新域名,在这个地方我花了好多时间。

我原以为旧域名A记录到主机的IP,或者301重定向到新域名就可以了。后来发现需要做域名绑定,把域名和空间对应起来。主机商给我的解决方案是,需要升级套餐然后绑定多个域名,其余一概不管。我心想,只是为了网址跳转去掏钱升级主机空间太不划算。何不申请个免费的虚拟主机,只做301重定向?

免费的虚拟主机很多,随便就申请了下来。绑定域名,.htaccess重定向,很快就做好了。原以为大功告成,没想到https 的网址会提示网址不安全。也就是http的网址可以正常跳转,https的网址会卡在那里不动。

这个免费的虚拟主机没有免费的SSL,却有个SSL/TLS证书配置页面。我心想,申请一个免费SSL证书不就行了吗。我试了好几家免费证书提供商,总是在域名确认的时候出错,无法确认域名。最后在腾讯云上申请下来了。但是这个虚拟主机没有证书上传和部署的地方,查了好久也解决不了。

既然SSL证书解决不了,我想着是否能把https的网址跳转到http呢?上网查了下,都是http的网址跳转到https的,后来才知道https的网址跳转到http技术上行不通。只好作罢。

就在我一筹莫展的时候,我找到了redirhub.com,一个专门做网址跳转的网站,而且支持HTTPS。我用了十几分钟,跟着网站的步骤提示,很快就做好了301网址重定向,完美解决了https网址跳转的问题。

遥想当年,我在2015年更换域名的时候就没有这么麻烦,因为那时主机空间可以绑定多个域名,直接在.htaccess做301重定向就行了。

麻烦各位看官及时惠存新的网址,更换RSS订阅地址。

新的网址:http://www.jfsay.com/
新的RSS地址:https://www.jfsay.com/feed

目前使用的自托管服务

趁着黑五,新购置了配置高些的 VPS。折腾一番后,整理了目前自托管的服务。

第一个 VPS (Bandwagon)托管了 2 个项目 wordpress(建站) 和 Umami(数据统计),保持全球稳定的线路,和博客的稳定性:

第二个 VPS(Racknerd) 托管了 11 个项目:

  • Freshrss,RSS 阅读器,目前还安装了两个扩展:TranslateTitlesCN(谷歌翻译标题) 和 Auto Refresh(自动刷新)。日常我会使用 Reeder 登录 freshrss 账号阅读。Freshrss 因是网页端的,所以也很适合配合 immersive translate 使用。
  • wewe-rss,生成微信公众号订阅源,实际使用还挺稳定的,最后订阅了 27 个微信公众号。
  • rsshub,为其他网站生成RSS源,自建的更稳定些。
  • RSS-Bridge,订阅部分 rsshub 无法订阅的内容。本想用来订阅 instagram,但不稳定。不过功能确实挺强,便留下观察。与rsshub有很多互补之处,比如 rsshub 如果要订阅 telegram channel 比较复杂,RSS-Bridge 目前则比较简单。经费充裕的话,可以尝试 thefeedreaderbot,使用 webshare 的动态代理 ip,能够躲过 Block.
  • AdGuardHome,DNS 去广告服务,配合浏览器插件uBlock Origin,效果很好。
  • n8n,工作流自动化平台。
  • calibre-web,在线电子书库管理系统。
  • laber,跨越付费墙。
  • FileCodeBox,文件分享。
  • qBittorrent Web UI,BT 下载客户端的 Web 界面,可以远程管理和控制BT下载任务。
  • NextChat,以前叫 ChatGPT-Next-Web,ChatGPT 网页端界面,专门部署给家人使用。

更多自部署软件可参考:awesome-selfhostedTop 3 BEST applications you’ve decided to self-host? 。想轻量级省心的可以试试 YunoHost

个人倾向于将关键的非隐私类文件托管于信誉较好的大平台,如 Dropbox 和 1Password,所以没有使用自托管云盘和密码软件。

还没升级到 PHP 8.4,也可以提前在 WordPress 中使用 PHP 8.4 引入的数组函数

PHP 升级到了 8.4,个人觉得对我们写代码帮助最大的就是 PHP 8.4 引入的 array_find()array_find_key()array_any() 和 array_all() 这 4 个 array_*() 数组函数。

其实这四个函数在 JavaScript 的 Array 的实例方法中就有了,只是他的命名方式和 PHP 有点不一样,就他是用 every 和 some 而不是 all 和 any,我之前写代码的时候,也有一些地方需要使用到这四个数组函数,所以我基于 JavaScript 的方式在 #WPJAM Basic# 中集成了这四个方法。

在 PHP 8.4 发布之后我基于 PHP 8.4 命名方式做了一些优化,使得大家在没有升级到 PHP 8.4,也可以提前在 WordPress 中使用 PHP 8.4 引入的数组函数。

array_find()

array_find() 是返回数组中第一个满足回调函数的元素,如果没有则返回 null,根据这个特性,我们很容易就是先这个函数:

if(!function_exists('array_find')){
	function array_find($arr, $callback){
		foreach($arr as $k => $v){
			if($callback($v, $k)){
				return $v;
			}
		}
	}
}

比如我在字段处理中,如果字段没有定义类型,我根据它是否有其他属性来给他设置类型的代码,如果没有 array_find,我们一般这么写:

if(!empty($field['options'])){
	$field['type']	= 'select';
}elseif(!empty($field['label'])){
	$field['type']	= 'checkbox';
}elseif(!empty($field['fields'])){
	$field['type']	= 'fieldset';
}else{
	$field['type']	= 'text';
}

有了 array_find,一行搞定了:

$field['type']	= array_find(['options'=>'select', 'label'=>'checkbox', 'fields'=>'fieldset'], fn($v, $k)=> !empty($field[$k])) ?: 'text';

array_find_key()

array_find_key()array_find() 很像,只是它返回数组中第一个满足回调函数的元素的健名:

if(!function_exists('array_find_key')){
	function array_find_key($arr, $callback){
		foreach($arr as $k => $v){
			if($callback($v, $k)){
				return $k;
			}
		}
	}
}

相比 array_find() 函数的定义,唯一的区别,它 return 的是 key 而不是 value。

上面的获取字段的类型的代码,也可以使用 array_find_key() 来实现,大家看看区别:

$field['type']	= array_find_key(['select'=>'options', 'checkbox'=>'label', 'fieldset'=>'fields'], fn($v, $k)=> !empty($field[$v])) ?: 'text';

array_all()

array_all() 判断数组中的每个元素是否都满足回调函数,意思是将每个元素传递给回调函数,都要返回 true

if(!function_exists('array_all')){
	function array_all($arr, $callback){
		foreach($arr as $k => $v){
			if(!$callback($v, $k)){
				return false;
			}
		}

		return true;
	}
}

比如我写的 SMTP 发信扩展里面就有判断代码,需要「发信地址」,「邮箱账号」和「邮箱密码」这三个选项都设置了之后才生效:

if(array_all(['host', 'user', 'pass'], fn($k)=> WPJAM_SMTP::get_setting($k))){
	// 执行代码
}

array_any()

array_any() 也是判断数组的元素是否满足满足回调函数,但是 array_any() 只需要一个满足即可,而 array_all() 一样则是需要全部都满足:

if(!function_exists('array_any')){
	function array_any($arr, $callback){
		foreach($arr as $k => $v){
			if($callback($v, $k)){
				return true;
			}
		}

		return false;
	}
}

上面例子中,发信设置扩展需要「发信地址」,「邮箱账号」和「邮箱密码」这三个选项都要设置,换成 array_any() 的思维,则只要一个没有设置就返回:

if(array_any(['host', 'user', 'pass'], fn($k)=> !WPJAM_SMTP::get_setting($k))){
	return;	// 返回,不生效
}

大家对比一下两个例子的代码,使用相类似的例子,通过不同的写法,也是一种更加清晰的区分函数的方式。😄

标题说了,还没升级到 PHP 8.4,也可以提前在 WordPress 中使用 PHP 8.4 引入的数组函数,意思只要你更新 WPJAM Basic 到最新版就能使用了,所以记得更新,有什么问题,记得给我留言。

网站速度很慢?使用 WordPress 短时缓存(Transients)来优化数据库查询和 HTTP 响应!

每个人都想要一个速度很快的网站,网站速度越快,用户停留和点击页面或购买产品的时间就越长,加快网站速度的方法之一是开启缓存,而缓存背后的逻辑就是存储信息,更具体一点说,就是找到一个比连接数据库更快的存储信息的地方。

在 WordPress 中,如果一些复杂的 SQL 查询或者耗时的 HTTP 请求,其实它们的结果在一定时间内是不变的,那么为了网站速度,如果把这些操作的结果缓存起来,这样下次进行同样的 SQL 查询和 HTTP 请求的时候,就可以直接从缓存中获取数据,从而可以显著加快网站的速度,当然一些复杂计算的结果也可以通过该方法进行缓存。

 WordPress Transients

那么在 WordPress 中如何快速缓存 SQL 查询和 HTTP 响应呢?这个时候就要用到 WordPress 的短时缓存(Transients)功能。

什么是短时缓存(Transients)

我们知道 WordPress 缓存有多种类型,比如对象缓存、浏览器缓存、页面缓存甚至数据库缓存,每种类型都有其用途和设置步骤,比如需要安装插件和更改服务器配置以启用对象缓存等。

那么今天介绍的 Transients API,是 WordPress 用于在页面加载期间临时存储 WordPress 中的信息,Transients 本身是“短暂的”或“临时的”意思,那么 Transients API 可以理解为临时缓存或者短暂缓存的意思,我这里将它翻译成短时缓存,它是 WordPress 用来缓存一些复杂的 SQL 查询和运算结果的最简单的方法。

它给这些需要缓存的数据一个过期时间,并且时间一到就会自动删除,所以在制作 WordPress 插件的时候,需要存储一些有一定生命周期的数据的时候,Transients API 就是最好的选择。

简单说,Transients 是一种非常强大的工具,它不仅可以用来避免对页面内容进行不必要的数据库请求,还可以加快生成复杂标记的速度并加快耗时的第三方 API 请求。 

Transients 相关函数

首先说下,Transients 的存储,如果服务器开启了 #Memcached#,那么缓存的数据就会存在 Memcached 的内存中,如果没有开启的话,则存储到 WordPress 数据库的 Options 表中

所以它接口函数和 WordPress 的 Option API get_option, add_option, update_option, delete_option))基本一样,唯一区别就是 Transients API 有一个过期时间,并且它没有 add 方法,统一合并成 set 了,所以 WordPress Transients API 有以下三个函数:

// 保存一个数据到短时缓存中
set_transient( string $transient, mixed $value, int $expiration )

// 从短时缓存中获取一个数据
get_transient( string $transient )

// 从短时缓存中删除一个数据
delete_transient( string $transient )

函数的使用过非常简单,这里不做详细解释,简单注意下两点:

  1. 如果使用获取短时缓存函数 get_transient 去获取数据,已经过期或者不存在的情况下是返回 false 的。
  2. 完全不用担心 Transients API 会将数据库的 Options 表塞满数据,因为临时变量一旦过期,下次获取的时候就会自动被删除,并且上面也说了如果服务器开启了 #Memcached#,那么缓存的数据就会存在 Memcached 的内存中。

一个应用 Transients 的例子

🙋‍♀️🌰 假设你要获取博客的浏览最高的 10 篇文章,文章的浏览数据一般是存在 PostMeta 表中,所以这样的数据库查询会用到 Posts 表和 PostMeta 表进行联表查询,如果文章数量比较多的情况下,这样的查询一般是比较慢的。

而事情的另一面,博客浏览最高的 10 篇文章一般来说在一段时间(比如:12小时)之内很可能是不变的,所以这个功能最适合使用 Transients API 进行缓存了:

$top_10_posts = get_transient('top_10_posts');

if(false === $top_10_posts){ // 临时变量过期了或者根本就没有创建

	// 通过 SQL 查询获取流量最高的 10 篇文章,
	$top_10_posts = wpjam_get_top_viewd_posts(10);

	// 把临时变量存到数据库中,时间为 12 个小时
	set_transient('top_10_posts', $top_10_posts, HOUR_IN_SECONDS*12);
}

我们首先使用 get_transient('top_10_posts') 函数从缓存中看看有没有缓存,如果没有,该函数是返回 false 的。

程序获取缓存结果为 false 的时候,就通过 wpjam_get_top_viewd_posts 这个带有复杂 SQL 的函数获取文章,然后通过函数 set_transient('top_10_posts', $top_10_posts, HOUR_IN_SECONDS*12) 存到缓存中,并且过期时间设置为 12 小时。

这样下次再去获取浏览最高的文章,直接从缓存中返回了,就不用担心不用担心数据库查询过慢的问题了。

使用 Hook 删除短时缓存

如果由于某种原因某篇流行文章删除,这个时候可能流量最高的文章都可能发生变化,我们就可以使用 delete_transient 函数把这个临时变量删除了,这样我们可以使用 WordPress 的删除文章的 Hook delete_post 进行操作:

add_action('delete_post', fn() => delete_transient('top_10_posts'));

如果你想有新文章发布了,虽然这时候一般不会影响浏览最高的文章列表,但是如果想,也可以把缓存清理了,这时候用到是 publish_post Hook:

add_action('publish_post', fn() => delete_transient('top_10_posts'));

WPJAM 终极方法

虽然 Transients API 的使用非常简单,它主要逻辑就是首先使用 get_transient() 函数获取缓存,=如果没有,再通过函数 set_transient() 将数据存到缓存中。

但是这里都有要写个判断,并且缓存的名称也要重复写两次,对于我这么懒的程序是不可能接受的,另外它的逻辑感觉上在破坏了程序的主逻辑,所以我在 #WPJAM Basic# 中集成了 wpjam_transient 函数,它通过回调的方式,让只需一步就实现 WordPress 短时缓存:

首先我们实现看看我的 wpjam_transient 函数的实现:

function wpjam_transient($name, $callback, $expire=86400){
	$data	= get_transient($name);

	if($data === false){
		$data	= $callback();

		if(!is_wp_error($data)){
			set_transient($name, $data, $expire);
		} 
	}

	return $data;
}

可以看到 wpjam_transient 函数把获取和设置短时缓存的函数都内置到了函数中,你只需要关注你程序的主逻辑,所以上面的缓存的浏览最高的 10 篇文章的代码可以简化为 1 行代码:

wpjam_transient('top_10_posts', fn()=> wpjam_get_top_viewd_posts(10), HOUR_IN_SECONDS*12);

是不是非常简洁。🤭

总结

WordPress 短时缓存(Transients API)是 WordPress 用于在页面加载期间临时存储 WordPress 中的信息,该功能用的好,特别是用于缓存复杂的 SQL 查询,耗时 HTTP 请求,以及复杂计算的结果等,对于站点有明显的提高,#WPJAM Basic# 集成的 wpjam_transient 函数进一步提高使用效率,只需一步就实现 WordPress 短时缓存。

在 WordPress 中如何设置背景色透明度?

最近开始写一些 WordPress 专业的知识,阅读数奇低,然后我发一些微信昵称技巧,又说我天天发这些小学生爱玩的玩意,写点文章真不容易。

那我两天发点专业的东西,两天发点小学生的东西,剩下三天我看着办,这样总行吧?

哈哈,那就天就发布一点点专业的东西,就是我们做网页开发的时候的时候如何设置透明背景。

为什么背景要设置透明度?

首先说下为什么背景要设置透明度,比如最近我给公司实现做的表格应用的时候,有个单元格条件样式的功能:

就是类似于 Excel 的条件格式化的功能,让数据根据不同的值显示不同的样式,如上图所示,可以设置,加粗,文本颜色,和填充颜色,其中填充就是设置单元格的背景颜色 :

由于我们的表格每一行本身就有间隔背景色(或者说斑马色),如果我们设置的单元格背景没有透明度的话,就会看不到间隔色,看数据不太方便,另外也会比较显眼,抢过了主体文本的颜色

也有人可能喜欢这种比较强烈的配色方式,不过不管了,我觉这个例子就是想给大家说下,我做了一个表格应用,可以自定义单元格样式,嘻嘻,另外也是为了点下今天的主体,怎么设置背景透明度。

如何设置背景透明度?

首先这个是 CSS 的活,我们都知道设置背景色的 CSS 代码:

// 使用 RGB
.background {
  background-color: rgb(255, 0, 0); /* 红色背景 */
}

// 使用 HSL
.background {
  background-color: hsl(120, 100%, 50%); /* 绿色背景 */
}

// 使用 HEX 6位16进制颜色代码
.background {
  background-color: #0000FF; /* 蓝色色背景 */
}

// 使用 HEX 3位16进制颜色代码
.background {
  background-color: #00F; /* 蓝色色背景 */
}

上面展示了 RGB 和 HSL 以及 HEX 16 进制三种设置背景的方法,但是这样设置都是不透明的。

那么如何设置透明度呢?其实也非常简单,只要给上面的颜色加上透明度的 Alpha 通道即可:

// 使用 RGBA
.background {
  background-color: rgba(255, 0, 0, 0.5); /* 红色背景 50% 透明度*/
}

// 使用 HSLA
.background {
  background-color: hsla(120, 100%, 50%, 0.3); /* 绿色背景  50% 透明度*/
}

// 使用 HEX 8位16进制颜色代码
.background {
  background-color: #0000FF80; /* 蓝色色背景 50% 透明度*/
}

// 使用 HEX 4位16进制颜色代码
.background {
  background-color: #00F8; /* 蓝色色背景 50% 透明度*/
}

其中 RGB 和 HSL 两种方法则在起方法名后面加上 A 即可,然后取值范围从 0(完全透明)到 1(完全不透明)。

16 进制的方法则有点复杂,使用16进制颜色代码设置背景透明度可以通过使用8位(#RRGGBBAA)或4位(#RGBA)的16进制格式来实现,其中最后两位(AA)或最后一位(A)代表透明度(Alpha)。透明度的值范围从00(完全透明)到FF(完全不透明)。

所以上面的例子中 0000FF 是蓝色,80(即128/255)表示大约50%的透明度。另外需要特别注意一下虽然现代浏览器普遍都支持16进制颜色透明度代码,但在某些旧版本的浏览器中可能不会正常工作,因此,如果你需要兼容,建议还是使用 rgba()hsla() 函数。

另外使用 opacity 定义透明度,但是他是使得整个元素透明度都下降,包括它的背景、文本和边框等,这个时候要注意你是要整体还仅仅是背景了。

.background {
  background-color: #0000FF; /* 蓝色色背景 */
  opacity: 0.5; /* 整个元素50% 透明度 */
}

在 WordPress 中如何设置支持透明度的颜色字段

我们知道有个 wp-color-picker 组件,可以让我们在设置输入字段的时候,可以直接选择颜色(在 WPJAM Basic 添加字段的时候,将 type 设置为 color 即可):

但是他无法设置透明度,Sergio 就更新了一下 wp-color-picker 组件,发不了 wp-color-picker-alpha 组件,支持通过拖拉即可设置透明度,如下图所示:

哈哈,WPJAM Basic 最新版也支持了该功能,在设置添加字段的时候,将 type 设置为 color 之外,还需要加上 data-alpha-enabled 属性,并将其设置为 true,比如我上面设置背景色的代码:

$fields	= [
	'background-color'	=> ['type'=>'color',	'button_text'=>'填充颜色',	'data-alpha-enabled'=>true]
];

我和大胡子做的模块化主题「Modular」也很快会加上该功能:

WordPress「站点选项」插件:一键查看和管理站点全局选项

前面我写了 WordPress 中如何设置全局选项?一文详解 WordPress 的 Option 功能,为了方便 WordPress 所有站点选项的管理和设置,我做了一个 WordPress「站点选项」插件,可以查看和管理所有 WordPress 站点的全局选项,特别是选项不再使用了,可以通过该插件直接删除它。

为什么开发这个插件?

我们知道绝大部分的插件和主题都会有选项设置,这些选项设置就会在 WordPress Option 表里面插入一些数据,如果这些插件或者主题不用的话,这些加入到 Option 表里面的数据一般都还会留在那里。

其实这些站点选项数据留在那里,问题也不大,不过总有一些有洁癖的同学,想清理一下,比如我,所以就开发了这个「站点选项」WordPress 插件。

查看和管理站点选项

安装好之后,在 WPJAM 菜单下会多出一个「站点选项」的子菜单,点击进去,即可查看站点上所有的全局选项:

对于这些选项数据,如果觉得没有任何用了,比如是插件停用之后的残留,就可以删除他们,不过删除前还是要再次确保不再使用。

除了删除之外,我们还可以进行「编辑」和「重命名」等操作,但是进行这些操作之前,还是要确认该操作不会造成任何问题。

另外对于如果数值是数组的选项,在列表是解析出来显示的:

但是在编辑的时候,在编辑的时候,显示的是序列化的:

所以编辑的时候,也要注意,不要搞错了,这时候建议的通过「替换」进行操作:

最后WordPress 选项「Option」的自动加载的功能,该功能是在 WordPress 的加载的时候,开启的「自动加载的选项就会一次全部加载,这样下次再使用该选项的时候,就无需再从数据库中获取。

所以该插件也可以加上一个设置「自动加载」的功能,可以开启或者关闭某个选项的「自动加载」功能,如下图所示,在列表页最后一列自动加载的开关点击一下即可切换:

总之,WordPress 「站点选项」是一个非常方便的后台数据管理 WordPress 插件,可以让你一键查看和管理站点的全局选项,但是操作之前还是要确保你对这些的操作已经足够了解,是自己真正需要的。😄

WordPress 「站点选项」插件

WordPress 「站点选项」插件是 WordPress 果酱知识星球福利插件,加入「WordPress果酱」知识星球(长按下图二维码)即可下载:


「WordPress果酱」知识星球福利插件基于 WPJAM Basic 开发,加入「WordPress果酱」知识星球,即可下载:

插件 简介
抓取公众号图文

支持一键同步微信公众号文章到 WordPress 博客,并支持一键将文章中所有图片都下载到 WordPress 媒体库。

搜索优化

WordPress 最强的搜索优化插件,支持限制每个 IP 每分钟搜索次数,达到上限之后屏蔽搜索时长,还可以限制搜索关键词的长度,搜索结果页面限制只显示「搜索结果」,还有以下搜索功能增强:

1. 只搜索文章标题,不搜索文章内容和摘要。
2. 当搜索关键词为空时重定向到首页,只有一篇文章时重定向到文章
3. 后台文章列表支持搜索ID。
4. 支持搜索自定义字段。

编辑器优化

一键增强 WordPress 经典 TinyMCE 编辑器:

1. 增加下划线,背景颜色,两端对齐,字体和大小设置,以及内容分页按钮。
2. 新增插入表格功能。
3. 直接插入屏幕截图。

标题设置

一键设置 WordPress 所有页面的页面标题,通过规则方式让博主可以自定义 WordPres 首页,分类,文章类型,文章详情都所有页面的页面标题。

登录优化

一键优化 WordPress 登录注册界面,并支持第三方账号登录和绑定,目前已经支持微信公众号(所有类型),微信小程序,手机号码第三方平台。

内容模板

实现在内容中插入一段共用的内容模板,通过短代码(shortcode)的方式来实现的,支持统一修改,目前支持普通的内容模板,表格内容模板和卡片内容模板三种类型。

用户管理

最强 WordPress 一键用户管理插件,一键实现以下12个功能:

1. 屏蔽个性化设置
2. 屏蔽姓氏和名字设置
3. 取消显示名称设置
4. 开启别名设置
5. 隐藏用户登录名
6. 开启登录次数限制
7. 用户最后登录时间
8. 按注册时间排序
9. 以此身份登陆
10. 生成密码重置链接
11. 自定义用户头像
12. 默认用户头像

分类管理

这是一个全能的 WordPress 分类管理插件:

1. 层式管理分类
2. 限制分类层级
3. 分类拖动排序
4. 使用数字固定链接
5. 首页文章支持分类过滤
6. 后台文章列表支持分类筛选过滤
7. 后台文章列表支持分类多重筛选

评论增强

这是一个 WordPress 评论增强插件,支持评论置顶,评论点赞和按照点赞数排序。

图片集

1. 给媒体创建个分类「图片集 | collection」
2. 图片分类限制为二级
3. 取消图片编辑入口
4. 附件页面直接图片链接。

配置器

全自动 WordPress 配置器,不用一行代码就可以开发。
支持自定义文章类型,自定义字段,自定义分类,分类选项,全局选项。

Script Loader

通过恢复 WordPress 联合加载方式来优化 WordPress 后台脚本加载。

外部链接

将文章或评论中的外部链接加上安全提示的中间页。
让用户确认之后再跳转,并还支持添加 nofollow rel 属性。

话题标签

文章中插入 #话题标签#。
如果是内部链接,直接跳转,
标签或者分类,则自动转换成标签或分类链接,
否则跳转到搜索链接。

格式文章

在 WordPress 实现真正的文章格式

草稿分享

一键生成草稿临时分享链接
并可设置分享链接的有效期

文章专题

设置文章专题,并在文章末尾显示一个文章专题列表。

文章隐藏

设置文章在列表⻚不显示,并且可以根据不同平台进行设置

Meta Data

可视化管理 WordPress Meta 数据,支持所有内置的 Meta 数据:
Post Meta,Term Meta,User Meta 和 Comment Meta。

站点选项

查看和管理所有非 WordPress 系统自动生成的站点选项。
如果你觉得某个选项无用,可以直接删除它。

后台论坛

WordPress 后台论坛,支持创建帖子,分组,消息。

微信小程序

微信小程序 WordPress 基础插件,包含基础类库和管理。

微信群二维码

轮询显示微信群二维码,突破微信群100人限制。

文章置顶

支持置顶文章排序和分类文章置顶的 WordPress 插件

静态文件

一键合并 WordPress 插件和主题的 JS 和 CSS 文件,加快页面加载速度

Debug

一键检测 WordPress 运行效率。

WordPress 中如何设置全局选项?一文详解 WordPress 的 Option 功能!

对于进行 WordPress 开发来说,肯定会了解到的一个开发功能就是 WordPress 设置选项的创建,访问,修改和删除,比如主题和插件的设置选项处理,那么 WordPress 具体是怎么管理全局选项的呢?

WordPress 全局选项管理的接口叫做 Option API,它是一种简单且标准化的在数据库中存储数据的方法,它使用给定的自定义名称将数据存储到 wp_options 表中。

WordPress 提供了 Option 的增删查改四个操作的函数,如果你安装的 WordPress 是多站点版本,那么还有对应的 _site_ 函数应用全网选项的函数,同样使用给定的自定义名称将数据存储到 wp_sitemeta 表中。

但是多站点的选项设置用到场景比较少,所以今天我们还是详细介绍一下 Option 的增删查改四个操作的函数:

增加选项|add_option

add_option( string $option, mixed $value = '', string $deprecated = '', string|bool $autoload = null ): bool

add_option 函数实现给 WordPress 增加一个选项,选项的名称通过参数 $option 指定,选项的值 $value 支持标量和非标量,如果非标量的话,则该值可以被序列化,但是无需手动对值进行序列化,该函数会在将值插入数据库之前会进行序列化操作,所以简单说,就是把各种类型值 $value 无需做任何处理,以 $option 作为名称添加到选项中。

另外第三个参数是被放弃的,不用管,如果要用到第四个参数 $autoload 的时候,三个参数的位置直接输入空字符串即可,这里简单说下一下第四个参数 $autoload,用于定义在 WordPress 启动的时候是否自动加载该选项到内存中,该参数默认值为 null,意思是它会自动根据 $value 大小来决定是否自动加载,小于 150000 字节则会自动加载,如果不管大小都要求自动加载,则可以将其设置 'on',无需自动加载,则需要将其设置为 'off'

最后如果该选项如果被成功添加,则返回 true,否则 false,额外说一下如果该选项数据库已有,则无法添加成功,如果你是想如已存在则修改,则建议用到后面介绍 update_option 函数。

add_option( 'my_option', 'my_value' );

比如上面代码就添加一个名称为 'my_option' 选项,它的值为:'my_value'

删除选项|delete_option

delete_option( string $option ): bool

delete_option 函数删除名称为 $option 的选项,删除选项函数比较简单,比如下面的代码就是删除名称为 'my_option' 选项。

delete_option( 'my_option' );

查询选项|get_option

get_option( string $option, mixed $default_value = false ): mixed

get_option 函数用于获取名称为 $option 的选项的值,除该参数之外,它还有第二个参数 $default_value,该参数默认值为 false,如果选项不存在,则返回该值。

get_option 函数返回值的类型可能会因与保存或更新选项时传递的类型不同而不同,如果选项值被序列化了,那么在返回时它将被反序列化,在这种情况下,返回的类型将会相同,比如存储一个如数组这样的非标量值,将返回相同的数组。

在大多数情况下,非字符串的标量和 null 值存储被转换并返回为字符串等效值。比如通过 add_option( 'my_option', $value ) 添加选项,然后通过 get_option( 'my_option' ) 获取选项值将会:

  • false 返回 string(0) ""
  • true 返回 string(1) "1"
  • 0 返回 string(1) "0"
  • 1 返回 string(1) "1"
  • '0' 返回 string(1) "0"
  • '1' 返回 string(1) "1"
  • null 返回 string(0) ""

如果添加是非标量的值,比如 add_option( 'my_array', array( false, 'str', null ) ), 返回的值将与原始值完全相同,因为它在保存到数据库之前已经被序列化了:

array(3) {
    [0] => bool(false)
    [1] => string(3) "str"
    [2] => NULL
}

更新选项|update_option

update_option( string $option, mixed $value, string|bool $autoload = null ): bool

update_option 函数的参数和 add_option 函数参数除了没有放弃的参数,基本都是一致的,用法也是一样的,这里就不重复了。

那么 update_option 函数和 add_option 函数的区别主要是:add_option 函数只会添加,如果已经存在,则不会覆盖,而 update_option 函数则会修改现有的选项,如果不存在,它则会调用 add_option 函数增加。

update_option( 'my_option', 'my_value' );

比如上面代码就修改名称为 'my_option' 选项的值为 'my_value',如果不存在则增加该选项,值也是为 'my_value'。

总结

关于 WordPress 全局选项,或者说站点选项的开发接口介绍,最核心的部分就是这四个函数,只要认真阅读这篇文章,那么进行开发的时候基本不会有太大的问题。

WordPress 新一代默认主题 Twenty Twenty-Five「2025」初探

WordPress 6.7 版本将推出一个新的默认主题:Twenty Twenty-Five,今天我们一起看看:

概念

Twenty Twenty-F​​ive 的设计理念可以总结为一句话:「简单的事情应该直观的,而复杂的事情应该可行的」。

所以该主题就体现了极致的灵活性和适应性,使用户能够通过多种模式和风格讲述自己的故事,有多种图案和风格可供选择,主题中融入的自然美景和历史的片段唤起了无常、时间流逝和不断进化的想法。

拼贴画形式的构图展示了 2025 年默认主题中使用的许多照片。

模式

在结构上,Twenty Twenty-Five 主体提供了一套健全的模板,为服务、关于、落地页、产品、行动呼吁、事件等多个类别设计了广泛的模式,提高了操作性并让用户快速撰写有针对性的页面。

A broad range of patterns designed for the 2025 theme in categories like services, about, landing pages, products, calls to actions, events, etc.

样式

考虑到该主题的全球使用,从设计的最初概念步骤开始,就考虑了支持多种语言的高质量和全面的字体,此外,主体还完善了一组不同的调色板,将其作为风格样式捆绑在主题中。

为 2025 年默认主题设计的八种不同的调色板。
为 2025 年默认主题设计的八种不同的字体搭配。
展示针对 2025 主题设计的不同风格变化模板的九个示例。

模板

Twenty Twenty-F​​ive 还提供了多用途的博客模板集:带有侧边栏的以文本为中心的博客模板、强调特色图片的照片博客模板以及具有多样化内容的更复杂的博客模板。

Twenty Twenty-F​​ive 并且和站点编辑器完全兼容,并使用了许多新的设计工具,例如网格块和图案/部分样式。

个人博客(默认)

为了保持简单的理念,个人博客倾向于依赖一个可以正常工作的默认模板,无论是否想写一个带有标题和特色图片的文章,并且显示文章的所有内容,而不仅仅是摘要。

两个模型:左边的模型显示带有图片、帖子标题和帖子全部内容的博客帖子,右边的模型显示单篇帖子。

照片博客(替代)

主要为摄影或作品集定制的替代“照片博客”模板,依赖于图像密集型的方法,具有可用于多种用途的有趣布局。

两个模型:左边的模型仅显示博客文章的特色图片,右边的模型显示带有全宽图像的单篇文章。

复杂博客(替代)

最后,复杂博客替代模板集更适合内容复杂度更高的网站。其中一些模板的字体范围更加多样,设计也更具个性,可以吸引不同的受众。

两个模型:左侧的模型显示了一个 3 列网格,其中的博客文章包含特色图片和文章标题,后面跟着一个 2 列网格;右侧的模型显示了一个单篇文章,其中有一个左对齐的大标题、文章元数据和一张宽图像,后面跟着文章内容,右侧有一个侧边栏。

主题随着 WordPress 6.7 一起发布。在这之前推荐我们主题:

深度自定义与模块化设计的 WordPress 企业主题来了」总结一下,可以说 Modular 主题完全是为了企业建站而生的:

如果你是一家企业的 IT 负责人,通过这个主题,自己设计一下图片,就能快速完成企业交给你的任务,再加上 WordPress 本身的易用性,这款主题可以说让你每天的「摸鱼」时间成倍增加。

如果你是一个平时接接单给企业做个小网站的自由职业者,这款主题可以让你快速赚到钱,你完全不用操心代码的事情,只需要沟通清楚企业的需求,找到对应的模块搭建进去即可,让你只需要800块钱的成本就能够构建5000-10000的企业站点。

最后的最后,Modular(模块化)主题是一个付费的主题,基于 WPJAM Basic 插件构建,原价2680 元,现在只需 688 元就能构建一个完全个性化的企业站点,购买请复制下面链接或者点击阅读原文:

https://wpjam.com/go/modular

在 PHP 和 WordPress 中如何给数组切片

从一个数组中取出一段数据,或者说切片,这是非常常见的数组操作,PHP 已经内置了了 array_slice 函数来实现这个操作,但是面对关联数组的一些基于 key 的切片操作,该函数就有点力不从心了,那么我们面对这些复杂的情况,怎么操作呢?今天就通过这篇文章详细讲解一下在 WordPress 中如何给数组切片。

还是从 array_slice 说起

array_slice 的简介就是从数组中取出一段,它是从指定偏移量开始提取特定数量的元素,具体的语法:

array_slice(array $array, int $offset, int $length, bool $preserve_keys = false)
  • $array:待切片的数组。
  • $offset:切片开始的位置,从 0 开始计数,支持负数,从末端开始算起。
  • $length:切片元素的长度。
  • $preserve_keys(可选):是否保留切片元素的键名,默认值为 false。注意无论本参数如何设置,都会保留字符串的键。

还是看具体的例子吧。

// 从数组中取出第一个元素
$slice = array_slice([1, 2, 3, 4, 5], 0, 1); // [1]

// 从数组中取出第二个和第三个元素
$slice = array_slice([1, 2, 3, 4, 5], 1, 2); // [2, 3]

如果是用负偏移量,将从数组末尾开始计数:

// 从数组中取出倒数第二个元素
$slice = array_slice([1, 2, 3, 4, 5], -2, 1); // [4]

如果不指定长度,则切片将包括从偏移量到数组末尾的所有元素:

// 从数组中取出第二个和之后所有的元素
$slice = array_slice([1, 2, 3, 4, 5], 1); // [2, 3, 4, 5]

如果将 $preserve_keys 参数设置为 true,则切片元素将保留其原始键名:

// 从数组中取出第二个元素,并保留键名
$slice = array_slice([1, 2, 3, 4, 5], 1, 1, true); // [1 => 2]

对于关联数组,则  $preserve_keys 不管参数是什么值,都会保留原始的键:

// 从关联数组中取出第二和第三个个元素,下面都是输出 ['b'=>2, 'c'=>3]
$slice = array_slice(['a'=>1, 'b'=>2, 'c'=>3, 'd'=>4, 'e'=>5], 1, 2, true);

$slice = array_slice(['a'=>1, 'b'=>2, 'c'=>3, 'd'=>4, 'e'=>5], 1, 2);

关联数组如何切片

从上面的例子可以看出 array_slice  是基于偏移量和长度进行切片的,但是对于关联数组来说,如果我们要基于数组的 key 进行切片怎么操作?

WordPress 的 wp_array_slice_assoc

WordPress 内置有个 wp_array_slice_assoc 函数,它基于一个健的列表从关联数组中取出数组,具体的语法:

wp_array_slice_assoc( array $input_array, array $keys )
  • $input_array:待切片的关联数组。
  • $keys:健的列表。
// 从数组中取出键为 c 和 b 的元素
$slice = wp_array_slice_assoc(['a'=>1, 'b'=>2, 'c'=>3, 'd'=>4, 'e'=>5], ['c', 'b', 'f']); 
// 结果为 ['c'=>3, 'b'=>2] 

取出的数组是按照 $keys 参数的顺序取出来的,上面的例子中,我故意把 c 放到 b 前面,取出的关联数组的 key 的顺序也是按照这个顺序,另外数组中不存在的 key,取出关联的数组也是不存在的,比如上面例子的 f。

WPJAM Basic 的 wpjam_slice

因为 wp_array_slice_assoc 取出的关联数组的顺序是按照输入的 $keys 参数顺序的,但是有些情况下我们要求取出的关联数组的顺序不要动,即不关系 $keys 的顺序,所以我在 #WPJAM Basic# 中加入了一个 wpjam_slice 函数,它取出的数组是不会变动的,具体的语法:

wpjam_slice( array $input_array, array $keys )
  • $input_array:待切片的关联数组。
  • $keys:健的列表。

还是看具体的例子吧:

// 从数组中取出键为 c 和 b 的元素
$slice = wpjam_slice(['a'=>1, 'b'=>2, 'c'=>3, 'd'=>4, 'e'=>5], ['c', 'b', 'f']); 
// 结果为 ['b'=>2, 'c'=>3] 

最后取出的关联数组的是按照原先的顺序,并且不存在的 key,取出关联的数组也是不存在的。

此外 $keys 参数除了数组之外,还支持字符串,通过空格或者逗号转化成数组:

// 从数组中取出键为 c 和 b 的元素,$keys 参数为逗号间隔字符串
$slice = wpjam_slice(['a'=>1, 'b'=>2, 'c'=>3, 'd'=>4, 'e'=>5], 'c,b,f']); 
// 结果也是 ['b'=>2, 'c'=>3]

// 从数组中取出键为单个元素
$slice = wpjam_slice(['a'=>1, 'b'=>2, 'c'=>3, 'd'=>4, 'e'=>5], 'c']); 
// 结果为 ['c'=>3] 

这样 WordPress 中给数组如何切片,是不是方法更多了一下,哈哈!

中文环境下,WordPress 截取个摘要,竟然有那么多问题!

我们先从 WordPress 文章摘要功能说起,大部分 WordPress 主题在首页,分类搜索等各种列表页,会只显示文章摘要,而不显示文章内容全文,所以摘要很重要,在列表页,用户是否会点击查看这篇文章,摘要会起到很重要的效果。

怎么设置文章摘要

那么怎么设置摘要呢?在使用经典编辑器的年代,摘要是非常容易设置的,就在文章内容的下面,很多人写完文章,顺手也设置了文章摘要:

但是升级到古腾堡编辑器之后,很多人就发现不知道去哪里设置摘要了,摘要设置文本框被移到编辑器右侧文章设置的很下面,很多人没有认真去看,还以为没了。😅

甚至有些人因为这个原因,从来没有去设置过文章摘要,也有人因为这个原因坚持在用经典编辑器。😅

#WPJAM Basic# 插件支持一键屏蔽古腾堡编辑器,此外 #WPJAM Basic# 还提供一个扩展「摘要快速编辑」,让你可以在文章列表快速设置文章摘要:

使用文章摘要

设置了 WordPress 摘要,那就要去用,这个一般来说都是主题开发者的工作,这里简单了解一下就好,如果你要自己修改主题,那就就要认真看下。😄

WordPress 提供了两个文章摘要的模板函数,这个知道就好,一般主题就是使用这两个函数实现的。

1. get_the_excerpt( $post = null ) ,用于获取文章的摘要,它只有一个参数,就是 $post,可以是文章对象,或者文章 ID, 也可以不传,不传则获取当前文章的摘要。

2. the_excerpt(),直接输出当前文章的摘要,该函数没有任何参数,所以模板开发很简单,直接在文章列表页使用该模板函数即可。

自动获取文章摘要

由上可知,并不是每篇文章都设置了摘要,这个时候,WordPress 默认会自动获取:

WordPress 默认会使用 wp_trim_excerpt 去获取文章内容,加上摘要长度传递给 wp_trim_words 函数处理, wp_trim_words 会基于用户所处的环境:

  • 单词之间没有空格的,比如中日韩,它就按照中文字符和英文字符都算一个字符来截取。
  • 单词之间有空格的,比如英文或其他,它就按照空格或者回车来获取单词数组,截取输入长度的单词数。

这种算法对于中文来说,非常不好,因为一个中文字符,宽度基本上是一个英文字符的两倍,如果文章中的中英文混排的话,截取出来肯定会长度不一。

所以现在很多主题会加入自动摘要截取优化的代码,但是有些主题直接使用 substr 函数来获取摘要,该函数是把中文算成 3 个字符,英文字符算 1 个字符,这个算法有点奇怪,但是如果英文不多,截取的产地还算一致,但是比较致命的是,该函数无法判断一个完整的中文字符,截取的时候,可能在中文字符中间劈开了,然后就出现乱码:😅

所以对于中文环境,最好按照「中文 2 个字节,英文 1 个字节」的方式来截取,并且中文字符会当作一个完整的字符来处理,而采用该截取算法 PHP 函数则是 mb_strimwidth

mb_strimwidth($text, 0, 240, '...', 'utf-8');

为了方便大家的设置,我在 #WPJAM Basic# 集成了自动获取文章摘要的设置,无需修改任何代码,简单选择设置一下即可,点击「WPJAM」菜单下「文章设置」子菜单下之后可以看到:

当文章未设置摘要时候,默认还是 WordPress 默认自带的截取摘要的方式,然后 WPJAM Basic 插件增加了两个选项:

  • 第一个很简单直接:直接不显示摘要。
  • 第二个选项就是前面介绍的算法,按照中文最优方式截取,并且还可以设置文章摘要的长度。
    再次提醒一下注意算法是「中文 2 个字节,英文 1 个字节」,设置长度的时候要注意下。

这个时候再看看,除了第二篇是后台设置了摘要,其他三篇摘要都基本差不多长度了,并且也没有出现乱码:

mb_strimwidth 不存在?

写到这里,你是不是觉得 WordPress 摘要的问题已经解决了?现在还存在两个问题:

1. #WPJAM Basic# 的设置不生效,还是出现上面那种乱码,或者长短不一的情况。

因为插件的优化摘要的代码和主题优化摘要的代码优先级是不一定的,可能主题占优了,那么你这个时候应该咨询主题作者,让他提供选项,然后你可以关闭主题的摘要优化功能。

2. 直接报错了:

Call to undefined function mb_strimwidth()

好吧,mb_ 打头的函数,需要 PHP 安装 mb_string 扩展,在后台「WPJAM」菜单下的「系统信息」的子菜单中,可以快速查看:

所以我又升级了一下 #WPJAM Basic# ,做了兼容,就是说现在没有装该扩展,也有该函数了:

if(!function_exists('mb_strimwidth')){
	function mb_strimwidth($str, $start, $width, $trimmarker=''){
		preg_match_all('/./us', $str, $match);

		$count	= count($match[0]);
		$start	= $start < 0 ? $count-1+$start : $start;
		$chars	= array_slice($match[0], $start);

		if($width >= array_sum(wpjam_map($chars, fn($char)=> ord($char) >=224 ? 2 : 1))){
			return implode('', $chars);
		}

		$length	= 0;
		$result	= '';
		$count	-= $start;
		$width	-= strlen($trimmarker);

		for($i=0; $i<$count; $i++){
			$char	= $chars[$i];
			$w		= ord($char) >= 224 ? 2 : 1;

			if($length + $w > $width){
				break;
			}

			$result	.= $char;
			$length	+= $w;
		}

		return $result.$trimmarker;
	}
}

这就是我最近发现大家在设置 WordPress 文章摘要中碰到的问题。好累,一个摘要的问题写了那么长。😅

还有一点,文章摘如果设置得好,结合一些 SEO 插件,比如 WPJAM Basic 的「简单SEO」扩展,摘要也可以设置成 meta description,搜索引擎收录内容之后,在搜索结果页面显示的内容也是文章的摘要。

又做了一个 WordPress 工具,可以一键生成 WordPress 数据库表前缀修改 SQL

好吧,不说理由,你就是需要修改 WordPress 的数据库表的前缀,那么所有的 WordPress 数据表的前缀都需要修改,还有 opitonsuser_meta 表里面的一些字段也要进行修改。

手工改的话,会非常累,真的会非常累,所以我就写了一个工具,可以一键把用于修改的所有数据库表前缀的 SQL 全部生成出来:

如上图,你只需要输入旧的前缀,和新的前缀,然后点生成即可,然后把生成的 SQL copy 到 MySQL 运行一遍即可,非常方便。

特别注意一下就是,在 MySQL 中运行 SQL 修改前缀之前,一定要先备份好数据库。最后工具的地址是:

https://wpjam.com/tool/prefix-changer/

另外我在「果酱站长」的首页 WordPress 分组也加入了该工具:

https://wpjam.com

欢迎收藏,下次要进行数据库前缀需要修改的时候就方便了,如果有这方面需求的朋友也可以分享给他。

本站进一步完善了用户系统,欢迎使用 & 测试

本站近期对用户系统进行了全面优化,新增了多种注册和登录方式,包括手机号注册、微信扫码、QQ、微博以及邮箱登录等,为用户提供了更多便利。同时,Kevin 还改进了用户设置和主页的显示效果,使界面更直观、更美观。此外,充值系统和积分任务页面也得到了完善。经过一轮又一轮的折腾,我想暂时停下来了,再继续就偏离初衷显得过犹不及了。

写下这篇日志,主要是向大家通知一个可能会进行的调整:我计划测试“用户必须注册并登录才可以发表评论”。虽然这样的改动可能对访客体验产生一定影响,但它可以有效减少垃圾评论的出现,提高社区交流的质量。不管如何,我打算先试行一段时间,看看效果如何。你的意见是什么?欢迎留言告诉我!

欢迎初次登录的博友!建议您使用或绑定邮箱地址,以便及时接收评论回复的通知。同时,我会为新加入的博友手动赠送一定数量的积分,这些积分可以用于解锁部分限制内容和权限,带来更丰富的浏览体验。

[ 阅读全文 ]

原文链接: https://www.shephe.com/website/%e5%bc%ba%e5%88%b6%e7%99%bb%e5%bd%95/
版权声明: Kevin's Space 版权所有,转载请用明链标明本文地址
本站相关: 随机文章 | 站长微博 | 关于本站 | 联系站长 | 捐助作者

零基础 WordPress 网站建设全攻略:域名注册、环境搭建及内容创作(2024.11)

本零基础 WordPress 网站建设教程涉及内容非常广泛,将从一个小白的视角(老鸟&大神请点右上角)浅显地介绍有关建设网站的方方面面,包括但不限于:域名注册、服务器搭建、WP 建站、内容创作、网络营销等,总归一句话:WordPress 网站建设看完这篇就够了。

就像你一样,博主曾经也是一个对网站建设一无所知的小白,也是经过了无数的挫折和错误才积累了一些经验和见解。这篇文章的目的就是为了帮助你少走弯路,相对简单、直接而全面地学习如何建设一个 WordPress 网站。考虑到你可能是从零开始,文章里所使用的技术和语言尽可能地通俗易懂,倘若你对以下内容有任何疑问也欢迎在评论区留言,Kevin 将会第一时间为你解答。那么,让我们开始吧!

0. 为什么要建设网站?该如何开始

你为什么要建设一个网站呢?请认真思考这个问题,是为了向大家推广你的产品?是对外发布和展示信息?是想建设一个漂亮的页面展示作品?还是说见了别人有属于自己的网站,觉得很酷,想自己也想搞一个…这个问题你必须要明确。

笔者第一次做网站是在十一年前,那会儿我临近大学毕业,可能是看了某个帖子突然就发现做网站似乎也不那么难,于是对此一窍不通的我开始从零开始学习做网站了。得亏我那会儿年轻学习能力强,能熬夜,所以即便走了不少弯路,最终也还是能把小站做得像模像样,当时好像有人愿意出一点钱买那个小破站…???

..... [ 阅读全文 ]

原文链接: https://www.shephe.com/tutorial/wordpress-website-building/
版权声明: Kevin's Space 版权所有,转载请用明链标明本文地址
本站相关: 随机文章 | 站长微博 | 关于本站 | 联系站长 | 捐助作者

目前使用的 WordPress 插件

以下是我目前使用的WordPress插件,共 11 个:

  • UpdraftPlus,核心备份插件,免费版支持定期备份到 Google Drive。近期迁移了一次,安装好WordPress和该插件,再关联一下 Google 账号即可备份成功,体验很好。
  • Blocksy 主题 + 插件,目前在使用的主题,免费版够用,可自定义选项多,颜值高。
  • Polylang,多语言插件,免费版功能齐全,中英文界面可同时 SEO 索引,增强博客覆盖面。
  • Antispam Bee,屏蔽广告评论。
  • Post SMTP,邮件发送插件,更简单的配置 SMTP。
  • Wenprise Better Emails,提供邮件模板,美化邮件。
  • WP Super Cache,网站缓存插件,提升网站加载速度。
  • WPS Hide Login,安全插件,可以自定义WordPress登录页面URL。
  • Rank Math SEO,SEO 优化插件,增强搜索引擎可见度。
  • Meow Gallery,图片画廊插件。
  • Juicer,社交媒体聚合插件,能为国内用户展示 Twitter 时间线。

目前已有足够的舒适度,之后会偏重稳定性,于是关闭了插件和主题的自动更新。除了安全性更新,尽量不动。

除了 Blocksy,都用的免费版。但 Blocksy 其实也没用到几个付费功能,只是比较喜欢,且长期使用,支持一下。

在 Jack 的帮助下,最近管理面板换成了 1Panel,舒适度比 AMH 要高一些,操作也更简单。

截图留念!

CleanShot 2024-11-24 at 15.52.48@2x.png

多语言博客WordPress 插件 Polylang

我对多语言博客 WordPress 插件有以下几个需求:

  • 保持长期更新;
  • 免费或者不贵的买断制;
  • 中英文界面可同时 SEO 索引;
  • 操作简单易于多语言用户理解;
  • 中英文 RSS Feed 可以分开。

尝试多款插件之后,决定使用 Polylang,需求都能满足,且免费功能就够用。虽然内容需要自己翻译,但我也不是每篇都想翻译成英文,且借助 ChatGPT 并不费劲。

Pro 版(99欧元)可以和 DeepL 深度整合,并支持更多自定义功能。

基础设置跟着 Setup 流程即可。之后每翻译一篇,就会在英文界面展示一篇。

设置完成后的效果:https://anotherdayu.com/en/

向国内用户展示Twitter X和Instagram-WordPress插件

Twitter 在 WordPress 上的常规展示方式是 嵌入时间轴,缺点是仍基于 Twitter 数据库,所以国内用户无法查看。

近期我使用的是 juicer.io,这个网站可以将 Twitter、instagram、RSS 等时间轴聚合,展示在一个网页中。

而且支持 WordPress 插件,将嵌入时间轴。优点是经过 juicer.io 的转存后,国内用户也能访问该页面:https://anotherdayu.com/timeline/

小遗憾是数据没有储存在本地,所以无法进行 SEO 索引。胜在轻量级,不折腾,

CleanShot 2024-11-16 at 09.44.35@2x.png

流程如下:


另外,昨天和评论尸交流了一下,他开发的插件可以通过 RSS 为 WordPress 载入即刻的时间轴,并且有可能为 twitter 实现类似的效果。因为是通过 RSS 实现的,数据会保存在服务器中,并可以被 SEO 索引。

目前还在测试阶段,感兴趣的朋友可以关注他的 Twitter :@JeffreyCalm ,跟踪项目进展。

博客升级为 WordPress 6.7

WordPress 大版本 6.7 今天发布了,随之而来的是 2025 主题,我已经升级了,并且换上了最新的主题,正如你所看到的一样。

原来我是一直嫌弃块主题的,今天摸索了下,不知道是6.7的块主题变好了还是我会用了,总之就是真香。

全站编辑真的很方便。最明显的体会就是页脚悬挂备案编号。之前我是通过建立子主题,然后在子主题里修改footer.php文件来实现的,为了挂一个备案编号而专门建立一个子主题,有点高射炮打蚊子的感觉。现在好了,直接编辑网站,修改页脚文字就可以实现了,真的很方便!

前段时间以来,一直在反思自己,随着年龄的增长,会有一点守旧,其实应该更开放一点,多拥抱新事物,才不至于被时代落下。

虽然古腾堡和全站编辑在互联网上风评不好,很多人觉得不好用,但我觉得还好,拖拖点点就能实现一些想法。方便用户使用,总是好的,最起码方向应该是没有错。至于为什么有那么多人喷,我想大概是幸存者偏差,用的好的人不会专门发个帖子赞扬它,只有觉得不好用的人才会去发帖抱怨,所以造成了看到的都是抱怨贴。

现在 WordPress 全力 all in 古腾堡,我相信未来会变得越来越好用,越来越成熟。

WordPress6.7主题语言包失效(已解决)

刚更新到WordPress 6.7,发现自己主题的语言包失效了。我换了其他几个主题也是一样,我也没看到更新日志有关于语言包的更新啊。怎么回事?又出bug了?


根据秋风于渭水obaby在评论区的反馈,我也测试了其他主题,发现确实是部分主题的问题。正好WPTEA也发现这样的问题,我以为也会帮到我,可没找到相关解决办法。

后来我发现,将load_theme_textdomain函数放在after_setup_theme外就能正常显示翻译,但是会提示“_load_textdomain_just_in_time 的调用方式不正确。 域的翻译加载触发得太早。翻译应该在 init 操作或之后加载.....”,所以这样做也不能解决问题,官方要求必须在init或after_setup_theme内。

wechat_2024 11 13_193628_611.png
load_theme_textdomain函数

经过三四个小时不断的测试,最终给我找到问题所在。所以这是主题的问题,而不是程序的问题。block-patterns.php和block-styles.php这是我借鉴WordPress默认的主题,因为提交官方主题库必须要有register_block_style和register_block_pattern的存在,即使对我来说一无是处。

RECOMMENDED: No reference to register_block_style was found in the theme. Theme authors are encouraged to implement new block styles as a transition to block themes.
RECOMMENDED: No reference to register_block_pattern was found in the theme. Theme authors are encouraged to implement custom block patterns as a transition to block themes.

然后我发现这两个位置,少了个符号“!”,因为按照逻辑来说,应该是如果没有什么什么,便注册什么什么。所以加上感叹号,问题就解决了。神奇吧!之前都没有验证过这个问题,却能正常显示。

wechat_2024 11 13_205842_910.png

虽然上面没有错误提示,但经过ZWW大佬一观,就发现问题所在了。其实我也想过,我抄的WordPress的主题代码,他们不至于犯这种错误啊。看到block-styles.php文件里,将这些函数放进init钩子,于是我照葫芦画个瓢,搞定。

wechat_2024 11 13_232023_348.png
版权声明: 本文采用 BY-NC-SA 协议进行授权,如无注明均为原创,转载请注明转自 皇家元林
本文链接: WordPress6.7主题语言包失效(已解决)

又到续费时

话说我使用搬瓦工是从2017年开始,中间也买过其他家的机器,灰常记忆一直从未挪窝稳稳的运行,虽然慢却可以打开…… 今天看了下这台vps,硬盘空间又不足10GB了,感觉也没搞什么东西在上面😂,现在看来vps最低配置2H3G-50GB+空间才适合我。 今天把Nginx换到了Nginx openresty,其实也没感觉出来有多快,有些东西不兼容又换回nginx。有好的东西就想尝试下,又不是太折腾。 又到了一年VPS续费的时节,目前手里一台香港、一台美国瓦工、两台美国大硬盘机器。 买了两台大盘鸡,用来做备份。现在使用wp后台总是会报错,挺无解的尽管玩了这么多年wordpress还是找不出问题所在,只能 […]

WP-UserAgent [纯真增强版] 15.01.01

之前为了下载纯真的ip 地址数据库订阅了他们的公众号,前几天的时候看到推送说什么数据库格式更新了,有了 czdb 的格式,并且提供了各种语言的 sdk。

不过这个东西应该不是最近才推的,因为印象里貌似很久之前就看到皇家园林写的数据库迁移的文章。官方给的sdk 地址是这个:https://github.com/tagphi/czdb_searcher_php

按照文档操作,感觉也不复杂,直接:

composer require czdb/searcher

composer导入,就一行命令的事,但是为了弄个插件,需要在服务器上装这么个东西?那插件安装到别的地方也麻烦啊。想着一次性解决这个问题,直接下载源码,修改导入方式,按照网上的教程一通改,并不好使,最后 还是请教杜郎,才解决了这个问题:

composer

真不错,直接小花花+1.

下载 copmoser 导出的包,直接扔到插件目录下,

因为最终要修改的是 ip2text.php 文件中的convertip函数,所以直接扔到 show-useragent 目录下,在代码中导入代码,并且初始化:

require_once __DIR__ . '/vendor/autoload.php';

use Czdb\DbSearcher;

$v4databasePath = dirname(__FILE__).'/czdb/db/cz88_public_v4.czdb';
$v6databasePath = dirname(__FILE__).'/czdb/db/cz88_public_v6.czdb';

$queryType = 'MEMORY';
$key = 'n2pf2******************==';

// Initialize the DbSearcher with the command line arguments
// $instance = new SomeNamespace\SomeClass();

$v4dbSearcher = new DbSearcher($v4databasePath, $queryType, $key);
$v6dbSearcher = new DbSearcher($v6databasePath, $queryType, $key);

// $dbSearcher = new DbSearcher($databasePath, $queryType, $key);

function convertip($ip) {
    global $v4dbSearcher;
    global $v6dbSearcher;
    try{
        if(strpos($ip, ':') != false){
            $region = $v6dbSearcher->search($ip);
        }else if (strpos($ip, '.')!= false)
        {
            $region = $v4dbSearcher->search($ip);
        }else{
            $region='Unknown';
        }
    }catch (Exception $e) {
        // Handle the exception and inform the user
        $region = 'Exception';
    }
   
    return $region;
}

这里初始化了两个DbSearcher,分别对应 v4 和v6的查询。查询代码也很简单,就上面这几行。

同样,既然有了国家代码,那剩下的就是去掉原来通过接口查询所属国家的问题了,之前用接口是因为qqwry.dat 旧版本没有 v6 的数据,后来也一直没更新,所以归属地现实国旗是通过接口实现的,现在既然 46 都有了,那就可以直接本地解析了,不过比较坑爹的是 v4 的地址是“-”拼接的,v6 的地址感觉是空格,实际上是个制表符’\t’,为了这个制表符废了半天的劲,一直解析不出来,直接头大:

function getCountryName($str) {
    $parts = explode('–', $str);
    $name = count($parts) > 0 ? $parts[0] : '';
    // print($name);
    if (strpos($name, " ")!==false){
        $parts = explode(" ", $str);
        $name = count($parts) > 0 ? $parts[0] : '';
        // print($name);
    }
    if (strpos($name, "\t")!==false){
        $parts = explode("\t", $str);
        $name = count($parts) > 0 ? $parts[0] : '';
        // print($name);
    }
    return $name;
}

之所以解析不出来是最开始的if (strpos($name, “\t”)!==false)用的单引号,后来才发现,单引号下转义字符无效,这尼玛是凭什么啊,果然 php 是最好的语言。

后面就是讲国家名转换为 2 位国家代码了:

function getCountryCode($countryName) {
    $countryMap = array(
        '中国' => 'CN',
        '美国' => 'US',
        '日本' => 'JP',
        '韩国' => 'KR',
        '俄罗斯' => 'RU',
        '法国' => 'FR',
        '德国' => 'DE',
        '英国' => 'GB',
        '意大利' => 'IT',
        '加拿大' => 'CA',
        // 省略部分国家地区
        '瓦利斯和富图纳' => 'WF',
        '也门' => 'YE',
        '赞比亚' => 'ZM',
        '津巴布韦' => 'ZW',
        );
    $countryName = removeWhitespace($countryName);
    $countryCode = 'unknown';
    if (isset($countryMap[$countryName])) {
        $countryCode = $countryMap[$countryName];
    }
    // ; return $countryCode;
    return strtolower($countryCode);
}

到这里改造基本就全部完成了。

更新日志:

= v15.01.01 =
* 替换本地IP归属地查询数据库为纯真CZDB格式
* 替换IPv6归属地查询,替换为本地数据库,去掉查询服务器配置功能
* 鉴于纯真数据库需要授权码,需要去 https://cz88.com/geo-public 获取授权密钥以及数据库文件
* 密钥配置文件,ip2c-text.php $key = 'n2pf2******************pg==';
* 数据库下载之后放入show-useragent\czdb\db 目录下,文件名分别为: cz88_public_v4.czdb cz88_public_v6.czdb

插件安装无法直接使用,请按照下面的步骤操作:

* 需要去 https://cz88.com/geo-public 获取授权密钥以及数据库文件

* 密钥配置文件,ip2c-text.php $key = ‘n2pf2******************pg==’;

* 数据库下载之后放入show-useragent\czdb\db 目录下,文件名分别为: cz88_public_v4.czdb cz88_public_v6.czdb

实际效果:

插件下载地址:

温馨提示: 此处隐藏内容需要发表评论,并且审核通过后才能查看。
(发表评论请勾选 在此浏览器中保存我的显示名称、邮箱地址和网站地址,以便下次评论时使用。
(请仔细检查自己的昵称和评论内容,以免被识别为垃圾评论而导致无法正常审核。)

WordPress RSS 排除特定分类 & 推送旧文更新

最近 Kevin's Space 被我折腾的挺凶,已经逐步从轻量级个人博客慢慢变化成综合性网站了。当然啦,网站内容方向和之前的并没有变化,只是数量上可能更多更细了,且难免会有一些转载的或者大多数博友不那么感兴趣的内容。因此我需要在 RSS 中进行一定程度的屏蔽,可能会是整个目录,亦有可能是某些特定文章。

同时呢,还有一些我认为有价值的文章我会反复更新,我可能也会去再次推送 RSS 给订阅者。以下是我对这些操作的简单记录,您各位老鸟做个参考。

1. 在 WordPress RSS 中排除特定分类文章

因为考虑到 Kevin's 有不少 RSS 订阅者,但同时呢我这又要更新不少订阅用户不喜欢看的内容,所以要在 WordPress 的 RSS 中隐藏特定分类的发布。如此便需要对 functions.php 文件进行一些修改以筛选 RSS 的输出内容。这是一个基本的步骤描述:

  1. 打开您的 WordPress 主题文件夹,找到并编辑 functions.php 文件。
  2. 选择一个对应的隐藏分类的 id。
  3. 在 functions.php 文件中,加入以下的 PHP 代码:
function myFilter($query) {
    if ($query->is_feed) {
        $query->set('cat','-5'); // 这里的 -5 应当替换为您想隐藏的分类 I..... [ 阅读全文 ]

原文链接: https://www.shephe.com/website/wordpress-rss-enhance/
版权声明: Kevin's Space 版权所有,转载请用明链标明本文地址
本站相关: 随机文章 | 站长微博 | 关于本站 | 联系站长 | 捐助作者

宝塔面板-V免签支付系统搭建教程:个人开发者收款解决方案(含2开源码)

V免签支付系统介绍

V免签(PHP) 是基于 Thinkphp5.1 + mysql 实现的一套免签支付程序,主要包含以下特色:

  1. 收款即时到账,无需进入第三方账户,收款更安全
  2. 提供示例代码简单接入
  3. 超简单 Api 使用,提供统一 Api 实现收款回调
  4. 免费、开源,无后门风险
  5. 支持监听店员收款信息,可使用支付宝微信小号/模拟器挂机,方便 iOS 用户
  6. 免 root,免 xp 框架,不修改支付宝/微信客户端,防封更安全

V免签官方源码:https://github.com/szvone/vmqphp

V免签安卓监控端:https://github.com/szvone/VmqApk

演示环境基于 宝塔面板 搭建,使用 nginx1.18、php7.4、mysql5.6 已实测该环境正常搭建可用

  • V免签的运行环境为PHP版本 >=5.6。

宝塔面板-V免签支付系统搭建教程
宝塔面板-V免签支付系统搭建教程

宝塔面板部署V免签支付系统教程

  1. 下载V免签压缩包,上传至服务器并解压

  2. 关闭防跨站攻击,设置运行目录为 public 并保存

宝塔面板-网站目录-运行目录
宝塔面板-网站目录-运行目录

  1. 设置伪静态为thinkphp并保存

宝塔面板-伪静态设置
宝塔面板-伪静态设置

  1. 设置默认文档,将index.html放在第一行并保存(这里改完顺序,点击添加就是保存)

宝塔面板-默认文档设置
宝塔面板-默认文档设置

  1. 打开网站路径/config/database.php ,设置好你的 mysql 账号密码并保存

V免签支付系统数据库设置
V免签支付系统数据库设置

  1. 导入数据库文件 vmq.sql 到服务器里

数据库导入V免签数据文件
数据库导入V免签数据文件

  1. 至此网站搭建完毕,请访问后自行修改配置信息!默认后台账号和密码均为 admin

V免签支付系统演示图

前台演示图

V免签支付系统前台演示图
V免签支付系统前台演示图

后台演示图

V免签支付系统后台演示
V免签支付系统后台演示

V免签支付系统后台演示-系统设置
V免签支付系统后台演示-系统设置

V免签支付系统后台演示-监控端设置
V免签支付系统后台演示-监控端设置

V免签监控端设置

V 免签监控端:该软件是基于 V 免签开发一款免 root 和框架 Android 收款监听软件,功能为监听支付宝和微信收款消息与服务端进行交互,若匹配当前时间段服务端有同金额订单将会把收到的金额消息进行回调!达到监听通知栏收款消息回调完成支付业务。该版本主要修复了原版监控的支付宝和微信不回调的 BUG,优化代码写法。删除沉余代码加快启动速度,增加电池白名单权限,使软件在电池优化时不会被杀掉!增加 Log 监听回调面板与店员监听。V免签现已更新 PC 端监控。

下载地址

付费图片
付费图片
限时优惠
宝塔面板-V免签支付系统搭建教程:个人开发者收款解决方案(含2开源码)
为尊重作者劳动成果,此处内容已隐藏,请购买查看内容
10
限时特惠
输入邮箱即可查询订单,跳转支付则为未查询到订单(邮箱只用于订单使用,不会发送内容到邮箱,虚拟产品售出不退!!!)
已有0人解锁查看
输入邮箱即可查询订单,跳转支付则为未查询到订单(邮箱只用于订单使用,不会发送内容到邮箱,虚拟产品售出不退!!!)
付费阅读
已售 0
隐藏内容

V免签Android监控端设置

使用Android手机安装APK,点击扫码配置 - 扫描V免签监控端设置的二维码即可配置完成

V免签二开源码

运行环境 Nginx1.1.5 以上 PHP5.6-7.3 Mysql5.6以上

  1. 网站目录->运行目录 设置为public并保存
  2. 伪静态 设置为thinkphp并保存
  3. 打开网站目录 config/database.php ,设置好您的mysql账号密码
  4. 导入数据库文件(位于根目录)pay.sql到您的数据库
  5. 至此网站搭建完毕,请访问/houtai后自行修改配置信息!默认后台账号admin和密码123456
  6. 后台登录入口在route/route.php,找到’houtai’修改即可
  7. 在后台里设置首页跳转地址,不设置跳转到默认地址
  8. 配置邮箱信息和支付宝商户号
  9. 使用免挂或者软件监控,使用免挂需要配置回调监控
  10. 建议把当前站点的网站防火墙关了,以防被拦截

下载地址:包含源码与监控挂机软件

付费图片
付费图片
限时优惠
宝塔面板-V免签支付系统搭建教程:个人开发者收款解决方案(含2开源码)
为尊重作者劳动成果,此处内容已隐藏,请购买查看内容
10
限时特惠
输入邮箱即可查询订单,跳转支付则为未查询到订单(邮箱只用于订单使用,不会发送内容到邮箱,虚拟产品售出不退!!!)
已有0人解锁查看
输入邮箱即可查询订单,跳转支付则为未查询到订单(邮箱只用于订单使用,不会发送内容到邮箱,虚拟产品售出不退!!!)
付费阅读
已售 0
隐藏内容

V免签WordPress插件

V免签WordPress插件

  • ✅关闭订单(2024年11月4日)

  • ✅收款返回文章页面,并显示隐藏内容(2023年11月4日)

  • ✅界面上面的文字可以自定义(2023年11月4日)

  • ✅金额可以在文章中自定义设置,如果不设置则显示默认金额(2023年11月7日)

  • ✅订单显示在后台(2023年11月7日)

  • ✅支付金额可以自动填入(2023年11月9日)@格子老师

  • ✅3款主题切换

V免签代部署服务

有源码不会装?懒癌发作,手不听使唤?瞌睡上头思想无法集中?昨晚酒还没醒?

如果您有以上疑难杂症,点这里就对了,发挥你的钞能力,一键解君愁!

服务内容:

  • 您无需准备以上所需源码,提出要求就好!
  • 带安装对接以上支付接口!
  • 您只需提供服务器信息、域名信息、收款二维码即可!

v免签 代安装搭建服务

WordPress 添加友情链接页面 & 样式参考

Kevin's 的“友情链接”模块 / 页面已经丢失几年了,主要是因为现下的友链既无法联络感情又无法释放 SEO 的功能性,且有更高效的方案去实现博友互访。所以,既然 WordPress 官方都把这个模块砍了,我也就一直没弄。

在此,我非常郑重地感谢那些在此前一直保留我链接的博主们,谢谢!正好最近在折腾博客,完善功能,我就又把这个功能折腾起来并完善了页面,您各位瞧瞧:友情链接页面。其中我已尽量将自己记得的博客添加进来,但难免有疏漏忘记的,还请海涵!看到的话请在留言板提示一下。此外还有一些我常去的页面也罗列在此,排名均不分先后。另外如果你觉得本站还算有趣,也可以与我交换链接。

制作该友链页面的步骤大概分为三步,首先是把 WordPress 隐藏的友链恢复,然后是把友链信息从数据库中抓取并输出,最后是对输出的信息做一个个性化的展示。因为本人并不擅长(可以说是不会)搞代码,所以这里边大量借用了 AI 的技术,嘿嘿。

WordPress 添加友情链接页面 & 样式参考[ 阅读全文 ]

原文链接: https://www.shephe.com/website/wordpress-flink-page/
版权声明: Kevin's Space 版权所有,转载请用明链标明本文地址
本站相关: 随机文章 | 站长微博 | 关于本站 | 联系站长 | 捐助作者

WordPress 博客年度更新:全新首页上线,用户中心与问答社区优化升级

自从 2022 年 8 月开始,我便用上了 WordPress 的 Impeka 主题。虽然期间文章和页面不断更新,但这两年一直沿用一款简单的首页设计,看着看着也就“审美疲劳”了。最近,在大家提出的宝贵意见启发下,我一边灵感迸发,一边疯狂折腾,终于为博客换上了全新主页!不仅焕然一新,还新增了不少实用功能,并对细节进行了优化完善。希望新页面能让大家耳目一新,浏览更愉快!

1. 利用强大的 Impeka 主题制作了全新首页

Impeka 是一款现代化、灵活且功能强大的多用途 WordPress 主题,我在WordPress Impeka 2.0.6 创意多功能主题完整下载一文中有详细介绍。因为博主并不是科班出身,也不想费尽心思去搞代码,所以利用了主题的页面构建器搭建了如今的首页,以前的首页挪作它用,成了“最新发布”。

其实,我最初的首页设计内容是丰富得多的,但后来考虑到页面加载速度,以及小站目前的内容量确实不足以支撑复杂的首页布局,所以就稍微精简了一下。不过即便如此,可能仍有朋友会觉得有些部分“不够实用”或“稍显多余”。没关系,慢慢来吧!我会继续丰富内容,争取让每一部分都更有意义,也希望大家能见证它一步步完善的过程!

[ 阅读全文 ]

原文链接: https://www.shephe.com/website/wordpress-blog-enhance-2024/
版权声明: Kevin's Space 版权所有,转载请用明链标明本文地址
本站相关: 随机文章 | 站长微博 | 关于本站 | 联系站长 | 捐助作者

WordPress Impeka 2.0.6 创意多功能主题中文下载

Impeka 是一款现代化、灵活且功能强大的多用途 WordPress 主题,由 Greatives 开发,专为创意人士、企业和机构设计。它以卓越的性能和设计自由度著称,适合任何类型的网站,如作品展示、博客、企业官网、电商平台等。当前 Kevin's Space 使用的就是最新版本的 Impeka,这是我当年从 Themeforest 花 59 刀购买的,这主题从 1.0 一直更新到了如今的 2.0.6 版本,功能已经足够强大和完善,各种小细节和 Bug 也已经修复得差不多了。目前本人使用了它可能 1/3 的功能和特性,已经把 Kevin's Space 折腾得很花哨了,总体来讲我是对它非常满意的。

本文分享的 Impeka 主题共两个版本,其一是我从 Themeforest 后台下载但没有授权的官方正版,拥有完整的文档和各种资料,您各位也能安装使用不过功能上会有些许限制。另一个是 NULL 版(你可以粗略地将其理解为破解版),它允许你使用 Impeka 的全部功能、扩展插件,并且能从官方后台导入模板数据和资料文件。

WordPress Impeka 2.0.6 创意多功能主题完整下载WordPress Impeka 2.0.6 创意多功能主题完整下载[ 阅读全文 ]

原文链接: https://www.shephe.com/website/wordpress-impeka-creative-theme-download/
版权声明: Kevin's Space 版权所有,转载请用明链标明本文地址
本站相关: 随机文章 | 站长微博 | 关于本站 | 联系站长 | 捐助作者

WordPress6.7 初体验

看到 WordPress6.7 将于11月12日发布,闲着没事下载了 Beta2 版本在本地体验了一下。总的来说,没有感觉到什么明显的变化。

新版本自带了一个 Twenty Twenty-Five 新主题,不用说还是 Block Theme,不知道为什么,我对块主题无感,尝试过多次,怎么都喜欢不起来。尤其是全站编辑,操作一会就会有点头晕目眩,有点类似晕3D的感觉……最主要的是,它的风格我并不喜欢。

随着 WordPress 的迭代开发,新主题越来越花哨,尤其是古腾堡的加入,让 WordPress 迈入了全站编辑时代,但是,这真的是我们所需要的吗?对于我来说,只要能安心记录那就足够了。

博客作者呀,我想采访你这 9 个问题!

「为自己而写作」是绝大多数作者的自我形象定义。这个行业,有它自己的传统。
—— 李兆欣

这个采访目录参考了 Manu雅余。Manu 会定期邀请有趣的人聊聊自己的博客,至今已有 59 篇。我稍微调整了他的目录,问一些感兴趣的问题。雅余则设计了一个独立博客问卷,已有很多朋友参加。

平日读博客时,最喜欢看的是各位写的杂文随笔,那些生活中的细碎小事,也很好奇文章背后的各位,是如何看待自己与博客的联系。所以和朋友一起设计了这 9 个博客作者和读者共同感兴趣的问题。

写完的朋友,可以回评论区留个言,期待看到一个很多链接的评论区。

如果有更多想与我分享的,也可以参加「交个朋友」活动。


1. 简单介绍下自己或者你的博客?

2. 什么契机让你开始写博客?

3. 你是如何完成创作的?

4. 运营博客的过程中是否有失去过动力?如果有,是为什么恢复的?如果没有,请问您又是如何保持创作的激情?

5. 如何搭建博客,以及运营博客每年需要投入的资金?

6. 推荐 1 篇你博客中的文章,并推荐一个你喜欢读的博客,聊聊原因。

7. 推荐 1 个近期喜欢的事物?

(例如书籍、电影、音乐、工具、软件。)

8. 想做还没有做的事,或想尝试还没有尝试的主题?

9. 写到这里,闭上你的眼睛,深呼吸几分钟,或是出去溜达一圈,然后回来写任何你想写的东西。


写一篇博客,就是跟未来的自己约会。

希望大家享受这个问卷。

Peer review:JackYorks0n

.

.

拖了两周,终于坐下来答自己设计的问卷。

Puock主题修改备忘录

作为一个写博十余年的老博主,实在是没有精力折腾各种新东西。但近期博客程序被入侵事件让我不得不换掉了使用很久的Flat主题。

本来想在后台随便找个官方推荐的主题凑合用,但那些主题基本上都是歪果人设计的,对中文排版支持不太友好,所以又重新找了款国人开发的主题,也就是本站正在用的——Puock主题

这款主题美观大方,功能强大,一次性解决了我很多痛点。可以说是立即部署、立即使用。

但使用了几天后,还是发现有需要调整的地方。现在记录一下,免得后面忘记了。

一、评论者URL跳转问题

主题模板设计的功能是:评论者如果留了URL的,则进行base64加密,然后通过一个中转页面进行二次确认,再进行跳转。

我对这个功能的态度是:完全不需要。

博友互访留下URL,并且清晰地展示在前台,我认为是非常重要的,加密再跳转极其影响用户体验。对于那些发广告的评论,我是一律删除就完事了,所以并没有这个需求。关键是,经过测试,部分URL加密后无法正常跳转,而是会跳到我博客首页,这完全让人摸不着头脑。

由于本人对代码几乎一窍不通,看了半天也没找到哪里能关掉这个功能。

开始把go.php里的代码丢给“文心一言”去分析,并根据AI指引修改里面的代码,试图取消加密,直接调转,但无果。

之后采取笨方法,直接用全文搜索,搜出了包含“go.php”这个关键词的页面opt.php,路径位于:

主题模板文件夹下的 /inc/fun/opt.php

相关代码为:

//跳转链接

function pk_go_link($url, $name = &#8221;)

{if (pk_is_cur_site($url)) {

return $url;

}$url = PUOCK_ABS_URI . &#8216;/inc/go.php?to=&#8217; . base64_encode($url);

if (!empty($name)) {

$url .= &#8216;&amp;name=&#8217; . base64_encode($name);

}return $url;

}

这段代码丢给AI,让他改为不加密,但AI弄了半天,不成功。

我看了下代码,还是采用最笨的方法,将$url =后面的内容改为了$url,也就是左右相等,替换后如下:

//跳转链接

function pk_go_link($url, $name = &#8221;)

{if (pk_is_cur_site($url)) {

return $url;

}$url = $url;

if (!empty($name)) {

$url .= &#8216;&amp;name=&#8217; . base64_encode($name);

}return $url;

}

再次刷新运行,完美解决。

二、屏蔽键盘左右键翻页功能

这个问题是博友S发现的。

在单篇文章页面,使用键盘左右键可以实现上一篇、下一篇的快速切换。

看起来很美好,但这里有个“致命”BUG,当浏览者在评论框里输入文字时,不小心使用了键盘左右键来调整内容,此时页面会马上切换到上一篇或下一篇,直接导致整个评论表单输入的内容全部丢失。

当我打算去官方开发者博客留言反馈这个问题时,结果光是写那条留言就反复写了五六次——官方竟然复刻了这个问题,也就是说跟我博客运行环境是没有关系的。

在等待官方修复这个BUG之前,我尝试自救。

跟文心一言沟通多次,并没有给出有效的解决办法。

无奈之下,找到了chatgpt,让他给我写一个屏蔽键盘左右键的插件,修改一次后,解决问题。

现在,我的博客将暂时屏蔽键盘左右键,按下时会弹出对话框,虽然也有一定影响,但总比吞掉辛辛苦苦敲下的文字强吧。

10.18更新:

在GitHub提交issue后,网友hausen1012回复说遇到同样问题,并给出了相关的代码。

经测试,删除主题模板下/assets/dist/js路径中puock.min.js文件以下代码即可取消左右键翻页功能:


{
key: "keyUpHandle",
value: function() {
var a = $(".single-next-or-pre");
a && (window.onkeyup = function(t) {
var e = null;
switch (t.key) {
case "ArrowLeft":
e = a.find("a[rel='prev']").attr("href");
break;
case "ArrowRight":
e = a.find("a[rel='next']").attr("href")
}
e && (window.location = e)
}
)
}
}

10.22更新:

感谢博友老何提醒,由于直接删除上述代码,会导致评论回复功能不可用(我猜是keyUpHandle这个功能还关联了其他事件)

忍不住又折腾了一下,经过chatgpt的分析,把上述代码修改为下面的代码:


{
key: "keyUpHandle",
value: function() {
var a = $(".single-next-or-pre");
var commentBox = $("#comment"); // 获取评论框

// 定义事件处理函数
var handleKeyUp = function(t) {
var e = null;
switch (t.key) {
case “ArrowLeft”:
e = a.find(“a[rel=’prev’]”).attr(“href”);
break;
case “ArrowRight”:
e = a.find(“a[rel=’next’]”).attr(“href”);
}
e && (window.location = e);
};

// 绑定事件
if (a.length) {
window.addEventListener(“keyup”, handleKeyUp);
}

// 解绑事件的函数
this.unbindKeyUp = function() {
window.removeEventListener(“keyup”, handleKeyUp);
};

// 监测评论框的焦点事件
commentBox.on(“focus”, () => {
this.unbindKeyUp(); // 当焦点在评论框上时,解绑键盘事件
});

// 可选:在评论框失去焦点时重新绑定事件
commentBox.on(“blur”, () => {
if (a.length) {
window.addEventListener(“keyup”, handleKeyUp); // 重新绑定事件
}
});
}
}

希望不会再衍生出新的BUG。

WordPress CORS问题一例

  本文记录阿猪在使用WordPress REST API为跨站应用做身份认证时遇到的一例CORS问题。经过一番折腾,最后发现问题出在使用的REST API Authentication插件在处理HTTP请求时与WordPress原生的REST API有重复。

ChatGPT-on-WeChat、WordPress、微信公众号:实现具有AI搜索功能的博客公众号

阿斌之前使用 WordPress 插件:微信机器人高级版 将 Wordpress 与微信公众号 进行了打通,但后来作者将插件隐藏,只能加入社区的才能免费下载,所以阿斌一直使用的是旧版本。

后来我发现微信将我的网站列为不安全网站了,申诉还比较麻烦,阿斌在想怎样直接将链接返回给用户,用户直接复制链接到浏览器打开即可。

我就找到了 chatgpt-on-wechat 这个可以对接微信公众号AI聊天机器人,只要设置好就能通过AI来回答用户发来的问题,还可以自己开发插件,自由度很高。

ChatGPT-on-WeChat、WordPress、微信公众号:实现具有AI搜索功能的博客公众号
ChatGPT-on-WeChat、WordPress、微信公众号:实现具有AI搜索功能的博客公众号

zhayujie/chatgpt-on-wechat :基于大模型搭建的聊天机器人,同时支持 微信公众号、企业微信应用、飞书、钉钉 等接入,可选择 GPT3.5/GPT-4o/GPT4.0/Claude/文心一言/讯飞星火/通义千问/Gemini/GLM-4/Claude/Kimi/LinkAI,能处理文本、语音和图片,访问操作系统和互联网,支持基于自有知识库进行定制企业智能客服。

如何在 CentOS上 安装 Python3.8

按行运行,一行是一条命令

# 查看系统包含的python环境
ps -aux|grep python
# 下载Python3.8.20的包
wget https://www.python.org/ftp/python/3.8.20/Python-3.8.20.tgz
# 解压压缩包
tar -zxvf Python-3.8.20.tgz
# 进入文件夹
cd Python-3.8.20/
# 配置python3
./configure --prefix=/usr/local/python3
# 编译
make && make install
# 将原有的python软链接重命名
mv /usr/bin/python3 /usr/bin/python368
mv /usr/bin/pip3 /usr/bin/pip368
# 对新的python3.8创建软链接
ln -s /usr/local/python3/bin/python3 /usr/bin/python3
ln -s /usr/local/python3/bin/pip3 /usr/bin/pip3
# 查看当前python3的版本号
python3 --version

搭建 ChatGPT-on-WeChat

# 克隆仓库
git clone https://github.com/zhayujie/chatgpt-on-wechat
# 进入文件夹
cd chatgpt-on-wechat/
# 安装核心依赖 
pip3 install -r requirements.txt
# 安装扩展依赖
pip3 install -r requirements-optional.txt
# 复制该模板创建最终生效的 config.json 文件,要先设置好配置信息再启动
cp config-template.json config.json
# 报错:ImportError: urllib3 v2 only supports OpenSSL 1.1.1+, currently the 'ssl' module is compiled with 'OpenSSL 1.0.2k-fips  26 Jan 2017'再执行下面命令
pip3 install urllib3==1.22
# 在后台运行程序并通过日志输出二维码
nohup python3 app.py & tail -f nohup.out

我的 config.json 文件内容,记得将 服务器 IP 加入 IP 白名单,否则会调用不通(配置说明

{
  "channel_type": "wechatmp",
  "single_chat_prefix": [""], 
  "wechatmp_app_id": "开发者ID(AppID)",
  "wechatmp_app_secret": "开发者密码(AppSecret)",
  "wechatmp_aes_key": "消息加解密密钥(EncodingAESKey)",
  "wechatmp_token": "令牌(Token)",
  "wechatmp_port": 999,
  "model": "gpt-3.5-turbo",
  "open_ai_api_base": "OpenAI地址",
  "open_ai_api_key": "OpenAI密码",
  "text_to_image": "dall-e-2",
  "voice_to_text": "openai",
  "text_to_voice": "openai",
  "proxy": "",
  "hot_reload": false,
  "single_chat_prefix": [
    ""
  ],
  "single_chat_reply_prefix": "[bot] ",
  "group_chat_prefix": [
    "@星辰"
  ],
  "group_name_white_list": [
    "文章接收助手"
  ],
  "group_chat_in_one_session": [
    "文章接收助手"
  ],
  "image_create_prefix": [
    "画"
  ],
  "speech_recognition": true,
  "group_speech_recognition": false,
  "voice_reply_voice": false,
  "conversation_max_tokens": 2500,
  "expires_in_seconds": 3600,
  "character_desc": "你是ChatGPT, 一个由OpenAI训练的大型语言模型, 你旨在回答并解决人们的任何问题,并且可以使用多种语言与人交流。",
  "temperature": 0.7,
  "top_p": 1,
  "subscribe_msg": "欢迎来到斌仔的公众号~\n\n2024年,愿你所求皆如愿🎉!\n\n记住我的资源小站,我把好用的都放在了那里:https://www.wangdu.site(复制链接在浏览器打开)\n\n1. <a href='weixin://bizmsgmenu?msgmenuid=0&msgmenucontent=目录导航'>点我:查看📕目录导航📕</a>\n2. <a href='weixin://bizmsgmenu?msgmenuid=0&msgmenucontent=专属福利'>点我:获取🎁专属福利🎁</a>\n3. <a href='weixin://bizmsgmenu?msgmenuid=0&msgmenucontent=黑苹果'>点我:获取🍎黑苹果🍎教程</a>\n4. <a href='weixin://bizmsgmenu?msgmenuid=0&msgmenucontent=影视'>点我:免费📽️看电影📽️</a\n5. <a href='weixin://bizmsgmenu?msgmenuid=0&msgmenucontent=youtube'>点我:🌍看YouTube🌍,了解世界</a>\n6. <a href='weixin://bizmsgmenu?msgmenuid=0&msgmenucontent=音乐'>点我:解锁全部🎵音乐🎵,不再怕灰色</a>\n7. <a href='weixin://bizmsgmenu?msgmenuid=0&msgmenucontent=AI'>点我:获取🤖AI(人工智能)工具🤖,大大提升工作效率</a>\n8. <a href='weixin://bizmsgmenu?msgmenuid=0&msgmenucontent=IPTV直播源'>点我:获取📺IPTV直播源📺,免费TV看电影视频</a>\n\n获取博客文章验证码:<a href='weixin://bizmsgmenu?msgmenuid=0&msgmenucontent=验证码'>点我:获取验证码</a>!\n\n查询博客内容:[搜 关键词],如:搜 黑苹果\n\n默认使用AI回答",
  "use_linkai": false,
  "linkai_api_key": "",
  "linkai_app_code": ""
}

ChatGPT-on-WeChat 公众号设置教程

根据上面设置好后启动项目,没啥报错后,我们要将项目的端口映射到域名,这样在微信公众号后台调用更加方便。

宝塔反向代理

  1. 宝塔面板 - 网站 - 添加站点,域名:你需要解析的域名,PHP版本:纯静态,确定

    宝塔面板添加站点
    宝塔面板添加站点

  2. 点击域名后的设置 - 反向代理 - 添加反向代理,代理名称:chatgpt,目标URL:http://服务器IP:999,确定

    宝塔面板添加反向代理
    宝塔面板添加反向代理

  3. 登录域名控制台,我这里是 阿里域名控制台,解析 - 添加记录 - 主机记录:上面解析域名的前缀,记录值:服务器IP,确认

    阿里域名控制台添加解析记录
    阿里域名控制台添加解析记录

  4. 服务器开放端口:在阿里云服务器控制台 - 安全组 - 服务器 - 管理规则 - 手动添加 - 目的:999/999,源:选择所有IPv4(0.0.0.0/0),保存(入方向、出方向都要添加)

    服务器开放端口
    服务器开放端口

  5. 此时访问你之前解析的域名:http://解析的域名/wx,出现:'signature',表示已经搭建成功了,为了安全起见,下面再给域名加个SSL证书就完美了。

  6. 宝塔面板申请SSL证书:宝塔面板 - 网站 - 点击域名后的设置 - SSL - Let's Encrypt - 申请证书,等待一会即可申请成功。(如果不成功,可查看阿里云申请证书教程来申请免费证书,有效期90天,申请下来后,下载解压证书,将PEM、KEY内容填到对应当前内容里保存即可。)

    宝塔面板申请SSL证书
    宝塔面板申请SSL证书

  7. 打开强制HTTPS,使用HTTPS来访问解析的域名,即可看到前面变成了小锁🔒(页面此时502,不要慌,继续往下看)

    宝塔面板打开HTTPS
    宝塔面板打开HTTPS

  8. 宝塔放行端口:宝塔面板 - 安全 - 添加端口规则 - 端口:14300,方向:入站/出站(2个都要添加) - 确定

    宝塔放行端口
    宝塔放行端口

  9. 此时使用HTTPS域名访问:https://解析的域名/wx,出现:'signature',表示已经搭建成功了。

微信公众号设置

微信公众号 - 基本设置 - 服务器配置,配置如下,设置好,提交成功表示配置成功。

  • 服务器地址:https://解析的域名/wx
  • 令牌:config.json 里的 wechatmp_token(两者保持一致)
  • 消息加解密密钥:config.json 里的 wechatmp_aes_key(两者保持一致)

服务器配置
服务器配置

给公众号发送消息,bot回复则代表对接成功

公众号回复效果图
公众号回复效果图

ChatGPT-on-WeChat 如何对接 WordPress

我开发了一款插件,用户通过关键词来搜索WordPress文章链接,并将文章标题、文章链接返回给用户。

WordPress插件效果图
WordPress插件效果图

  1. 下载插件,将压缩包上传到服务器 chatgpt-on-wechat/plugins 文件夹下并解压

  2. 修改 wordpress插件/config.json

    {
     "wordpress": true,
     "wordpress_prefix": "搜",
     "wordpress_base_url": "改为自己的WordPress博客地址"
    }
  3. 重启 ChatGPT-on-WeChat,执行下面命令

    # 直接杀死之前的进程,否则端口会被占用
    kill -9 ps -ef | grep app.py | grep -v grep | awk '{print $2}'
    # 启动项目
    nohup python3 app.py & tail -f nohup.out

ChatGPT-on-WeChat 插件

安装完插件后,需要重启一下项目才能正常使用

  1. fatwang2/sum4all:为大模型内容总结服务,有微信插件、telegram机器人 、iOS快捷指令 三个版本,其中微信插件需要自行部署,需配合chatgpt-on-wechat项目,其他插件可点击链接自行体验
  2. XcNgg/chatgpt-on-wechat-plugins
    • FishCalendar 摸鱼日历
    • SearchDomain 域名查询
    • SearchIP ip查询
    • TodaysQuotationste 每日语录
    • TopHub163 网易新闻热榜
    • RandomWord 随机语录
    • WindowsHostInfo Windows主机状态巡检
    • PerpetualCalendar万年历
    • Almanac 黄历
    • CurrentAffairs 政务要闻
    • Poetry 随机诗词
    • CetsHelper CETS单词助手(每日背单词)
    • CTF日历

使用 WordPress 创建自定义链接分享

步骤 1:在主题文件夹下,找到 functions.php 文件,将下方代码复制粘贴进去。

function create_share_links_post_type() {
    register_post_type('share_links',
        array(
            'labels' => array(
                'name' => __('链接分享'),
                'singular_name' => __('链接'),
                'add_new' => __('添加新链接'),
                'add_new_item' => __('添加新链接'),
                'edit_item' => __('编辑链接'),
                'new_item' => __('新链接'),
                'view_item' => __('查看链接'),
                'search_items' => __('搜索链接'),
                'not_found' => __('没有找到链接'),
                'not_found_in_trash' => __('在回收站中没有找到链接')
            ),
            'public' => true,
            'has_archive' => true,
            'supports' => array('title'),
            'exclude_from_search' => true,
            'publicly_queryable' => true,
            'show_ui' => true,
            'show_in_menu' => true,
            'menu_position' => 5,
            'menu_icon' => 'dashicons-admin-links',
        )
    );
}
add_action('init', 'create_share_links_post_type');

function add_share_links_meta_boxes() {
    add_meta_box(
        'share_links_meta_box',
        '链接地址',
        'share_links_meta_box_callback',
        'share_links',
        'normal',
        'high'
    );
}
add_action('add_meta_boxes_share_links', 'add_share_links_meta_boxes');

function share_links_meta_box_callback($post) {
    wp_nonce_field('save_share_links_data', 'share_links_nonce');
    $link_url = get_post_meta($post->ID, 'link_url', true);
    ?>
    <input type="text" id="link_url" name="link_url" value="<?php echo esc_url($link_url); ?>" class="regular-text" />
    <?php
}

function save_share_links_data($post_id) {
    if (!isset($_POST['share_links_nonce']) || !wp_verify_nonce($_POST['share_links_nonce'], 'save_share_links_data')) {
        return;
    }

    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
        return;
    }

    if (!current_user_can('edit_post', $post_id)) {
        return;
    }

    if (isset($_POST['link_url'])) {
        update_post_meta($post_id, 'link_url', sanitize_text_field($_POST['link_url']));
    }
}
add_action('save_post_share_links', 'save_share_links_data');

function share_links_columns($columns) {
    $new_columns = array();
    foreach ($columns as$key => $value) {
        if ($key == 'date') {
            $new_columns['link_url'] = __('链接地址');
        }
        $new_columns[$key] = $value;
    }
    return $new_columns;
}
add_filter('manage_share_links_posts_columns', 'share_links_columns');

function share_links_custom_column($column,$post_id) {
    switch ($column) {
        case 'link_url':
            $link_url = get_post_meta($post_id, 'link_url', true);
            if (!empty($link_url)) {
                echo esc_url($link_url);
            } else {
                echo __('未设置');
            }
            break;
    }
}
add_action('manage_share_links_posts_custom_column', 'share_links_custom_column', 10, 2);

步骤 2:刷新 WordPress 后台页面,在左侧菜单可看到「链接分享」。

步骤 3:在你的主题文件夹中找到(或创建)一个名为 page-templates 的子文件夹。在该文件夹中创建一个名为 share-links.php 的新文件。将下面的代码复制并粘贴到 share-links.php 文件中。

<?php /* Template Name: share_links */ ?>

<?php get_header(); ?>

<?php
// 设置每页显示的链接数量
$posts_per_page = 20;

// 设置当前页码
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;

// 创建一个查询来获取链接
$args = array(
    'post_type' => 'share_links',
    'posts_per_page' => $posts_per_page,
    'paged' => $paged,
);

$share_links_query = new WP_Query($args);

if ($share_links_query->have_posts()) {
    while ($share_links_query->have_posts()) {
        $share_links_query->the_post();

        // 获取链接地址
        $link_url = get_post_meta(get_the_ID(), 'link_url', true);

        // 输出链接地址
        if (!empty($link_url)) {
            echo get_the_date();
            echo '<a href="' . esc_url($link_url) . '">' . get_the_title() . '</a><br>';
        }
    }
}

// 分页导航
<div class="pagination">
    <?php
    echo paginate_links(array(
        'total' => $share_links_query->max_num_pages,
        'current' => $paged,
    ));
    ?>
</div>

<?php
} else {
    echo '<p>' . __('没有找到链接。') . '</p>';
}

wp_reset_postdata();
?>

<?php get_footer(); ?>

步骤 4:在 WordPress 后台新建一个页面,引用名为 share_links 的模板即可。

Obsidian 和 WordPress 我都用什么插件

Obsidian 插件

1. Hover Editor
快速悬浮模式编辑。

2. Outliner
整理大纲。

3. Clearing Unused Images
用于清理图片,该插件默认不开启,需要清理时才启用。但现在基本不插入图片到笔记,纯文本记录。

以上就是我当前使用的所有第三方插件。之前也试过安装 Calendar、Kanban、Thino 等等插件,但感觉都没太大必要,软件自带功能和核心插件完全可以应付常规笔记需求。插件多了反而影响软件秒开。

我使用 Obsidian 插件的使用原则是,脱离 Obsidian 后,所有内容可以在其他编辑软件中继续正常使用。这意味着类似 Dataview 需要语法来判断、筛选内容的插件不符合我的要求。没有 Dataview 的便捷性,反而让我对于索引卡制作和双链的使用更加严格,对内容有更多的思考。提升效率的插件可以考虑安装一两个,或者多记几个快捷键。


WordPress 插件

1. Akismet
默认插件,能应付部分垃圾评论。

2. Autoptimize
优化 HTML、CSS、JS。

3. Object Cache
优化缓存。

4. WP Permalinks Migration
去年简化固定链接后作重定向安装的,计划明年删除。

以上就是我当前使用的所有插件,其他就是依赖部署服务器的时候一些优化,买的最低配轻量应用服务器。目前感觉网站整体速度还可以。我的开源主题,我会在functions.php 中禁用一些不需要的功能。我自己用的主题,我会禁用更多,比如禁止WordPress自动生成缩略图、禁止响应式图片。我不考虑使用第三方服务,比如图床,以避免以后服务终止或迁移带来的困扰。

-

个人觉得,做笔记也好,写博客也好,软件/程序功能上的需求没有那么多,就是图片和文本信息。基于极简原则,其他都是画蛇添足或锦上添花。花样多,需要投入的非必要时间就多,让你分心的东西越多。够用就好。

WordPress私密评论插件

昨晚爆肝到凌晨三点,终于搞定了这款插件。细心的朋友会发现我博客发表评论旁多了个选项——私密评论,顾名思义,选中,你这条评论一般人看不到,成你与博主的悄悄话了。这个功能我原先早在XIGE的博客上看到过,当时觉得没必要,因为我一直觉得一篇文章里,评论也是精彩的部分,老子说过,高手在评论区嘛!

那为毛现在又开始折腾了呢?因为上一篇文章的事情,让我感受到言论不是很自由。暴露在网络上的笔记本,不仅仅只是评论区的朋友在看,更多的是被监管。所以我能控制我博客上的内容,但是我控制不了别人的言论,我觉得在我这里,他们是自由的。但是我又不想与其他博客那样,需要注册登录才能查看和评论,这样很不方便。像WP这样,有昵称、邮箱就可以参与评论,实在太方便了,以至于我觉得验证码都是多余的。

奇怪,怎么有种要立牌坊的味道?

于是乎我就想有个私密评论的功能。起先我想找个插件就好了,没想到唯一一款插件还得收费,像我这种白嫖党是不能接受的。看到Jeffer.Z小友开发JefRssFriends插件,我也有了想法——AI。我不太会使用AI,或者说我不会提问题,沟通有障碍,导致AI给我的答案不仅看不懂,效果几乎没有,无论我怎么问,它只有那一个答案。最后我直接躺平了,说你给我写个WordPress插件,评论可以设置私密评论,我还能修改私密评论的状态。好,好像可以了。然后再加以修改,结合料网分享的私密评论的代码,效果就有了。

20240831192835.jpg
游客看到的私密评论
20240831192805.jpg
博主和评论者看到的私密评论
20240831192731.jpg
后台显示评论私密的状态
20240831193006.jpg
点击可以转换私密的状态
20240831193057.jpg
点击可以转换私密的状态

料网分享的代码,直接复制粘贴就能用。但只能设置私密,但不能取消私密,而我还想实现管理员可以修改评论这种私密与否的状态,不能只能私密,不能公开吧。能力有限,他的代码我不会改,所以就求助于AI,二者一结合,感觉还是挺完美的。

好了,话不多说,网不好的朋友见此下载地址,网好的朋友可以到我的GitHub下载

如果大家有想骂我,表白的,都可以私密我哦!但同时若我觉得你的评论不好公开,我也会将你的评论私密哦。

版权声明: 本文采用 BY-NC-SA 协议进行授权,如无注明均为原创,转载请注明转自 皇家元林
本文链接: WordPress私密评论插件

WP搬家策略

现在WordPress服务器供应商的服务期限大概到今年10月就满了,所以在那之前,团长是应该带着我搬家的,今年早些时候我们已经讨论过这个问题,因为他已经忘记了账号密码,所以常规的搬家步骤不没办法实现,因为根本进不了后台,导出不了数据库,同时也不能把我挂在上面的网站拷贝出来。今年4月的时候,我已经折腾了一番,用的是一个WP的插件(All-in-One WP Migration),那个东西可以在WP后台的界面把网站所有数据全部导出。导出的那些数据被压缩成一个文件。那个文件通过他们网站上面的某些工具,可以在线浏览里面的内容,也可以下载工具安装之后把它解压出来。但即便都解压了出来,那个东西的结构跟WP网站本身还是有一定区别,所以我猜他们没想过用户会把数据导出来以后,通过手工搬家的方式,把数据库挪到其他地方。比如在新的服务器那里,首先进行一个数据库的导入,然后把网站解压的内容复制到新的服务器。为什么这么说呢?因为上面说过,文件加压后的结构跟WP网站本身是有点区别的,但我并没有研究过差异在哪里。有区别就意味着直接搬过去肯定会遭殃。所有人都知道服务器上传文件的大小是有限制的,有可能服务商对你进行了限制,也有可能是软件进行了限制。所以这个插件还卖了一个功能,他们可以把超大的压缩文件上传到你的网站上。你完全不需要考虑文件超限,做不了任何事情。这么高端的操作是付费服务。如果人人都可以轻易地自己挪动,这个付费也就毫无意义,他们也就无法靠这个东西生存下去了。如果网站的数据超限了,但又不想给钱,他们还是给出了一些调整的方案,但这些步骤对小白来说有点复杂,但是对我这种不怕折腾,只要能免费的人来说,完全是可行的。主要步骤分为两个,第一个是在我WP的文件里插入某些语句,但即便这样插入了,也不能保证上传一定不超限。因为还有服务商那边的门槛,所以必要的时候还是要跟服务商沟通一下。在测试搬家这个问题上,我用过两个方式,一个是纯粹的导出导入,第二个是在导入形成网站之后,再导出那个网站的数据库文件,接着把那个网站的网页文件复制到一个新的地方,然后把数据库文件另存为一个新的数据库文件并修改网址,最后把新的网页文件指向新的数据库。之所以做这么无聊的测试,是因为万一服务器那边无论我怎么修改,就是不让我直接导入大文件,我还可以通过这种方式搬家。我20年数据的整个文件不到600MB,而数据库文件只有70多MB。不让600多MB的文件上传,我觉得这是有点可以理解的,但是70多MB的数据库文件,我感觉还是可以成功导入的。如果能实现,我很折腾的第二个方案就意味着我可以把网站从线上搬到线下,然后进行一个普通搬家的流程。之前说过,之所以得这么折腾,是我没办法直接访问现在那个网站的后台,折腾一番以后,实际上我就是把网站线上的后台搬到了线下。

这两年来写了很多的VBA+ADO+SQL,所以我在 phpmyadmin里看到数据库和SQL的时候,我感到了默默的亲切。当我在那里测试SQL语句的时候,发现那个速度实在太感人了。70多MB的SQL文件用Notepad++打开,大概13万行。我要更新里面的某些东西,那是眨眼就能完成的事,跟用Excel处理的速度相比,专业的数据库真的太伟大了。

星期三就已经找过团长,但到星期四下班的时候,他还没回复我。通常情况下不会这么长时间都没反应的,大概他出差了吧…

14年的独立blog

blog在WordPress上,不知不觉已经14个年头。如果没记错的话,是在2010年开始的,因为那个时候BlogBus崩掉了。这14年,我都是跟着同一个团长。那个团长是在豆瓣上认识的,估计现在那个团里面就只剩下我和他了,其他人可能都已经渐渐退掉。实际上,对blog有需求的人,可能只剩下我一个,只有我一个积极用户。团长本身就只是做那个事而已,我不知道他有没有在服务器上折腾些什么。以前可能他是有折腾的,但折腾这种事,对普通人来说不可能一直都折腾。因为写blog本身不算太折腾,每天都耗费基本上相似的时间,习惯下来就好。

我有想过有一天团长不干了,我该怎么办。我自己独立一个门户吗?那个时候,如果遇到一些技术上的故障,我该怎么办呢?现在实际上,我们也的确遇到了技术上的故障。因为团长换电脑了,所以那个服务器的账号密码不见了。理论上联系服务商,只要你提供足够的资料,对方是可以帮你找回密码或者帮你重置密码的,但关键是邮件发过去,对方完全不理你,还真一点办法都没有。当然,如果服务商是大型的,估计不会发生这种事,但如果那只是一个小众的服务商,那么发生这种事,绝对是有可能的,中途跑路也是有可能的。这么多年下来一直都相安无事,我觉得都已经是个奇迹了。中途我们有没有搬过家呢?我没什么印象,因为不是我操作的,我顶多是一段时间开不了网页,但实际上,无论我开得了还是开不了网页,我的blog都会继续,都会在记事本上写下来。重新能开网页的时候,我就把之前囤下的那些东西发布上去,仅此而已。

如果有一天团长不干了,我还会继续每天写,但那个时候估计就不能称之为blog,要称之为日记了,blog和日记对我来说,最大的区别在于一个自己存着,另外一个放在网上,谁都可以看到。

服务商这种东西,即便是最大型的,也说不准靠谱不靠谱,因为大型的服务商也非常有可能有倒闭的那一天,某一天,他们不再开展这个业务了,转而开展别的,把这个业务关闭了,你一点办法都没有。一直以来我们的数据都是放在外国的服务器的。以现在的局势看来,继续放在外国好像有点风险。倒不是因为我的数据有什么问题,涉及了什么方面的东西,而是如果一旦某些事情发生,互联网中断,即便我的东西还存在着,但我再也接触不到了。

我从2004年开始写自己的blog,到昨天为止,我备份了一下全站的内容,媒体资料有400多MB,数据库有70多MB,其它的都是一些很小的脚本。文字内容的东西基本上都在数据库的SQL文件里,附件类图片音频之类的东西其实这么多年下来也不是很大,最主要的原因是可能一开始我会用得比较多,尤其是在我刻橡皮章的时候,后来越来越少了,尤其是近几年,我基本上没有了什么兴趣爱好之后。

还记得一开始在BlogBus上开我自己的blog的时候,我的誓言是一辈子都写,每天不间断,但现在看来,写不写下去靠的是我个人,但能不能让其成为blog,外部干扰因素很大。如果是短时间内,外部因素干扰可以忽略,但如果把时间延长到十年甚至几十年,外部干扰因素影响非常大。

关于博客新主题

在这篇文章中,不讨论深刻的问题,仅仅讲述博客新换主题的一些事情——为何选择这个主题,我对主题进行了哪些修改,我从中得到了什么。

博客的上一个主题

上一个主题修改自Saira。查看开发日志,我发现后期版本中删掉了很多用于主题自定义的代码。查看官方主题商店可见,这部分自定义功能,外加一些其他功能,被设置成了付费主题功能。我利用wordpress.org的开发日志功能,将作者删掉的那部分代码手动恢复了回来。

这个主题的代码中,有大量的注释,而且注释中非常清晰的写出:如果你想改,请改动这里的哪个代码。作为非程序员,对我来说,这大大降低了修改的难度。

这个主题我用了两年半,期间断断续续进行了多次修改。

我突然想到,某国产博客系统的应用商店,没有类似于开发日志的功能,我们无法查看商店内所有开源主题和插件的历史源代码。

博客的新主题

上一个主题用了两年半,我的心境发生了一点变化:主题本来很简单了(不能说是极简,毕竟页面元素还是有好几种),但我想找找更简单的——我想尝试首页只有标题,没有摘要的主题。折腾的过程中,我测试过多个WordPress主题,最终将目光放在瑞典大佬开发的免费主题McLuhan,并进行了一些修改。

适配汉字

该主题自带字体文件及相应css,该字体不是汉字字体。我修改字体家族,调用Windows、Linux、macOS、BSD的内置字体进行显示。并且移除原字体文件及相应css。

我看到有些博主用了云端字体,如霞鹜文楷和思源宋体。当我正在阅读他们的文章时,突然屏幕一闪,所有文字消失,几秒钟后,这些文字以引用的字体重新显示。这个过程有点突兀,因此我没有在博客上使用云端字体。

主题汉化

对前端显示的英文进行汉化。除右下角的版权信息外,其余部分应该已经全部汉化了。如果我发现汉化不完整的地方,还会进行修改。

修复Bug

该主题有一处bug:评论翻页,或提交评论后,无法直接跳转到评论区域。我不是程序员,所以发现该bug时是懵逼的。对比上一个主题的源代码,我发现该主题少了一句代码,也就是id="comments"。添加以后,这个问题没有再出现。

修改主题的收获

检验知识的唯一方法

在过去折腾的过程中,我虽然没有足够的时间去系统性学习html+css,但我依然学到了一些css和php知识。在修改主题的过程中,可以对我所学到的知识进行检验,看看我掌握的知识有没有出现错误。事实证明,我学到的是正确的。

验证自己的想法

在讲述如何验证自己想法之前,先讲一下心路历程。

该主题针对英文及瑞典语文章的显示效果是非常好的。我们都知道,汉语言文字和英文、瑞典语最大的不同是,汉字是方块字,视觉上要比英文和瑞典语文字大。因此,使用该主题显示汉字便没有英文和瑞典语那么好看了,我需要进行修改。

我想到,如果我增加行距,设置为两端对齐,为了减轻眼睛负担而将字号加大(尤其是移动端),是不是可以呢?

于是改动相应的css代码进行测试。最终发现,我的想法是正确的。

成就感

修改主题的过程中,当自己收获了成功的喜悦,心中会有让自己满足的成就感。

也许有人会问:你为何不直接用国内开发者的主题,你到底是什么居心?

答:没有什么居心,就是因为这种成就感。

在一位国内大佬连续开发出几个简单的WordPress和Typecho主题之后,我看到有博主在其博文中说:“我看到关注的博客很多都已经食用。”这个“很多”到底是多少,我不清楚。我关注的博客中,也有使用的。他的主题外观看起来不错,我在测试站安装使用过。外观好看的主题当然不仅于此。我选择了在自己能力范围内的折腾,这个过程让自己有知识和能力上的收获,更有成就感。

这个主题会用多久

这取决于下一次心境变化的时间,目前还无法确定。

下一个努力的方向

学会WordPress的主题架构,并能够将自己在Typecho上开发的主题移植到WordPress。由于时间有限,这个努力的方向能否实现还不确定。

在这里,要感谢TasteWP提供的免费服务,给我提供了完善的测试环境。特别是,我的VPS和虚拟主机都尚未支持安装PHP 8.3,但这个主题确实是在PHP 8.3环境下修改的。

博客带给我什么?——博客重建7周年

自2016年12月29日博客重建以来,至今已走过7个年头。有句话叫“七年之痒”,博客重建7年后,写博客的热情因极度繁忙的工作而有所减退——本来想在2023年12月29日将这篇文章发出来,无奈闲暇时间太少,断断续续写到现在。然而,即便如此,我依然没有放弃长文写作。宁愿不写,我也不愿意将博客完全变成微博。如果没有这个信念,我也不会在2016年底选择重建博客。既然重建,那就把这个信念坚持到底。

博客带给我精神层面的提升

接受曾经的自己

博客重建伊始,我想督促自己戒掉智能手机成瘾,记录相应的心路历程。最终,博客建立的比较成功,但戒掉智能手机成瘾却失败了。

2018年,我开始记录自己的成长经历,名为《人生前三十年》。这个连载在2020年暂时停更,原因是这种记录方式并没有凸显我和家庭成员的性格成因,以及带给我的无穷伤害。我需要换一种方式去记录这一切,但由于工作的忙碌而无暇顾及。

我为何要去写《人生前三十年》呢?起因在2017年,我陷入有点严重的抑郁状态。当时的我,不知道问题的起源,受制于物质条件,我无法去进行昂贵的专业心理咨询。天无绝人之路,因缘和合之下,经过有相似经历之人的点拨,后购买心理问卷调查,我终于得以了解到,自己抑郁,以及一系列性格和行为缺陷及障碍的根源,完全来自于原生家庭。经过总结和思考,我决定以《人生前三十年》的名字将这一切记录下来。虽然文章没有写出自己想要的样子,但写作的过程极大缓解了我的痛苦,减轻了抑郁的折磨。

2019年6月,我去了当时赫赫有名的建立在安徽宣城的净土宗寺院“弘愿寺”。三天后,我离开寺院,此时我基本走出抑郁,能够正常工作和生活。从此以后,自己的性格有极大改善,虽然目前仍有缺陷——比如自己依然喜好争执——但已经和过去的自己完全不同,几乎已经彻底脱胎换骨。重建后的博客,记录了这整个历程。

这便是博客重建带给我的巨大帮助之一。精神层面的提升,对我非常重要,彻底改变了我的人生走向。如果没有通过在博客上写作,进而发生这些改变,也许我已被埋在黄土之下。

陪伴自己成长

在博客的“关于”页面,我列出了自己使用独立博客的历史。里面提到,2013年9月16日博客因主机垮掉而倒闭之时,有个唯一的数据库备份。博文数据现在完整地放在wordpress.com上,但我从来没有去回顾。直到前两个月,我在进行测试时(下文会提到我在测试什么),将数据又恢复了一次,保存在了测试站上。工作之余稀少的休息时间,我间歇性的将以前的文章通读了一遍。

以前的文章,与现在的对比非常明显。不仅透露出曾经的幼稚,还凸显出来因原生家庭环境影响而出现的性格问题,及进而导致的语言表达问题。另外,观察世界、思考问题及写作方面的思维,已在接受学校教育之后被固化,这大大限制了我从多角度、多方面去观察世界和自身,这种情况在文章里同样表现的非常明显。

所幸的是,我终于在2018年以后认识到了这些问题。在摆脱原生家庭影响方面,我做的还算是成功;摆脱思维固化方面,仍在努力挣扎。我知道,在背后那只“手”的操纵下,想做到摆脱思维固化是非常难的。但既然已经意识到这个问题了,我必须去解决掉它。

在这里,我把其中一个事情单独拎出来说说。以后我也许单独撰文回顾这件事,因此本文中我只用寥寥数语讲述一下,希望您不要把焦点全部放在这件事上。2010年时,我喜欢过一个女生,暧昧了两个月以后,她拒绝了我。大半年以后我才走出来,因为她,我写了五篇文章。现在回头看看,当初的情执,反映的问题恰恰是原生家庭环境塑造了我缺乏关爱、没有安全感、缺乏调节情绪的能力和控制欲强的性格。这个女生在2021年结婚生子,她的老公不是我,而我也从这恶劣的性格中解脱了出来。

这些成长的过程,被我用博客记录了下来。博客的存在,陪伴了我的成长。

只是2016年之前的数据,我永远都不会再公开出来。存储这些文章的wordpress.com站点,被我设置成了私密。

反抗思想的“被迫”退化

在《警惕背后的那只手——读和菜头〈重开博客〉有感》这篇文章中,我提到,背后的那只“手”在操纵着我们能够从纸质材料和互联网中获取的一切信息类型和内容,更是操纵我们只能获取他们编撰或是杜撰的一切知识、思想和情绪。在他们的操纵下,绝大多数人会愈发心浮气躁,进而丧失逻辑思维和思考能力。即便是热爱写作的人,除了会发生前文提到的观察世界、思考问题和写作方面的思维被禁锢的问题之外,还存在这些能力的退化,首先表现出的便是阅读和写作长文能力的丧失。

大秦从未消亡,法家的理论体系对治理我们的人来说从未“过时”。对治理我们的人来说,我们出现这些恶性变化对他们和他们的后人绝对利好;对我们来说,这导致我们失去了最基本的学习能力,进而会丧失重要的生活能力,沦为一个丢失灵魂的行尸走肉。

有一些被操纵的人,意识不到这些不说,反而仗着手里的话语权去替那只“手”辩护,再试图让意志不坚定或没有主观意志的人堕入更深层的思想地狱。

如果换在过去,受原生家庭影响,我是个讨好型人格,没有任何主见,别人说什么我都相信,我能想象到自己早已踏上通往奴役之路的样子。通过不断的思考、观察和写作,如今虽然也在这条路上,但行走缓慢,希望永远不会走到终点。

博客带给我技术上的进步

折腾,还是折腾

我曾多次在博客上说“多思考,少折腾”,但只要有闲暇时间,我便收不住这颗折腾的心。

这些年,注册过数不清的BSP,折腾过独立搭建Typecho、Zblog PHP、MovableType、Flatpress(文本数据库)、Ghost、PivotX(已停止开发)、Farbox 2.0,以及已经记不住名字的程序。前些日子,我利用一个随时可能跑路的个人主机商的月付版高配VPS折腾了消耗运行内存很严重的Halo程序。有的程序折腾的掉头发,有的则能做到熟练使用。

我已熟练掌握如何利用Netlify、Vercel和CloudFlare Pages在线编译Jekyll、Hexo和Hugo,而不是本地生成html再上传。

我在自己的VPS上用过Ubuntu、Debian、Centos和AlmaLinux操作系统,在VPS上用过纯命令行操作的LAMP和2023年发生挂马事件的LNMP,也用过宝塔、1Panel、AMH、WDCP、WebAdmin等服务器控制面板。

现在,我将目标放在使用Litespeed环境、Mariadb数据库的CyberPanel面板。我的两台VPS分别在跑OpenLitespeed和已开通Starter Plan(免费)的Litespeed Enterprise。

我曾发布过3个Typecho主题,分别是DiaryWriteSimple,修改并发布了Typecho的目录树插件

我曾魔改几个WordPress主题,包括现在自己在用、啊呜喵在用的,以及几个在测试站上欣赏的。

我还曾无偿帮助过几位博友建立、维护自己的博客。

在折腾的过程中,虽然远达不到精通的程度,但还是了解了不少东西,促使我能够基本独立进行博客的建立和维护,还能帮助博友解决一些常见的基础问题。在技术层面之外,与人心有关的种种,我也深刻领悟了——我在求助技术问题时,曾被少部分博主嘲讽,特别是折腾Bitcron期间;当思想本可以碰撞出火花时,极个别博主却不想真心讨论问题,只想让你接受,只想教育你,只想证明你是错的,在找不到理由时,便直接进行人身攻击。可又能怎么样?始终没能阻止我技术和思想的成长。

折腾是我的爱好,但我不会将它变成职业。有位WordPress免费主题开发者的前车之鉴便是如此。

博客运营的备用选择

经过折腾,我可以做到不拘泥于某个特定的服务,某个特定的技术去维护博客。假如,提供服务的主机商倒闭了,或服务质量大幅度下降,可以立刻迁移;某个著名的服务器控制面板加入了后门(懂得都懂),可以立刻使用其他的面板;博客程序能做到无缝切换,不损失任何数据……

为了博客能顺利的维护下去,我准备了备选方案。

前面提到,我为了测试而恢复了旧的博客数据。我测试的,正是上文提到的Litespeed Enterprise。我花费0元购买了Litespeed Enterprise的Starter Plan,复刻了与目前所用虚拟主机完全一致的服务质量和使用体验。如果目前的虚拟主机不再使用,我可以在自己的VPS上独立托管这个博客。

对于使用Litespeed Enterprise的虚拟主机,或者专业的WordPress Hosting,也有备选,虽然花销会比目前使用的虚拟主机高,但依然低于使用VPS的费用。

等待天明

影视节目制作人季业曾说过这样一段话:

如果天总也不亮,那就摸黑过生活;如果发出声音是危险的,那就保持沉默;如果自觉无力发光,那就别去照亮别人。但是——但是:不要习惯了黑暗就为黑暗辩护;不要为自己的苟且而得意洋洋;不要嘲讽那些比自己更勇敢、更有热量的人们。可以卑微如尘土,不可扭曲如蛆虫。

摸黑生存并不可怕,可怕的是为黑暗辩护;同样可怕的是,身处黑暗却不自知,以至于双目失明。

我想起这样两类人:

第一类人,代表之一便是斯维拉娜·亚历塞维奇在《二手时代》中记录的,那些在罪恶的时代结束之后反而仓皇失措的人。

第二类人,代表之一则是东晋、姚秦时期著名高僧鸠摩罗什。从公元382年开始,他经历了人生至暗的20余年,但他依然没有放弃信仰和信念,厚积薄发,最终成为一代高僧,译经三十五部,广为流传到今天。

我正在向鸠摩罗什及以他为代表的第二类人学习。在至暗时刻,我一直试图点燃烛光,哪怕再微弱,也要照亮内心。如果能唤醒他人,那便是功德无量。我相信,天亮之前是最黑暗的时刻,熬过这一刻便是黎明的曙光。我会耐心守护心中的烛火,拼尽全力等待天明。

警惕背后的那只手——读和菜头《重开博客》有感

说来惭愧。前不久我才知道和菜头已重开博客,而这已经是6个月之前的事情了。作为十几年前便开设了独立博客的博主,当时的博客圈很少有人不知道和菜头。


先说说我对和菜头仅有的了解。

2011年,我从一本讲述Linux日常使用的书的配套光盘的视频中看到了一个网站《槽边往事——比特海日志》,这就是和菜头最广为人知的博客。

就在那段时间,我发现他其实还有两个开设更久远的博客,内容是同步的,在2009年底全部被“隔离”了。有其他独立博客记录了原因:当时他点评了一个社会新闻。具体是什么新闻,时隔十余年我已经不记得了。那时,他的文章后面会附上一句话和一张图,巧的是这张图我因为很喜欢便保存起来了,如今贴在这里,一起回味。

和菜头在没有被“隔离”的博客上发布的内容与另外两个博客同步。根据页面版式、302跳转链接、页脚的电话号码等信息,我推测这个博客托管在了罗永浩创建的牛博网上。这个网站对近些年走入博客圈的博主来说应该都很陌生。想当年,牛博网上群英荟萃,也正因如此,牛博网被强制关闭,服务器被迫迁移,随后也被“隔离”;老罗在国内服务器重新开设了“嫣牛博”,将其定义为“阉部落”。2013年夏天,老罗关闭了牛博和阉牛博,但《槽边往事——比特海日志》一直保留着。几年后,打开《槽边往事——比特海日志》,页面提示数据库空间已满,博客倒下。

和菜头曾经利用Feedburner(后被谷歌收购)提供邮件订阅,该服务通过抓取RSS更新,自动向订阅的电子邮箱发送新的内容,无需手动操作发送过程。我的邮箱收到的这些邮件,至今依然保留着。

几年前,和菜头转战WX公众号。然而,他的写作风格却在写公众号不久之后就变了。

和菜头在2011年7月23日的文章(互联网档案馆同步链接)当中提到:“我的实名并非和菜头,而是赵得柱“,不知道这是不是他的真实名字。


当我看到《重开博客》以及2020年注册的新域名所发文章《1587》,我深有感触。自从我2016年12月29日重建博客以来,对于他提到的问题,我也被影响过,我也思考过。这些问题,我将直接引用“槽边往事”的内容叙述,并在引用之后,讲述自己的思考。对我来说,能够支撑到今天,靠的是一种更猛烈的坚持,这种坚持除了要求自己坚持思考和写作之外,也是在坚持一些“反抗”。

博客算是网络近现代史上的一款老产品,在中国早已经式微。尤其是移动互联网的兴起,让人们大规模地转移到App里去,不再写长文,而是以发短文字、图片和视频为主。所以,博客在中国已经完全过气,而我这样的行为应该算作是一种复古。

类似的事情,包括我在内已经有无数的人曾经提起。

对不少人来说,不仅仅是“不再写长文,而是以发短文字、图片和视频为主”,而且连阅读长文的能力都已经退化甚至丧失。打开一篇长文之后,心浮气躁之下草草看两眼就关掉,只愿意阅读包含图片和视频的短文。

这一点,在独立博客圈表现同样非常明显。在一些以记录日常为主的博客中,包含着很多图片的短文,下面的评论就有很多;而我的博客当中,上千字甚至两三千字的长文下面评论数则少得可怜。

每家大公司建立起一个平台,把内容和用户全部集中在自己的App里。

他们习惯了打开App,并且将这种动作视为上网本身。

这些App通过这些方式实现了流量内循环——利用用户的人际关系进行捆绑,并限制外链、限制跨平台分享。APP内包含着无数不透明且动态变化的“红线”,于是靠标题党和谣言组成绝大部分内容,将人们推进“娱乐至死”的怪圈中。

有些人将这种现象视为国内互联网发展的“趋势”,似乎这是不以人们意志为转移的时代发展“潮流”。而我却不这样认为。

我认为,国内互联网背后有一只“手”,无时无刻不在操纵这一切,有意将国内互联网创造成这个样子,目的很明确:让绝大多数人愈发心浮气躁,进而丧失逻辑思维和思考能力,成为一名只能被动接受由他们编撰(抑或是杜撰)的一切知识、思想和情绪的机器。这个目的对哪些人利好,懂的都懂。

只不过,总有那么一戳人是例外。

只使用手机上网的人,和同时使用台式机电脑、笔记本电脑、平板电脑、智能手机的人,完全是不同的两类人。简单说起来,只会用手机上网的人不大适合阅读,他们的行为习惯是快读扫读,然后就要留言发表看法,并且喜欢在留言区里骂人。会使用电脑,熟练进行Web上操作的人,毫无疑问眼界要相对宽广一些,多少见识过一点世界,这些人还保留有阅读的习惯,也知道讨论的形式和规则……这样的读者群和这样的讨论,一旦产生之后就可以保留在互联网上,可以为搜索引擎所查找,于是就对所有人提供了永续的价值。

根据我的经验,将“会使用电脑,熟练进行Web上操作的人”都描述为“眼界要相对宽广一些,多少见识过一点世界”过于绝对,但是,这类人确实要比“只使用手机上网的人”在阅读和讨论方面有太多的优势。

海浪撞击海岸的鸟瞰图。
田野的鸟瞰图。一条道路穿过右上角。

不知道您是否听说过上面图片中的两本书。奥威尔的书描述了人们出现“对真实世界认知能力的毁灭,更是人自我意识的毁灭”;赫胥黎的书描述了“科技并没有令社会的人民精神进步,反而让社会文化倒退”。现如今,二者都存在,并且是二者的有机结合。

背后的那只“手”,有足够的能力对这两类人分别施加类似于两本书中描述的“法术”,拿捏的恰到好处,无懈可击。

和菜头在文章中还提到:

十五年前,我是用WordPress架设博客,购买了独立域名,委托朋友帮我购买了虚拟机。唯恐访问速度慢,唯恐国内读者看不到,唯恐搜索引擎优化不足,唯恐博客界面难看。为此我花费了许多时间和精力,申请过ISP,替换过不知道多少套模板,用了许多种性能优化插件。

我可能还要考虑是不是在GitHub上架设一个静态博客,是不是要在Typecho和Hexo之间做选择?因为blogger和WordPress已经不是最流行的了,用起来不够前卫。

我也有一部分相似的经历,而我折腾的更多。

2016年12月底重建博客之后,我花费了很多时间折腾。我折腾过TypechoZblog PHPMovableType阮一峰的网络日志使用的程序)、FlatpressGhost(自托管)、PivotX(已停止开发)、Farbox 2.0(折腾的掉头发,再也不玩这个了),以及一些我已经记不住名字的程序。我还尝试建立Jekyll、Hexo和Hugo三类静态博客。最新又想折腾Halo程序,但我没有闲置的VPS了,也没有足够的闲暇时间。

我自己的博客使用的程序,从2011年到现在,经历过WordPress、Jekyll、Zblog PHP和Typecho之后,又回到了WordPress。现如今,Litespeed环境,无论是开源的OpenLitespeed,还是针对单个网站免费的Litespeed Enterprise,都对WordPress和其他一部分PHP程序提供了足够的优化,速度丝毫不差。WordPress使用起来难度最低,有足够的、完善的资料可供独立查找。因为,在简体中文圈,在那只“手”的操纵下,有很多人的戾气非常重,他们喜欢嘲讽求助者,而不是帮助求助者。最好的办法,是独立查找资料,询问可靠的人,而不是有求于那些嘲讽者。

图片来源:OpenLitespeed官网

真正的问题是什么平台看样子能够持续稳定地存在下去?以及今天才存在的特色问题:如何让一篇文章成为互联网上的文章,而不是App的内部文章?也就是说,它可以被搜索引擎找到,被他人简单容易地跨平台引用和链接,让我明晰地看到trackback和feedback。

你看,独立博客上的文章不就是互联网的文章吗?

我在文章中添加了对其他内容的引用和链接,都是跨平台的。


我的博客,并不像“槽边往事”一样拥有流量。反之,正如上文中提到的,评论数少得可怜;在inoreader和feedly的订阅量远少于以短文、丰富的图片为主的日常记录博客,也远少于记录较多但思考较少的博客。

要知道,“不再写长文,而是以发短文字、图片和视频为主”的现状,对那只“手”的操纵者而言是好事,可对我们呢?我意识到,我们被这只“手”操纵而丧失了重要的东西,影响的是我们自己的一生。

因此,我要“反抗”这只“手”制造的所谓“潮流”。

我不仅要多读书,多观察这个世界的不同角落,多记录,多思考,并且要保留自己写作长文的能力,增强自己写作长文的动力。因为在写作长文的过程中,可以将自己积累的思考通过一定的逻辑记录下来,不仅记录了世界最真实的样子,而且还锻炼了那只“手”试图抹杀掉的能力,这二者都很有价值和意义。

我的棱角,并没有全部被这只“手”磨平,有些反而更尖锐了。

解决因为 SSL 导致的 WordPress 后台无限 Redirect 的问题

在使用 CapRover 并配置域名为 HTTPs 域名时,在你访问管理后台时,可能会导致触发Chrome 自己的无限 Redirect 的问题。

之所以出现这个问题,是因为 CapRover 的架构导致的:CapRover 在最外层是一个 Nginx,SSL 证书也是在这一层完成的。而 CapRover 的默认配置,在将请求向后转发时,透传的域名会是不含 HTTPs 的协议标识的,导致 WordPress 认为发来的请求是非加密的。

d2b5ca33bd970f64a6301fa75ae2eb22 18

而 WordPress 识别到你的请求未加密,就会返回 302 让你进入 HTTPS的链接。但新的请求并不会带上 HTTPs 的标识,导致进入无限循环。

解决这个问题的一个简单处理的方式是 — 在你的 wp-config.php 中加入如下代码,来告诉 WordPress,这个请求已经是 HTTPs 保护的了,你直接处理就好。

/* for ssl in docker */

define('FORCE_SSL_LOGIN',true);

define('FORCE_SSL_ADMIN',true);

$_SERVER['HTTPS'] = 'on';

在 WordPress 的 Docker 镜像上加装 Redis 拓展,以支持 Redis 缓存

从 LAMP 到 Docker based PaaS 工具 当中,我提到我现在使用的是 Docker Based PaaS 产品来托管站点。本站目前其实就是跑在 Docker 上的。

使用默认的 WordPress 镜像时,我发现一个问题:没有支持 Redis 拓展!我使用 Redis 来缓存 Query,提升访问的性能。如果缺失了 Redis 拓展,就会减少一部分缓存的能力。于是开始研究如何在官方的 WordPress 镜像上加入 Redis 拓展。

根据 WordPress 镜像的官方说明,我们可以 docker-php-ext-* 命令来配置镜像,安装必要的拓展,来满足我们日常使用的需求,并给出了官方的参考。

不过,我在验证 Redis 拓展时,使用 docker-php-ext-* 命令没有配置成功,好在可以使用 pecl 来安装。于是,我便将 Dockerfile 修改成如下内容,来完成对于 Redis 拓展的安装。

FROM wordpress:latest
RUN pecl install -o -f redis && rm -rf /tmp/pear && docker-php-ext-enable redis

修改好 Dockerfile ,然后重新启动,一切都好了~

d2b5ca33bd970f64a6301fa75ae2eb22 4

WordPress接入纯真IP库CZDB版本

之前,本站基于纯真IP库实现评论者IP归属地,用的好好的,突然官方又改变策略了,推出czdb数据格式,并在10月1日开始停止dat格式和exe格式的发布(详情见官方公众号)。

新版本的要求就多了,首先你得在官方注册登录,其次根据它的要求帮它宣传(我是在本博客底部加上他们网站的链接),并截图给他审核,通过之后你才会有授权,你才能得到key。有了这个key你才能使用czdb格式数据库。我个人是不太喜欢需要通过这种方式才能得到的一些东西,吃相有点难看了。但是没办法,好像也找不到更好的选择了。

CZDB目前官方已支持JAVA、C语言和PHP解析程序,我们直接拿来用就可以了。下面主要说说咱们WordPress的食用方法,也就是PHP的解析程序。

PHP解析程序的GitHub地址:czdb_searcher_php

在项目目录下运行以下命令来安装 CZDB Searcher:

composer require czdb/searcher

如果找不到包,可能是因为你没有使用composer 2.x版本,可以使用以下命令来安装composer 2.x版本:

composer self-update --2

然后将下面代码扔进functions.php文件里:

//解析纯真IP获取评论者ip归属地 开始

require_once __DIR__ . '/vendor/autoload.php';

use Czdb\DbSearcher;

//评论作者归属地函数
//Code by HJYL.ORG
//IP数据库由纯真CZ88提供
function getCity($ip){
    $dbSearcher = new DbSearcher("cz88_public_v4.czdb的路径", "BTREE", "key");
    // get_template_directory() . "/czdb/cz88_public_v4.czdb" 这是某主题目录下的文件夹
    // 默认BTREE,搜索模式(例如,"BTREE" 少量查询 或者 "MEMORY" 大量查询)。
    // key,即密钥,从https://cz88.net/geo-public获取
    
    $region = $dbSearcher->search($ip);
    // 将字符串拆分成各个部分
    if(strpos($region, "\t")){
        $region = preg_replace('/\t+/','–',$region);

    }elseif(strpos($region, " ")){
        $region = str_replace(' ','–',$region);
    }

    $region = explode("–", $region);

    //分别获取国家、省、市字段
    $country = $region[0] ?? "";
    $province = $region[1] ?? "";
    $city = $region[2] ?? "";

    $dbSearcher->close();

    //优先显示城市,其次省,最后国家
    if($ip == '127.0.0.1'){
        $data = '小黑屋';
    }elseif($city == "" || false !== strpos($city, '移动') || false !== strpos($city, '电信') || false !== strpos($city, '联通')){
        $data = $province;
    }elseif($province == "" || false !== strpos($province, '移动') || false !== strpos($province, '电信') || false !== strpos($province, '联通')){
        $data = $country;
    }else{
        $data = $city;
    }
    
    return $data;
}

//解析纯真IP获取评论者ip归属地 结束

调用方法:

echo getCity(get_comment_author_IP());

结束撒花~~~

花絮:

这个版本的数据库支持IPv4和IPv6,其实之前的那个itbdw/ip-database也是支持IPv4和IPv6的,只是纯真没有IPv6数据库。这次发布了IPv6数据库,但是我也用不上。

这段代码的解析思路是这样的:根据IP查询数据库,得到的格式是这样的——“中国–安徽–合肥 移动”,然后将其拆解,分别得到国家、省、市。别看这格式很简单,我测试了很久,才发现移动前的空格不仅有空格,还有制表符“\t”,这是目前我遇到的,不知道还有没有其他看不见的符号了。

最让人吐槽的是纯真社区版IP库在地级市的准确率上不是很高。所以不必较真,仅供娱乐而已。

版权声明: 本文采用 BY-NC-SA 协议进行授权,如无注明均为原创,转载请注明转自 皇家元林
本文链接: WordPress接入纯真IP库CZDB版本

近期调整计划

最近这几天心情挺烦躁,有时候压抑,有时候暴躁的很。真不知怎么了做事也特别没有耐心,也许是太多事压在心头闹的! 试了新的wordpress自带主题,感觉还蛮不错的,配置起来还不是很麻烦。 最近网站的一些调整: 1. 打算把文章别名改为数字ID,因为有时候文章名会重复,也懒得在一次次修改这个拼音别名了。(毕竟新版wordpress已经很好了,别名终将成为过去,必须接受新的事物。)-待定 2. 彻底修改图床程序,现已改为wordpress,图片链接地址不变。-已实现 3. 准备取消自建的统计?统计了又有什么用?CF自带的也挺爽,折腾这些多余的没啥作用。-待定 4. 有计划取消自建的RSS,2-3究其 […]

飞牛士主题修改记录

记录飞牛对博客的一些修改记录,方便自己以后回溯,以供他人参考。

一直持续更新

2024.10.28

修改H2样式

.post-content h2 {
    position: relative;
    padding: 1.25rem 0 0;
}
.post-content h2 {
    position: relative;
    padding: 0 0 0 1.5rem;
    line-height: 1.5;
}
.post-content h2:before {
    content: '';
    position: absolute;
    width: 50px;
    height: 5px;
    border-radius: 10px;
    left: 0;
    top: 0;
    z-index: 1;
    background-image: linear-gradient(to right, #3858f6, #6e86ff, #8068ff, #3858f6);
    background-size: 300% 100%;
    transition: all .4s ease-in-out;
}
.post-content h2:before {
    content: '';
    position: absolute;
    width: 5px;
    height: 24px;
    border-radius: 10px;
    left: 0;
    top: 6px;
    z-index: 1;
    background-image: linear-gradient(to right, #3858f6, #6e86ff, #8068ff, #3858f6);
    background-size: 300% 100%;
    transition: all .4s ease-in-out;
}

2023.12.20

换主题换个心情,慢慢修改。

panda主题精选评论

php

//走心评论
function weisay_touching_comments_list( $comment ) {
	$cpage = get_page_of_comment( $comment->comment_ID, $args = array() );
?>
	<li <?php comment_class(); ?> id="comment-<?php comment_ID() ?>">
		<div id="comment-<?php comment_ID(); ?>" class="comment-body">
		<div class="comment-meta">
		<div class="comment-avatar flex-avatar w-48"><?php echo get_avatar( $comment, 48 ); ?></div>
		<b class="fn comment-name"><?php comment_author_link() ?></b><span class="edit-link"><?php edit_comment_link( __( 'Edit' ), ' ' ); ?></span>
	
		</div>		
			
		<div class="comment-content">
		<?php comment_text(); ?>
		</div>
	
			
			
	<div class="comment-metadata"><?php comment_date('Y-m-d') ?> 评论于  •  <a href="<?php echo get_comment_link($comment->comment_ID, $cpage); ?>" target="_blank"><?php echo get_the_title($comment->comment_post_ID); ?></a></div>
	</div>
<?php
}
function weisay_touching_comments_end_list() {
		echo '</li>';
}

css。

.touching-comments-button{display:block;float:right;clear:both;margin-top:10px;}
.touching-comments-button span svg{width:18px;height:18px;}
.touching-comments-button br{display:none;}
.touching-comments-button a{outline:none;}
.touching-comments-list li{list-style:none;border-bottom:1px solid #ddd;margin-bottom:10px;}
.touching-comments-list .touching-comments-button,.touching-comments-list .touching-comments-chosen{display:none;}
.touching-comments-list img.avatar{vertical-align:middle;}
.touching-comments-list .comment-name{margin-left:2px;}
.touching-comments-list .comment-content p{text-indent:0;     background-color: #e8b86826 !important;
    display: inline-block;
    padding: 0.75rem 1rem;
    border-radius: var(--border-radius-md);
    border-top-left-radius: 0;
    margin: 1rem 0 1rem;
    text-indent: 0;}
.touching-comments-list .edit-link{float:right;}
.touching-comments-list .comment-metadata{opacity: 0.8;margin: 0 0 1rem;}
.touching-comments-title{display:block;line-height:30px;height:30px;margin:10px; font-size: 1.25rem;}
.touching-comments-picture img{width:100%;vertical-align: middle;}
.touching-comments-chosen{background:#f9f1be;padding:3px 8px;margin:5px 0;border-radius:8px 0;font-size:14px;display:inline-block;}
.touching-comments-chosen span{color:#76600a;}

2023.12.18

添加了精评页面

页面链接:https://www.feinews.com/touching

使用的是@威言威语 的走心评论插件。

插件地址:https://www.weisay.com/blog/wordpress-plugin-touching-comments.html

修改页面css样式:

.touching-comments-button{display:block;float:right;clear:both;margin-top:10px;}
.touching-comments-button span svg{width:18px;height:18px;}
.touching-comments-button br{display:none;}
.touching-comments-button a{outline:none;}
.touching-comments-list li{margin-left: -30px;list-style:none;border-bottom:1px solid #ddd;margin-bottom:10px;}
.touching-comments-list .touching-comments-button,.touching-comments-list .touching-comments-chosen{display:none;}
.touching-comments-list img.avatar{vertical-align:middle;}
.touching-comments-list .comment-name{margin-left:2px;}
.touching-comments-list .comment-content p{text-indent:0;margin-top: 30px;padding: 20px;
    position: relative;
    background: hsla(var(--theme-color-hsl),.04);}
.touching-comments-list .comment-content p:before {
    position: absolute;
    left: 15px;
    top: -19px;
    border: 9px solid transparent;
    border-bottom: 10px solid hsla(var(--theme-color-hsl),.04);
    content: "";
}
.touching-comments-list .edit-link{float:right;}
.touching-comments-list .comment-metadata{opacity: 0.8;margin-bottom: 20px;}
.touching-comments-title{display:block;line-height:30px;height:30px;    margin: 20px 0px 20px 0px;font-weight: bold;}
.touching-comments-picture img{width:100%;vertical-align: middle;}
.touching-comments-chosen{background:#f9f1be;padding:3px 8px;margin:5px 0;border-radius:8px 0;font-size:14px;display:inline-block;}
.touching-comments-chosen span{color:#76600a;}

2023.12.09

修改页面主题背景色:#f3f7f6;

修改文章页面内边距从20px改成30px;

.el-boxed .entry-main {
    background: var(--theme-el-bg-color);
    padding: 30px;
    margin-bottom: 20px;
}

2023.12.06

清理和优化WordPress网站数据库wp_options表和自动加载的数据,由原来的1800项,减少成255项。

2023.12.05

顶部导航栏修改将原来导航栏的菜单文字大小14px改成16px。

body>header.header .nav {font-size: 16px;}

2023.12.04

友情链接页面修改

  • 修改边框为圆角8px
  • 增加了边框外间距10px
  • 添加了鼠标划过时,box上移5px

详情页面:https://www.feinews.com/links

❌