# Sablog 数据导入指南 把 SaBlog-X 1.6 老站数据完整迁入 LaraLog。**全部脚本化、可重复执行**,保留原始 ID,老 URL 自动 301 兼容(不产生 SEO 404)。 ## 前置准备 1. 老库可访问:MySQL 8(或可导出的老 MySQL 5.x,先在 MySQL 8 建好导入目标) 2. 老附件目录:sablog 的 `attachments/`(在 Web 服务器上,含编号子目录) 3. 已按 `docs/install.md` 完成安装(`migrate --seed` 后导入) > 建议:先在**测试环境**用 `--dry-run` 风格(见下文幂等说明)完整跑一遍,确认数量后再上生产。 ## 一键导入 ```bash php artisan sablog:import \ --host=127.0.0.1 --port=3306 \ --database=sablog --username=root --password=老库密码 \ --prefix=sablog_ \ --attachments-dir=/var/www/old/attachments \ --sync-attachments \ --convert-markdown ``` ### 参数说明 | 参数 | 默认 | 说明 | |------|------|------| | `--driver` | mysql | 老库驱动(测试可用 `sqlite`) | | `--host` / `--port` | 127.0.0.1 / 3306 | 老库地址 | | `--database` | (必填) | 老库名 | | `--username` / `--password` | root / 空 | 老库账号 | | `--prefix` | `sablog_` | 老表前缀(老站可能自定义过) | | `--attachments-dir` | — | 老附件目录,配合 `--sync-attachments` 用 | | `--sync-attachments` | 关 | 同步附件文件到新存储(本地中转或直接上 S3) | | `--convert-markdown` | 关 | 导入时把 HTML 正文转为 Markdown | | `--fresh` | 关 | 清空目标表后重新导入 | ## 数据映射 | 老表 | 新表 | 说明 | |------|------|------| | `users` | `users` | **ID 保留**;老 MD5 密码进 `legacy_md5`,登录时自动升级为 bcrypt | | `articles` | `posts` | **articleid 保留为 id**;`[attach=xx]` 按内容格式处理(见下) | | `categories` | `categories` | cid 保留;导入后自动重算文章数 | | `comments` | `comments` | commentid 保留;visible 语义映射为状态 | | `links` | `links` | linkid 保留 | | `attachments` | medialibrary `media` | 文件 + `legacy_attachmentid` 映射(老 `[attach=xx]` 按此解析) | | `settings` | `settings` | 键值映射为站点设置(可在后台「博客设置」继续改) | | `tags` | spatie tags | 老 aids 文本解析为独立标签 + 关联 | **不迁移**:trackback/引用通告(垃圾来源,接口已关闭)、搜索缓存表、验证码(由 AI 审核 + 蜜罐 + 频控取代)。 ## 附件短代码的处理 | 老内容 | 导入后 | |--------|--------| | HTML 正文 `[attach=12]` | 原样保留,**渲染时按 legacy id 解析**为附件链接/图片 | | Markdown 正文(--convert-markdown) | 自动转成 `{{attach:12}}` 令牌(`[]` 是 Markdown 保留字符) | 两种格式都能正常显示老附件,无需手工替换。 ## 老 URL 兼容(301,无需 Nginx 配置) - 伪静态:`/show-12-1.html` → 新文章页;`/category-3-1.html` → 新分类页;`/archives-202008-1.html` → 新归档 - 查询串:`/?action=show&id=12`、`/?action=search&keyword=x`、`/?action=tags&id=1` …全部映射 - 稳定路径:`/rss.xml`、`/sitemap.xml`、`/robots.txt` 保持原样 - 老入口:`attachment.php?id=` → 301 到 S3/本地媒体地址;`tburl.php`/`trackback.php` → 410 ## 附件上 S3 ```bash # 导入后再把老附件批量上传(Multipart、幂等、可断点续传) php artisan attachments:sync-s3 --legacy-dir=/var/www/old/attachments # 个别文件校验失败需要强制重传 php artisan attachments:sync-s3 --legacy-dir=... --force ``` > 未配置 S3 时附件留在本地 public 磁盘,网站可正常展示;配好 S3 后再执行同步即可无缝切换。 ## 内容转换(可选) ```bash php artisan content:convert --all # 全部 HTML 文章转 Markdown php artisan content:convert 12 # 单篇 php artisan content:convert --all --dry-run # 先预览 ``` ## 幂等与重跑 - 导入按**原始 ID** `updateOrInsert`:重复执行不会产生重复数据,只会覆盖更新 - 需要完全重来:`--fresh` 清空目标表后导入 - `attachments:sync-s3` 自带去重:已上传的文件跳过(除非 `--force`) ## 导入后检查清单 - [ ] 文章总数、评论总数与老站一致(后台仪表盘 / `SELECT COUNT(*)`) - [ ] 抽查老 URL:`/show-12-1.html` 301 到新文章页 - [ ] 抽查带 `[attach=xx]` 的文章:附件正常显示 - [ ] 老账号用**原密码**登录成功(密码自动升级为 bcrypt) - [ ] 分类文章数、文章评论数正确(导入脚本已自动重算) - [ ] RSS/Sitemap 正常输出 - [ ] 主题切换后前台布局正常 ## 常见问题 | 现象 | 处理 | |------|------| | 报「找不到老表」 | 检查 `--prefix`(老站表前缀可能不是 `sablog_`)与老库名 | | 附件显示不出来 | 确认 `--attachments-dir` 路径正确;看 `attachments:sync-s3` 输出报告 | | 老密码登录失败 | 老库密码若是自定义加密(非 MD5),需要按 `User::verifyPassword` 扩展 | | 中文乱码 | 老库导出时用 utf8mb4;`--driver=sqlite` 只用于测试 |