PHP's ease, with safety built in.
PHX keeps what made PHP productive — $variables, HTML templates, routing by file, save and reload — and makes the compiler responsible for type safety, safe output and speed.
<?phx
import std.http.request;
import std.db.Database;
$name = request()->query("author") ?? "ann"; // ?string, narrowed by ??
$db = Database::open("data/blog.db");
$posts = $db->query(sql"SELECT title FROM posts WHERE author = {$name}");
?>
<h1>Posts by <?= $name ?></h1>
<ul>
<?phx foreach ($posts as $post): ?>
<li><?= $post->string("title") ?? "untitled" ?></li>
<?phx endforeach; ?>
</ul>Typed, without ceremony
A variable's type comes from its first assignment. No implicit conversions, strict ==, null safety with ?T, ?-> and ??, generics, interfaces and enums.
Escaping that knows where it is
Output is escaped automatically, and the compiler tracks the HTML around every <?= ?>. A string at the start of a URL, inside <script> or in an event handler is a compile error.
SQL without injection
Queries are sql"..." literals. Interpolated values always become bound parameters — there is no way to build SQL text from a string.
Locked down by default
A Content-Security-Policy with automatic nonces, CSRF checks, server-side sessions, rate limiting, and file access only where phx.toml allows it.
Fast
A typed register VM, a Cranelift JIT for numeric code, and a signed bytecode cache. fib(30) runs in about 7 ms.
Everything in one command
phx serve, test, fmt, lsp, install and migrate (from PHP), plus a VS Code extension.
Mistakes are compile errors
Escaping alone cannot make a URL safe: javascript:alert(1) contains nothing to escape. PHX knows the value lands at the start of an href and refuses to compile until it is checked.
<?phx
import std.http.request;
$site = request()->query("site") ?? "";
?>
<a href="<?= $site ?>">Website</a>
error: a URL attribute cannot start with an unchecked value
--> profile.phx:5:14
|
5 | <a href="<?= $site ?>">Website</a>
| ^^^^^
= note: use `safe_url($url)`, which only allows http(s), mailto, tel and relative URLs (blocks `javascript:`); `escape()` does not make a URL safe
1 error found
Download
PHX 0.2.0 for Windows, Linux and macOS. Unpack the archive and put phx on your PATH.
| Platform | Archive |
|---|---|
| Windows x64 | phx-0.2.0-x86_64-pc-windows-msvc.zip |
| Linux x64 | phx-0.2.0-x86_64-unknown-linux-gnu.tar.gz |
| macOS (Apple Silicon) | phx-0.2.0-aarch64-apple-darwin.tar.gz |
| macOS (Intel) | phx-0.2.0-x86_64-apple-darwin.tar.gz |
Check the archive against SHA256SUMS from the same release, then run it:
sha256sum -c SHA256SUMS --ignore-missing
tar -xzf phx-0.2.0-x86_64-unknown-linux-gnu.tar.gz
./phx-0.2.0-x86_64-unknown-linux-gnu/phx --version
./phx-0.2.0-x86_64-unknown-linux-gnu/phx serve mysite # http://127.0.0.1:8080
Or build from source with a recent stable Rust and a C compiler: cargo build --release.
For VS Code, install the extension from editors/vscode for highlighting and live diagnostics.
Security
PHX has been through three security audits, each followed by fixes and regression tests. Read the audit report. To report a vulnerability, email security@phx-lang.org.