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(订阅激活/解锁)、post.rendered(付费内容过滤)、seo.structured_data
  • 后台「插件管理」:启停 / 上传 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 照常可用(同一队列)

测试

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

目录结构

app/
  Blog/            # 前台域模块(Controllers/Jobs/Services/Support/View
  Filament/        # 后台资源与页面
  Console/Commands # sablog:import / attachments:sync-s3 / workerman:serve / content:convert
themes/            # 主题(sablog / modern
plugins/           # 内置插件(blog-seo / ai-moderation / payment / membership
docs/deploy.md     # 部署指南

许可

MIT

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