gouki e0c709ad5c
Build and Deploy / verify (push) Successful in 1m0s
Build and Deploy / deploy (push) Successful in 33s
fix(import): null out orphan category references (FK safe)
2026-09-07 19:55:19 +00:00

LaraLog

基于 Laravel 12 + Filament 5 + Livewire 4 + Spatie 生态 的现代化博客系统,从 SaBlog-X 1.6 完整迁移而来:

  • 脚本迁移php artisan sablog:import 一键从老库迁入全部数据(文章/分类/评论/标签/友链/用户/附件),保留原始 ID,老 URL 全部 301 兼容
  • 多主题themes/ 目录即皮肤,后台一键切换/上传 ZIP;内置 sablog 经典风 + modern 简约风两套
  • 插件系统plugins/ 目录 + 钩子系统(action/filter),ZIP 安装 + 可选远程市场
  • 内置插件SEO & GEOJSON-LD/OG/llms.txt/Markdown 导出)、AI 评论审核 + 内容润色(Workerman 异步)、支付(支付宝/微信/沙箱)、会员(套餐订阅 + 付费文章)
  • 附件全走 S3R2 / COS / OSS 兼容,新上传零落盘,attachments:sync-s3 一键同步老附件(大文件 Multipart)

技术栈

组件 版本 说明
Laravel ^12.0 应用框架
Filament ^5.7 后台面板(zh_CN
Livewire ^4.4 前台交互
Workerman ^5.2 常驻进程:队列消费者 + WebSocket 进度推送
yansongda/pay ^3.7 支付宝 / 微信支付
spatie 库 permission / medialibrary / sitemap / robots / tags / backup
league/commonmark ^2.9 Markdown 渲染(GFM
league/html-to-markdown ^5.1 老 HTML 内容转换
MySQL 8.x 数据库

快速开始

# 1. 安装依赖
composer install
cp .env.example .env
php artisan key:generate

# 2. 配置 .envMySQL 8
DB_DATABASE=laralog
DB_USERNAME=root
DB_PASSWORD=

# 3. 迁移 + 种子(创建 admin@laralog.test / password
php artisan migrate --seed

# 4. 启动(Herd 或 artisan serve
php artisan serve

# 5. 后台:http://laralog.test/admin

迁移老 Sablog

# 原始导入(内容保持 HTML,[attach=xx] 渲染时解析)
php artisan sablog:import \
  --database=sablog --host=127.0.0.1 --port=3306 \
  --username=root --password=xxx \
  --attachments-dir=/path/to/old/attachments --sync-attachments

# 同时把内容转换为 Markdown[attach=xx] 转为 {{attach:xx}} 令牌)
php artisan sablog:import ... --convert-markdown

# 事后单独转换 / 同步附件到 S3
php artisan content:convert --all
S3_ACCESS_KEY=... S3_BUCKET=... S3_ENDPOINT=... php artisan attachments:sync-s3 --legacy-dir=/path/to/old/attachments

不迁移的过时功能:trackback(引用通告,垃圾来源)、搜索缓存表、验证码(由 AI 审核 + 蜜罐 + 频控取代)、WAP、广告位变量。

主题

  • 目录:themes/{name}/,含 theme.json(标题/版本/描述/作者)+ views/** + assets/
  • 激活主题的 views 目录前置到全局视图路径:主题覆盖同名视图,缺失自动回退默认视图
  • 资产开发期由 /themes/{name}/assets/... 流式返回;生产可 php artisan theme:publish(见 docs/deploy.md
  • 后台「主题管理」可激活 / 上传 ZIP / 删除

插件

  • 目录:plugins/{vendor}.{name}/,含 plugin.json + src/ServiceProvider.php(继承 App\Blog\Support\PluginServiceProvider+ 可选 database/migrationsroutes/web.phpviews/
  • 钩子:addAction(hook, cb) / addFilter(hook, cb, priority),核心钩子:
    • comment.createdAI 审核)、payment.paid(按 payable 分发订阅激活/解锁)、post.rendered(付费内容过滤/paywall)、seo.structured_data
    • filament.post_form / filament.post_table(后台文章表单/表格注入)
  • 插件依赖 requires 强制校验:启用需依赖已启用,停用/卸载会被依赖者阻止;启动时依赖不满足的插件跳过
  • 订单商品化:Payment 多态 payable 关联购买实体,实体实现 payableLabel() / payableUrl() 接入订单展示(详见 docs/plugins.md
  • 后台「插件管理」:启停 / 上传 ZIP 安装 / 卸载 / 市场拉取(配置 MARKET_URL 后可用)
  • 插件自带迁移由 migrate 自动加载(app/Providers/AppServiceProvider 注册 plugins/*/database/migrations

内容格式

  • 每篇文章有 content_formatmarkdown / html),新文章默认 Markdown
  • 老数据导入标记为 html 原样保留;content:convert 批量转 Markdown
  • 附件短代码:HTML 内容用 [attach=1] / [img=1]Markdown 内容用 {{attach:1}} / {{img:1}}[] 是 Markdown 保留字符),渲染时统一解析
  • 付费内容:[paid]...[/paid] 短代码,非会员/未解锁访客隐藏(会员插件)

