Typecho自动删除占用cid附件自动文章连贯插件
早在24年就尝试解决文章id不连贯
解决Typecho新文章、页面uid排序错乱问题
出现不连贯的原因是所有内容(文章、页面、附件、草稿)都存在同一张contents表中,共用一个 “自增 ID”(AUTO_INCREMENT)为了解决这个问题我开发了 AutoIDSeq 插件,让 CID 能自动 “归位”。下面分享它的功能、核心代码
AutoIDSeq - 自动连贯文章id
AutoIDSeq 的目标很简单:确保新发布的文章、页面(及对应草稿)CID 连续且不冲突。它实现了这些关键能力:
- 自动同步 CID:新内容发布时,智能计算 “最大有效 CID + 1” 作为目标 ID;若被占用,自动避让(删除占用的附件,或对有效内容 +1)。
- 附件冲突处理:若目标 CID 被 “附件” 占用,直接删除该附件(附件 ID 通常不影响核心内容)。
- 自增 ID 管理:支持手动修改数据库表的自增 ID 起点,避免后续 ID “断层”。
- 多类型兼容:同时覆盖 文章(post)、文章草稿(post_draft)、页面(page)、页面草稿(page_draft),贯穿内容创作全流程。
插件的核心逻辑集中在 “发布前 CID 同步”和“后台动作处理” 两部分
发布前自动同步 CID:beforePostPublish 方法
这个方法是 “自动排序 ID” 的核心,在内容发布 / 编辑的钩子中触发:
public static function beforePostPublish($content, $widget)
{
$isNewContent = !isset($content['cid']); // 判断是否为“新内容”(非编辑已有内容)
$contentType = $widget->type; // 获取内容类型(post 或 page)
$db = Typecho_Db::get();
$prefix = $db->getPrefix();
$tableName = $prefix . 'contents';
$targetCid = 0;
if ($isNewContent) { // 仅处理“新发布”的内容,编辑已有内容不改动 ID
// 步骤 1:查询“文章/页面及草稿”的最大 CID
$validTypes = ['post', 'post_draft', 'page', 'page_draft'];
$maxContentResult = $db->fetchRow($db->query(
$db->select('MAX(cid) AS maxCid')
->from($tableName)
->where('type IN ?', $validTypes)
));
$maxContentCid = $maxContentResult ? (int)$maxContentResult['maxCid'] : 0;
$targetCid = $maxContentCid + 1; // 目标 CID 为“最大有效 ID + 1”
// 步骤 2:检查目标 CID 是否被占用
$occupiedCheck = $db->fetchRow($db->query(
$db->select('cid', 'type', 'status')
->from($tableName)
->where('cid = ?', $targetCid)
));
if ($occupiedCheck) {
if ($occupiedCheck['type'] == 'attachment') {
// 若被“附件”占用,直接删除该附件
$db->query(
$db->delete($tableName)
->where('cid = ?', $targetCid)
);
} else {
// 若被“文章/页面/草稿”占用,CID 自动 +1 避让
$targetCid += 1;
}
}
// 步骤 3:同步数据库自增 ID,避免后续 ID 断层
$db->query("ALTER TABLE `{$tableName}` AUTO_INCREMENT = " . ($targetCid + 1));
// 步骤 4:为新内容设置最终 CID
$content['cid'] = $targetCid;
}
return $content;
}
通过 4 个步骤保障 CID 连续性 —— 先找 “文章 / 页面 / 草稿” 的最大 ID、检查冲突、智能处理冲突(删附件 / 避让有效内容)、同步数据库自增 ID,最后给新内容赋值。
2. 后台动作处理:handleActions 方法
这个方法处理 “一键删除所有附件” 和 “修改自增 ID” 两个核心操作:
public static function handleActions()
{
$request = Typecho_Request::getInstance();
$db = Typecho_Db::get();
$prefix = $db->getPrefix();
$tableName = $prefix . 'contents';
// 一键删除所有附件
if ($request->isPost() && $request->action === 'deleteAllAttachments') {
try {
$db->query("DELETE FROM `{$tableName}` WHERE `type` = 'attachment'");
Typecho_Widget::widget('Widget_Notice')->set(_t('所有附件已成功删除'), 'success');
} catch (Exception $e) {
Typecho_Widget::widget('Widget_Notice')->set(_t('删除失败:%s', $e->getMessage()), 'error');
}
}
// 修改自增 ID
if ($request->isPost() && $request->action === 'updateAutoIncrement') {
$newValue = trim($request->newAutoIncrement);
if (is_numeric($newValue) && (int)$newValue > 0) {
try {
$db->query("ALTER TABLE `{$tableName}` AUTO_INCREMENT = {$newValue}");
Typecho_Widget::widget('Widget_Notice')->set(_t("自增ID已修改为:{$newValue}"), 'success');
} catch (Exception $e) {
Typecho_Widget::widget('Widget_Notice')->set(_t("修改失败:%s", $e->getMessage()), 'error');
}
} else {
Typecho_Widget::widget('Widget_Notice')->set(_t('请输入有效的正整数'), 'error');
}
}
}
提供 “清理冗余附件” 和 “手动干预自增 ID” 的入口,让插件既能自动化又能手动控制
3. 可视化配置面板:config 方法
设计了后台界面,可以直观查看 “当前自增 ID”“最近内容”“附件数量” 等信息:
public static function config(Typecho_Widget_Helper_Form $form)
{
// 自动同步开关(代码略,主要是 Checkbox 组件)
// 自增 ID 管理区域
echo '<div class="plugin-section">';
echo '<h3>表自增 ID 管理</h3>';
// 显示“当前自增 ID”“建议修改值”,并提供修改表单
echo '</div>';
// 最近内容区域(显示文章/页面及草稿的最近 5 条)
echo '<div class="plugin-section">';
echo '<h3>最近 5 篇内容(含文章/页面及对应草稿)</h3>';
// 从数据库查询并展示最近内容
echo '</div>';
// 附件信息与操作区域
echo '<div class="plugin-section">';
echo '<h3>附件信息</h3>';
// 显示附件数量、列表,以及“一键删除所有附件”按钮
echo '</div>';
// 调试日志展示区域
echo '<div class="plugin-section log-section">';
echo '<h3>最近一次自动同步日志</h3>';
// 展示 debug.log 中的最近日志
echo '</div>';
}
使用截图
当前页面是本站的「Google AMP」版。查看和发表评论请点击:完整版 »