PHP-VIA 将您的 PHP 转换为一个响应式、支持多用户的服务器。无需 JavaScript。无需构建步骤。无需 API 层。只需 PHP 和 OpenSwoole。
实时引擎,用于在 PHP 中使用 Swoole 构建响应式 Web 应用。基于 OpenSwoole 实现异步 PHP,Datastar(RC.8 版本)处理 SSE + DOM 变形,以及 Twig 进行模板渲染,从而实现完全无 JavaScript 的服务端响应式用户界面。
文档与实时示例:
https://via.zweiundeins.gmbh
composer require mbolli/php-via
<?php
require'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 模板:
<div id="counter">
<p>计数: <span data-text="${{ count.id }}">{{ count.int }}</span></p>
<label>步长: <input type="number" data-bind="{{ step.id }}"></label>
<button data-on-click="@post('{{ increment.url }}')">增加</button>
</div>
运行:
php app.php
# 访问 → http://localhost:3000
$name = $c->signal('Alice', 'name');
$name->string(); // 读取当前值
$name->setValue('Bob'); // 修改 → 自动推送更新到浏览器
模板中使用:
<input data-bind="{{ name.id }}">
<span data-text="${{ name.id }}">{{ name.string }}</span>
$save = $c->action(function () use ($c): void {
// 保存逻辑...
$c->sync();
}, 'save');
模板:
<button data-on-click="@post('{{ save.url }}')">保存</button>
作用域 | 共享范围 | 典型场景 |
|---|---|---|
Scope::TAB | 每个浏览器标签页独立(默认) | 个人表单、用户设置 |
Scope::ROUTE | 同一路由下的所有用户 | 共享看板、多人协作编辑 |
Scope::SESSION | 同一会话的所有标签页 | 跨标签页共享购物车 |
Scope::GLOBAL | 全局所有用户 | 系统通知、全局公告 |
自定义(如 "room:lobby") | 指定作用域内的所有连接 | 聊天室、游戏房间 |
支持 Twig 模板文件或内联字符串:
$c->view('dashboard.html.twig', ['user' => $user]);
$app->page('/blog/{year}/{slug}', function (Context $c, string $year, string $slug): void {
// $year 和 $slug 已自动注入
});
可重用、带独立状态的子上下文:
$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) => /* ... */);
$c->broadcast(); // 广播到当前作用域
$app->broadcast(Scope::GLOBAL); // 广播给所有人
$app->broadcast('room:lobby'); // 广播到自定义作用域
访问 https://via.zweiundeins.gmbh/examples 下的所有 demo:
git clone https://github.com/mbolli/php-via.git
cd php-via && composer install
cd 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