异步处理(Workerman

php artisan workerman:serve start      # 队列消费者 × N + WebSocket :8787
php artisan workerman:serve stop
  • 消费者复用 Laravel Queue\Workerdatabase / redis 队列统一支持,常驻进程内框架只启动一次(省去每个任务的启动开销)
  • 任务统一实现 App\Blog\Jobs\AiJob 接口(handle(LlmClient)),依赖由容器自动注入
  • 队列选择:
    • database(默认):WORKERMAN_QUEUE_CONNECTION=database
    • redisWORKERMAN_QUEUE_CONNECTION=redis 并确保 QUEUE_CONNECTION=redisREDIS_* 配置正确;redis 连接的 block_for 建议设为 0(配合 1s 轮询,避免阻塞 Workerman event loop
  • 消费队列:WORKERMAN_QUEUES=default,aiai 队列为 AI 审核/润色任务)
  • 失败重试:WORKERMAN_MAX_TRIES(默认 3),超时 WORKERMAN_TIMEOUT(默认 60s),重试耗尽进 failed_jobs
  • 降级路径:php artisan queue:work 照常可用(同一队列)

外链中转(/go,内置插件)

内置插件 neatstudio.link-tracker(外链中转):

  • 正文外链、评论正文 URL、评论作者网址、友链统一改写为 /go/{hash}302 跳转 + 点击统计、可停用拦截(返回 410)、隐藏真实链接、为未来广告位预留
  • 站内链接/相对路径/mailto/tel/锚点不中转;同一 URL 复用同一短码
  • 后台「管理 → 外链中转」可查看点击量、启停、删除
  • 插件化设计:核心提供 tracked_url() 钩子(link.redirect 过滤器)+ 正文 post.rendered 过滤器接入点,停用插件后链接恢复直连、不影响内容显示

前台缓存

  • 匿名 GET 页面整页缓存(首页/列表/文章/归档/标签等),TTL 默认 300 秒(PAGE_CACHE_TTL),命中时零数据库查询
  • 文章浏览量由独立 /track-view 端点统计,不受整页缓存影响(实时)
  • 后台「缓存管理」:清空页面/侧边栏/设置/全部缓存、重建编译缓存
  • 侧边栏数据与站点设置另有 1 小时缓存

对外 API

  • 交互式文档(OpenAPI/Swagger 风格):GET /docs/api
  • 端点:/api/site/api/posts/api/posts/{slug}/api/categories/api/tagsPOST /api/comments/api/meBearer Token
  • 供小程序 / 第三方平台接入,详见 docs/api.md

测试

php artisan test    # 84 个用例:迁移/老路由 301/主题/插件/会员支付流/AI 审核/商城购买

开发者文档

文档 内容
docs/install.md 安装指南(环境/配置/验收清单)
docs/import.md Sablog 老数据导入(命令/映射/附件/301 兼容)
docs/deploy.md 部署(nginx/systemd/workerman/cron/上线清单)
docs/development.md 开发规范(代码/插件/主题/队列/测试/提交)
docs/tutorial-plugin.md 插件开发教程(10 分钟上手,配套 demo)
docs/tutorial-theme.md 主题开发教程(10 分钟上手,配套 demo)
docs/plugins.md 插件 API 详解(钩子/依赖/商品化/市场契约)
docs/themes.md 主题 API 详解(视图解析/注入点/变量)
docs/architecture.md 架构与设计决策
docs/api.md 对外 API(小程序/第三方)

上手示例

  • 插件:plugins/demo.hello-world/(短代码 / 钩子 / 路由 / 后台页 / 迁移 / 表单注入,全演示)
  • 主题:themes/demo/(最小可运行主题,绿色系,覆盖 partials 即可换肤)

目录结构

app/
  Blog/            # 前台域模块(Controllers/Jobs/Services/Support/View
  Filament/        # 后台资源与页面
  Console/Commands # sablog:import / attachments:sync-s3 / workerman:serve / content:convert
themes/            # 主题(sablog / modern / demo 示例)
plugins/           # 内置插件(blog-seo / ai-moderation / payment / membership+ demo.hello-world 示例
docs/              # 全部文档(见上文表格)

许可

MIT

S
Description
No description provided
Readme
2.1 MiB
Languages
PHP 70.5%
Blade 22.8%
CSS 6.2%
JavaScript 0.3%
Shell 0.2%