Getting Started
php-via is a real-time engine for PHP. It brings server-centric reactivity to PHP using OpenSwoole as the runtime and Datastar as the client-side reactive layer.
The result: you write PHP, the browser updates in real-time. No JavaScript. No build step. No API layer to maintain.
Requirements
- PHP 8.4+
- OpenSwoole extension
- Composer
Installation
composer require mbolli/php-via
Your first app
Create app.php in a new directory. Here's the most minimal
php-via application — a counter:
<?php
require __DIR__ . '/vendor/autoload.php';
use Mbolli\PhpVia\Config;
use Mbolli\PhpVia\Context;
use Mbolli\PhpVia\Via;
$app = new Via(new Config());
$app->page('/', function (Context $c): void {
// 1. Declare a reactive signal
$count = $c->signal(0);
// 2. Define an action (server-side event handler)
$increment = $c->action(function () use ($count): void {
$count->setValue($count->int() + 1);
});
// 3. Render a view (the framework pushes updates via SSE)
$c->view(fn() => <<<HTML
<p>Count: <strong data-text="$count">{$count->int()}</strong></p>
<button data-on:click="@post('{$increment->url()}')"}>+1</button>
HTML);
});
$app->start();
php app.php
# ⚡ Server started on http://0.0.0.0:3000
Open localhost:3000 in your browser and click the button. Then open a second tab — the counter stays independent. That's TAB scope, the default.
<?php
require __DIR__ . '/vendor/autoload.php';
use Mbolli\PhpVia\Config;
use Mbolli\PhpVia\Context;
use Mbolli\PhpVia\Via;
$app = new Via(new Config());
$app->page('/', function (Context $c): void {
$count = $c->signal(0);
$increment = $c->action(
fn() => $count->setValue($count->int() + 1)
);
$c->view(fn() => <<<HTML
<p>Count: <strong data-text="$count">
{$count->int()}
</strong></p>
<button data-on:click="@post('{$increment->url()}')">
+1
</button>
HTML);
});
$app->start(); Count: 0
This is your counter. Only you see it.
How it works
When the page loads, php-via:
- Executes your page handler to build the initial HTML
- Injects signal state into the page as JSON
<meta data-signals> - Datastar establishes an SSE connection to
/_sse - When you click a button, Datastar POSTs to
/_action/{id} - Your action callback runs, signals update, view re-renders
- The patch arrives via SSE and Datastar morphs the DOM
No page reload. No flash. Just seamless updates.
Next steps
- Signals — reactive state and two-way binding
- Scopes — share state across users with one line
- Components — compose complex pages from isolated sub-contexts
- Examples — live, editable examples of every feature
Professional support
Need help with architecture, migration, or scaling a server-centric PHP application? zwei und eins gmbh — the company behind php-via — offers audits and implementation support.