Flarum 简介与版本差异
Flarum 是新一代的轻量级论坛软件,以快速、美观、易于扩展而著称。其技术栈基于 PHP (Laravel 组件)、MySQL/PostgreSQL 以及 Mithril.js 前端框架。
| 特性 | Flarum 1.x | Flarum 2.x |
|--------------|-------------------------------------|---------------------------------------|
| 发布时间 | 最后稳定版 1.8.5 (2023) | 正式版 2.0 (2024-05) |
| PHP 要求 | 7.3 – 8.0(不兼容 PHP 8.1+) | PHP 8.1+ |
| 底层框架 | Laravel 6/7 组件 | Laravel 11 组件 |
| 前端构建 | Webpack (node) | Vite (node 18+) |
| 模板引擎 | 自定义 | Blade 组件支持 (增强) |
| 队列系统 | Illuminate Queue(可选) | 内置 Laravel Queue,更易配置 |
| 性能建议 | PHP-FPM + Redis | FrankenPHP Worker 模式 大幅提升 |
| 扩展兼容性 | 大量成熟扩展 | 生态快速迁移,主流扩展已兼容 |
本指南以 Flarum 2.x 为主线,同时保留 1.x 部署章节供历史项目参考。如果你正准备新部署,强烈建议直接选择 2.x。
一、环境准备
1.1 服务器基础要求
- 操作系统:Ubuntu 22.04/24.04、Debian 12、CentOS 9 等,推荐 Linux。
- CPU 不少于 1 核,内存建议 ≥ 1 GB(编译前端时可能需要更多)。
- 域名已解析到服务器 IP(用于 SSL 配置)。
# 更新系统并安装基础工具(Ubuntu/Debian)
sudo apt update && sudo apt upgrade -y
sudo apt install curl wget git unzip software-properties-common -y
1.2 PHP 安装与扩展
Flarum 2.x 要求 PHP 8.1 或更高版本(推荐 PHP 8.3)。使用 ondrej/php PPA 安装最新版:
sudo add-apt-repository ppa:ondrej/php -y
sudo apt update
sudo apt install php8.3 php8.3-fpm php8.3-cli \
php8.3-common php8.3-mysql php8.3-pgsql \
php8.3-gd php8.3-xml php8.3-curl php8.3-mbstring \
php8.3-zip php8.3-bcmath php8.3-intl php8.3-opcache \
php8.3-redis -y
检查安装:
php -v
php -m | grep -E "mysql|pgsql|gd|curl|redis|mbstring"
1.3 数据库(MySQL / MariaDB / PostgreSQL)
MySQL 8.0+ 或 MariaDB 10.6+,或者 PostgreSQL 14+ 均可。以 MySQL 为例:
sudo apt install mysql-server -y
sudo mysql_secure_installation
创建数据库及用户:
CREATE DATABASE flarum CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'flarum'@'localhost' IDENTIFIED BY '超级强密码';
GRANT ALL PRIVILEGES ON flarum.* TO 'flarum'@'localhost';
FLUSH PRIVILEGES;
EXIT;
1.4 Composer 包管理器
Flarum 使用 Composer 管理依赖与扩展。安装全局 Composer:
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === file_get_contents('https://composer.github.io/installer.sig')) { echo 'Installer verified'.PHP_EOL; } else { echo 'Installer corrupt'.PHP_EOL; unlink('composer-setup.php'); exit(1); }"
php composer-setup.php --install-dir=/usr/local/bin --filename=composer
php -r "unlink('composer-setup.php');"
composer --version
1.5 Web 服务器选择
| 服务器 | 优势 | 适用场景 |
|-------------|----------------------------------------|------------------------------|
| Nginx | 成熟稳定,配合 PHP-FPM,文档丰富 | 传统高性能站点 |
| Apache | 易于配置 .htaccess,共享主机普遍支持 | 初学者或共享环境 |
| Caddy | 自动 HTTPS,配置极简 | 单文件部署,现代项目 |
| FrankenPHP | 将 PHP 编译为静态二进制,内置 Caddy,支持 Worker 模式,性能飞跃 | 本文首选高性能方案 |
1.6 高性能 C 内核方案:FrankenPHP
传统 PHP-FPM 每次请求启动/销毁进程,存在不小的开销。FrankenPHP 使用 Go 语言编写,其内部集成了 Caddy(一个用 Go 打造的高性能 Web 服务器)并直接调用 PHP 解释器(C 实现),可让 PHP 脚本常驻内存(Worker 模式),达到接近 Swoole/RoadRunner 的高吞吐。
- 二进制分发,无需额外安装 PHP-FPM。
- 内置自动 HTTPS、HTTP/2、HTTP/3。
- 可运行于独立模式或配合 Docker。
安装 FrankenPHP(独立二进制):
# 下载最新 FrankenPHP 二进制(需包含 PHP 8.3)
curl -L -o frankenphp https://github.com/dunglas/frankenphp/releases/latest/download/frankenphp-linux-x86_64
sudo mv frankenphp /usr/local/bin/
sudo chmod +x /usr/local/bin/frankenphp
frankenphp --version
此二进制已将 PHP 8.3 编译在内,无需单独安装 PHP。如需加载扩展(如 redis),可通过 php.ini 或环境变量配置。
1.7 Redis 缓存数据库
sudo apt install redis-server -y
sudo systemctl enable redis-server --now
redis-cli ping # 应返回 PONG
确保 PHP 已安装 Redis 扩展(见 1.2 节末尾)。
二、Flarum 1.x 安装(历史版本)
尽管 Flarum 2.x 已发布,但仍有存量站点运行 1.8.5。如需部署 1.x(例如测试目的),请确保 PHP 7.4/8.0(不可使用 PHP 8.1+)。
# 指定版本安装
composer create-project flarum/flarum . "1.8.5"
安装过程与 2.x 类似,但后续需要手动配置 config.php 中的数据库信息,并访问 /admin 完成安装。官方已不再对 1.x 提供安全更新,请尽快迁移。
三、Flarum 2.x 安装(推荐)
3.1 创建项目
进入 Web 根目录(例如 /var/www/flarum),使用 Composer 创建 Flarum 2.x 项目:
sudo mkdir -p /var/www/flarum
sudo chown -R $USER:$USER /var/www/flarum
cd /var/www/flarum
composer create-project flarum/flarum . --stability=stable
若想体验最新开发版,可将 --stability 设为 beta 或 dev。
3.2 配置数据库与安装
复制环境配置文件:
cp .env.example .env
编辑 .env 填入数据库信息(MySQL 示例):
DB_DRIVER=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=flarum
DB_USERNAME=flarum
DB_PASSWORD=超级强密码
如果需要 PostgreSQL,请设置为 DB_DRIVER=pgsql。
运行安装命令:
php flarum install
根据提示填写管理员信息,安装成功后会显示论坛首页链接。
设置目录权限(如果使用传统 PHP-FPM,Web 用户通常为 www-data):
sudo chown -R www-data:www-data /var/www/flarum
sudo chmod -R 755 /var/www/flarum
3.3 定时任务与队列
Flarum 2.x 依赖 Laravel 的调度器和队列处理任务(邮件、通知等)。
添加 Cron 任务:
sudo crontab -e
# 添加一行,每分钟执行一次调度器
* * * * * cd /var/www/flarum && php flarum schedule:run >> /dev/null 2>&1
配置队列:默认使用 sync 驱动(同步执行),高并发场景请使用 Redis 队列(见 5.1)。
四、Web 服务器配置实战
4.1 Nginx 配置模板
假设域名 forum.example.com,PHP-FPM 监听 unix:/run/php/php8.3-fpm.sock。
server {
listen 80;
server_name forum.example.com;
root /var/www/flarum/public;
index index.php index.html;
# 禁止访问敏感文件
location ~ /\.(?!well-known).* {
deny all;
}
# 友好 URL 重写
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# 静态资源缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}
启用站点:
sudo ln -s /etc/nginx/sites-available/flarum /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
4.2 FrankenPHP 配置与运行
FrankenPHP 可直接作为生产服务器,无需 Nginx。
创建文件 Caddyfile 到项目根目录:
forum.example.com {
root * /var/www/flarum/public
php_server {
resolve_root_symlink
}
# 或者使用 Worker 模式(性能更佳)
# php {
# worker /var/www/flarum/public/index.php
# }
file_server
}
启动 FrankenPHP:
sudo frankenphp php-server --domain forum.example.com --root /var/www/flarum/public
# 或使用 Caddyfile 模式
sudo frankenphp run --config /var/www/flarum/Caddyfile
Worker 模式启动(极致性能):
frankenphp worker --worker-public /var/www/flarum/public /var/www/flarum/public/index.php
Worker 模式会启动指定数量的 PHP 工作进程常驻内存,减少启动开销,要求你的代码无全局状态泄漏(Flarum 2.x 已兼容)。
4.3 Caddy 通用配置
如果单独安装官方 Caddy Web 服务器,Caddyfile 如下:
forum.example.com {
root * /var/www/flarum/public
php_fastcgi unix//run/php/php8.3-fpm.sock
file_server
}
4.4 SSL 证书自动管理
FrankenPHP 和 Caddy 均内置 Let's Encrypt 自动化,只需将域名指向服务器,Caddy 会自动申请证书,无需额外操作。Nginx 用户可使用 certbot:
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d forum.example.com
sudo systemctl reload nginx
五、性能深度优化
5.1 Redis 作为缓存、会话、队列驱动
编辑 config.php(或在 2.x 的 .env 中配置):
// config.php 或通过环境变量控制
return [
'cache' => [
'driver' => 'redis',
'connection' => 'default',
],
'session' => [
'driver' => 'redis',
'connection' => 'default',
],
'queue' => [
'driver' => 'redis',
'connection' => 'default',
],
];
在 .env 中添加 Redis 连接信息:
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
安装 Laravel Redis 包(2.x 已内置,1.x 需要 composer require illuminate/redis)。
记得重启队列 Worker:
php flarum queue:work redis --queue=default --tries=3 --daemon
5.2 PHP OPcache 与 JIT
编辑 /etc/php/8.3/fpm/php.ini 或 FrankenPHP 的自定义 php.ini:
opcache.enable=1
opcache.memory_consumption=128
opcache.max_accelerated_files=10000
opcache.revalidate_freq=60
opcache.jit_buffer_size=64M
opcache.jit=tracing
注意:Worker 模式下代码常驻,修改后需要重启 FrankenPHP。
5.3 FrankenPHP Worker 模式详解
传统 PHP-FPM 为每个请求创建一个新进程或复用空闲进程,脚本执行完毕即回收上下文。
Worker 模式 下,FrankenPHP 启动固定的 Worker 进程,index.php 只加载一次,所有请求在同一个进程中循环执行,大大减少了 vendor/autoload.php 和框架启动的开销。测试显示,相较于 FPM,吞吐量可提升 3-5 倍。
启动命令示例(4 个 Worker):
frankenphp worker --worker-num 4 /var/www/flarum/public/index.php
确保你的应用没有使用全局变量保存请求相关数据(Flarum 符合),否则会造成数据污染。
六、Flarum 生态总览
6.1 扩展市场与安装方法
Flarum 的扩展通过 Composer 分发,官方市场位于 Flarum Discuss,或者直接搜索 Packagist 上的 flarum-ext-* 包。
安装扩展(以头像上传为例):
composer require fof/upload
安装完成后,管理员后台 “扩展” 页面会出现对应设置卡片。
6.2 常用核心扩展推荐
| 扩展 | 功能描述 |
|---------------------|----------------------------------|
| [fof/upload](https://forum.xmuer.online/d/194) | 文件与图片上传(支持 S3) |
| flarum/mentions | @用户、引用帖子 |
| flarum/tags | 标签分类 |
| flarum/suspend | 用户禁言管理 |
| [fof/links](https://forum.xmuer.online/d/195) | 导航链接管理 |
| fof/oauth | 社交媒体登录(GitHub、微信等) |
| [ianm/twofactor](https://forum.xmuer.online/d/208) | 双因素认证 |
| [fof/sitemap](https://forum.xmuer.online/d/207) | XML 站点地图,利于 SEO |
| clarkwinkelmann/flarum-ext-seo | SEO 优化 (2.x 已更名为其他包) |
6.3 语言包与国际化
中文语言包安装:
composer require flarum-lang/chinese-simplified
启用后,刷新后台即可看到中文界面。也可在后台 “外观” → “语言” 中切换默认语言。
6.4 主题与前端定制
Flarum 提供了 Less/CSS 变量覆盖机制。在后台 “外观” → “编辑自定义样式” 中,你可以直接编写 Less 代码来修改变量,例如主色调:
@primary-color: #3490dc;
@secondary-color: #ffed4a;
对于深度定制,可以创建主题扩展(继承 flarum/core 的前端资源)。
七、修改现有插件
日常使用中,你可能需要调整某个扩展来适配自己的业务。
7.1 插件目录结构解析
以 vendor/fof/upload 为例,典型结构:
fof/upload/
├── extend.php # 扩展注册入口
├── js/
│ ├── src/
│ │ ├── admin/ # 后台前端入口
│ │ └── forum/ # 前台前端入口
│ └── package.json
├── src/
│ ├── Commands/
│ ├── Listeners/
│ └── ...
├── resources/
│ └── locale/ # 翻译文件
├── migrations/
└── composer.json
- extend.php:定义插件如何扩展 Flarum(相当于服务提供者)。
- js/:前端资源,使用 Mithril.js,通过 Webpack (1.x) 或 Vite (2.x) 编译。
- src/:PHP 后端逻辑。
7.2 修改后端逻辑
假设要修改 fof/upload 的上传大小限制,直接编辑 src/Api/Controllers/UploadController.php 并不安全,因为 Composer 更新会覆盖。推荐方式:
- 在自己的插件中监听相关事件或替换服务(见第九节)。
- 如果必须改动核心扩展,用 Composer 的
post-install-cmd 脚本打补丁,或使用 cweagans/composer-patches。
但最简单的临时修改是直接编辑,然后记录备份。
7.3 修改前端组件(1.x 与 2.x 差异)
Flarum 1.x:
进入扩展的 js/ 目录,安装依赖并运行编译:
cd vendor/fof/upload/js
npm install
npm run build # 或 npm run dev(开发模式带 source map)
Flarum 2.x:
默认使用 Vite。进入插件 JS 目录,执行:
cd vendor/fof/upload/js
npm install
npm run dev # 开发服务器,自动编译与热重载
npm run build # 生产构建
编译后的 JS 会被输出到扩展的 assets/ 目录,Flarum 框架自动加载。
7.4 重新编译与热重载
在修改前端过程中,使用 npm run dev 启动本地 Vite 服务器,然后配置 Flarum 的后台 “外观” 选项中的 “开发者模式”,或者在前端 URL 后加 ?hot=1,会自动指向本地开发服务器,实现热更新,无需频繁刷新。
八、从零制作 Flarum 插件
8.1 生成插件骨架
官方提供了模板生成器 FriendsOfFlarum/nova 或直接使用 Composer 创建。这里使用最简单的 Composer 初始化:
mkdir -p packages/acme/example && cd packages/acme/example
composer init
按照提示填写包名 acme/example,类型选择 flarum-extension。
然后创建基本文件:
acme/example/
├── extend.php
├── composer.json
├── js/
│ ├── src/
│ │ ├── admin.js
│ │ └── forum.js
│ ├── package.json
│ └── webpack.config.js # 1.x 用,2.x 改为 vite.config.js
├── src/
├── resources/
│ └── locale/
└── LICENSE
8.2 插件架构与命名规范
composer.json 必须包含 extra.flarum-extension 信息:
{
"name": "acme/example",
"type": "flarum-extension",
"require": {
"flarum/core": "^2.0"
},
"extra": {
"flarum-extension": {
"title": "示例插件",
"icon": {
"name": "fas fa-puzzle-piece",
"backgroundColor": "#3490dc",
"color": "#fff"
}
}
},
"autoload": {
"psr-4": {
"Acme\\Example\\": "src/"
}
}
}
8.3 使用 Extenders 扩展系统
extend.php 是插件的灵魂,通过 Extenders 以声明式方式修改论坛功能。
<?php
namespace Acme\Example;
use Flarum\Extend;
use Flarum\Frontend\Document;
return [
(new Extend\Frontend('forum'))
->js(__DIR__.'/js/dist/forum.js')
->css(__DIR__.'/resources/less/forum.less'),
(new Extend\Frontend('admin'))
->js(__DIR__.'/js/dist/admin.js'),
new Extend\Locales(__DIR__.'/resources/locale'),
(new Extend\Routes('api'))
->get('/example', 'acme.example.api', Api\Controllers\ExampleController::class),
// 设置权限
(new Extend\Policy())
->modelPolicy(User::class, Access\UserPolicy::class),
// 注册新权限
(new Extend\Permissions())
->ability('acme.example.view', 'acme.example'),
];
Flarum 提供了丰富的 Extenders,涵盖路由、模型、事件监听、设置、通知等等,几乎无需触及框架核心。
8.4 数据库迁移与 Model
创建迁移文件:
mkdir -p migrations
touch migrations/2024_01_01_000000_create_example_table.php
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Schema\Builder;
return [
'up' => function (Builder $schema) {
$schema->create('acme_example', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
},
'down' => function (Builder $schema) {
$schema->drop('acme_example');
},
];
在 extend.php 中注册:
(new Extend\Migration())
->path(__DIR__.'/migrations'),
Model 示例:
namespace Acme\Example;
use Flarum\Database\AbstractModel;
class Example extends AbstractModel
{
protected $table = 'acme_example';
}
8.5 前端开发(Mithril + Vite/Webpack)
Flarum 使用 Mithril.js 构建 UI。
在 js/package.json 中设置:
{
"private": true,
"name": "@acme/example",
"scripts": {
"dev": "vite",
"build": "vite build"
},
"devDependencies": {
"vite": "^5",
"@vitejs/plugin-react": "^4"
}
}
js/src/forum.js 示例(添加一个欢迎横幅):
import { extend } from 'flarum/common/extend';
import IndexPage from 'flarum/forum/components/IndexPage';
import app from 'flarum/forum/app';
app.initializers.add('acme/example', () => {
extend(IndexPage.prototype, 'hero', function (vnode) {
vnode.children.push(
<div style="background:#f0f0f0; padding: 10px;">
欢迎来到我们的社区!
</div>
);
});
});
执行 npm install && npm run build 生成 js/dist/forum.js。
8.6 发布到 Packagist 与市场
将代码推送至 GitHub,然后登录 Packagist 提交仓库地址,确认 composer.json 包含 name、type:flarum-extension。
随后在 Flarum 官方论坛 Discuss 的“扩展”分类发布介绍帖,就会出现在社区扩展列表中。
九、PHP 深度定制与高级应用
除了插件,你也可以直接使用 PHP 在应用层面进行更灵活的调整。
9.1 事件与监听器
Flarum 使用 Laravel 事件系统。在你的插件 extend.php 中注册监听器:
use Flarum\Extend;
use Flarum\Post\Event\Saving as PostSaving;
return [
(new Extend\Event())
->listen(PostSaving::class, Listeners\FilterPostContent::class),
];
监听器:
namespace Acme\Example\Listeners;
use Flarum\Post\Event\Saving;
class FilterPostContent
{
public function handle(Saving $event)
{
$event->post->content = strip_tags($event->post->content, '<p><a>');
}
}
几乎所有操作(发帖、注册、设置修改)都有对应事件,可在官方文档 Events 列表 查询。
9.2 中间件开发
创建 API 中间件检查自定义请求头:
namespace Acme\Example\Middleware;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
class CustomHeaderMiddleware implements MiddlewareInterface
{
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
if (!$request->hasHeader('X-Custom-Key')) {
return new JsonResponse(['error' => 'Missing header'], 403);
}
return $handler->handle($request);
}
}
在 extend.php 中注册:
(new Extend\Middleware('api'))
->add(Middleware\CustomHeaderMiddleware::class),
9.3 自定义 API 端点
创建一个控制器:
namespace Acme\Example\Api\Controllers;
use Flarum\Api\Controller\AbstractShowController;
use Psr\Http\Message\ServerRequestInterface;
use Tobscure\JsonApi\Document;
class ExampleController extends AbstractShowController
{
protected function data(ServerRequestInterface $request, Document $document)
{
return ['hello' => 'world'];
}
}
注册路由(见 8.3 节),即可通过 GET /api/example 访问。
9.4 Blade 模板与视图覆盖
Flarum 2.x 内置了 Blade 引擎支持。你可以在扩展的 resources/views 目录下放置 .blade.php 文件,然后通过路由或服务返回视图。
例如,覆盖论坛首页:
use Flarum\Extend;
use Flarum\Forum\Content\Index;
use Illuminate\Contracts\View\Factory;
return [
(new Extend\View())
->namespace('acme.example', __DIR__.'/resources/views'),
(new Extend\Frontend('forum'))
->content(function (Index $data, Factory $view) {
return $view->make('acme.example::custom-index', ['title' => '自定义首页']);
}),
];
9.5 服务提供者与容器绑定
如果你需要注册复杂的服务,可以直接在插件中编写 Laravel 服务提供者:
namespace Acme\Example\Providers;
use Flarum\Foundation\AbstractServiceProvider;
use Acme\Example\Services\MyService;
class ExampleServiceProvider extends AbstractServiceProvider
{
public function register()
{
$this->app->singleton(MyService::class, function () {
return new MyService(config('services.my_api_key'));
});
}
}
在 extend.php 中:
return [
// ... 其他扩展器
];
并在 flarum/core 自动发现时合并,或直接通过 App::register()。通常在插件主类中调用 $this->container->register(...)。
十、日常维护与升级
10.1 备份策略
# 备份数据库
mysqldump -u flarum -p flarum > flarum_backup_$(date +%F).sql
# 备份文件(含扩展、资源)
tar -czf flarum_files_$(date +%F).tar.gz /var/www/flarum
建议自动化 cron 任务,并将备份同步至远程存储。
10.2 使用 Composer 安全升级
升级 Flarum 核心及所有扩展前,建议先在测试环境验证。
cd /var/www/flarum
composer update --prefer-dist --no-dev -W
php flarum migrate
php flarum cache:clear
如果是从 1.x 升级到 2.x,请查阅 官方迁移指南,需要手动调整扩展和配置。
10.3 常见故障排查
- 白屏/500 错误:检查
storage/logs/ 下的日志,通常为权限或缺少 PHP 扩展。
- 某些扩展不兼容:运行
composer why-not flarum/core 2.0 查看依赖冲突。
- 前端资源加载失败:清除浏览器缓存,执行
php flarum assets:publish 重新发布资源。
- Worker 模式下内存泄漏:设置最大请求数自动重启:
frankenphp worker --max-requests 500。
十一、总结与学习资源
本指南从服务器环境搭建、FrankenPHP 性能加速、Redis 深度集成,到插件修改、自制扩展乃至 PHP 高级定制,完整覆盖了 Flarum 1.x 至 2.x 的部署开发生态。
通过灵活运用上述技术,你可以构建出高并发、高度定制化且运维友好的社区平台。如果这份教程对你有所帮助,欢迎在你的技术博客或社区中分享,让更多人享受 Flarum + 现代 PHP 的卓越体验!