概述
PHP-VIA 将您的 PHP 转换为一个响应式、支持多用户的服务器。无需 JavaScript。无需构建步骤。无需 API 层。只需 PHP 和 OpenSwoole。
实时引擎,用于在 PHP 中使用 Swoole 构建响应式 Web 应用。基于 OpenSwoole 实现异步 PHP,Datastar(RC.8 版本)处理 SSE + DOM 变形,以及 Twig 进行模板渲染,从而实现完全无 JavaScript 的服务端响应式用户界面。
文档与实时示例:
https://via.zweiundeins.gmbh
为什么选择 php-via?
- 无需编写任何 JavaScript — Datastar 负责客户端的响应性、SSE 连接和 DOM 变形
- 使用 Twig 模板 — 熟悉且功能强大的服务端模板引擎
- 零构建步骤 — 无需转译、打包、node_modules 或前端构建工具
- 作用域状态管理 — 支持 TAB、ROUTE、SESSION、GLOBAL 以及自定义作用域,精确控制状态共享范围
- 单一高效 SSE 流 — 结合 Brotli 压缩,传输开销极低
系统要求
安装
composer require mbolli/php-via
快速上手
<?phprequire'vendor/autoload.php';use Mbolli\PhpVia\Via;use Mbolli\PhpVia\Config;use Mbolli\PhpVia\Context;$config = new Config();$config->withTemplateDir(__DIR__ . '/templates');$app = new Via($config);$app->page('/', function(Context $c): void{ $count = $c->signal(0, 'count'); $step = $c->signal(1, 'step'); $increment = $c->action(function()use($count, $step, $c): void{ $count->setValue($count->int() + $step->int()); $c->syncSignals(); }, 'increment'); $c->view('counter.html.twig', ['count' => $count,'step' => $step,'increment' => $increment, ]);});$app->start();
对应的 counter.html.twig 模板:
<divid="counter"><p>计数: <spandata-text="${{ count.id }}">{{ count.int }}</span></p><label>步长: <inputtype="number"data-bind="{{ step.id }}"></label><buttondata-on-click="@post('{{ increment.url }}')">增加</button></div>
运行:
php app.php# 访问 → http://localhost:3000
信号(Signals)—— 服务端与客户端实时同步的响应式状态
$name = $c->signal('Alice', 'name');$name->string(); // 读取当前值$name->setValue('Bob'); // 修改 → 自动推送更新到浏览器
模板中使用:
<input data-bind="{{ name.id }}"><span data-text="${{ name.id }}">{{ name.string }}</span>
动作(Actions)—— 客户端事件触发的服务端函数
$save = $c->action(function()use($c): void{// 保存逻辑... $c->sync();}, 'save');
模板:
<button data-on-click="@post('{{ save.url }}')">保存</button>
作用域(Scopes)—— 控制状态共享范围和广播目标
视图(Views)
支持 Twig 模板文件或内联字符串:
$c->view('dashboard.html.twig', ['user' => $user]);
路径参数(自动注入)
$app->page('/blog/{year}/{slug}', function(Context $c, string $year, string $slug): void{// $year 和 $slug 已自动注入});
组件(Components)
可重用、带独立状态的子上下文:
$a = $c->component($counterWidget, 'a');$b = $c->component($counterWidget, 'b');
生命周期钩子
$c->onDisconnect(fn() => /* 清理资源 */);$c->setInterval(fn() => $c->sync(), 2000); // 每 2 秒同步一次$app->onClientConnect(fn(string $id) => /* ... */);
广播(Broadcasting)
$c->broadcast(); // 广播到当前作用域$app->broadcast(Scope::GLOBAL); // 广播给所有人$app->broadcast('room:lobby'); // 广播到自定义作用域
工作原理(简要流程)
- 浏览器请求页面 → 服务端渲染完整 HTML 并建立 SSE 流
- 用户交互(点击等) → Datastar 通过 POST 发送信号值 + 动作 ID
- 服务端通过 SSE 推送 HTML 补丁 + 信号更新
- Datastar 在客户端应用 DOM 变形 → UI 无刷新实时更新
实时示例(均可在线体验并查看源码)
访问 https://via.zweiundeins.gmbh/examples 下的所有 demo:
开发环境搭建
git clone https://github.com/mbolli/php-via.gitcd php-via && composer installcd website && php app.php # 启动网站和示例(端口 3000)vendor/bin/pest # 运行测试(85 个测试用例,240+ 断言)composer phpstan # 静态分析(级别 6)composer cs-fix # 修复代码风格
部署建议
使用单一 OpenSwoole 进程 + 反向代理(如 Caddy)。参考仓库中的 deploy/ 目录,包含 systemd 服务文件和 Caddy 配置示例。
典型架构:
浏览器 → Caddy (负责 TLS + Brotli 压缩) → OpenSwoole :3000