Real PHP · on the metal

Real PHP, running bare-metal on microcontrollers.

php-baremetal runs the official PHP interpreter on microcontrollers. It is not a reimplementation, a language subset, or a transpiler: the upstream Zend engine from php.net is cross-compiled for the chip and executes your index.php opcode by opcode — the same way it would behind a web server.

$ phpflash init my-project
The idea

The same interpreter, on a $5 chip.

The PHP source tree is vendored unchanged; the only modifications are separate patches applied at build time, for the handful of places where a bare-metal RTOS differs from a Unix host. Hand the same script to this engine or to a desktop php and you get the same output — because underneath it is the same interpreter.

8.3–8.5

PHP versions

2

Chip families

0

Lines re-implemented

8–32 MB

PSRAM

What you get

A full PHP runtime, not a toy.

The complete Zend engine and standard library, real extensions, and the applications that ride on top — all cross-compiled to the chip's own CPU and run through the official embed SAPI.

01

The unmodified engine

Namespaces, classes, traits, enums, closures, generators, match, exceptions, typed properties and attributes — plus strings, arrays, JSON, PCRE, hashing, SPL, Reflection and the CSPRNG.

02

Native, not emulation

PHP's C is built with the chip's own cross-compiler and runs on the board's CPU through the official embed SAPI. No interpreter-on-an-interpreter.

03

Silicon-agnostic by design

Runs today on the ESP32-P4 (RISC-V) and ESP32-S3 (Xtensa) — but a new chip family is a directory, not an engine change. The port targets microcontrollers, not one vendor, so more silicon can follow.

04

Real extensions

date, mbstring, filter, ctype, session, PDO SQLite, full OpenSSL 3.0 with an HTTPS client, and Zend OPcache (no JIT, statically linked).

05

Composer & frameworks

Composer works with unmodified packages from Packagist. With the web-server model and OPcache, the ESP32-P4 serves stock Laravel and Symfony pages over HTTP.

06

Storage, your way

Run the source from a microSD (swap the card to change the program, no rebuild) or embedded in the flash image. The partition layout is generated per build.

07

State across requests

A reboot-persistent store_* (NVS) and a volatile in-RAM mem_*, so the shared-nothing web-server model can still hand data from one request to the next.

08

Extend it in C

Drop native code under firmware/exts/ and it compiles into the firmware — no fork required. A GPIO extension drives pins straight from PHP.

09

One tool for all of it

phpflash — a single static binary that scaffolds, builds, flashes and monitors a project, and identifies a connected board. It reads what the firmware can build, so it only ever offers real choices.

10

WiFi, from PHP

Scan for networks, join one, or bring up your own access point — straight from PHP. Even the radio-less ESP32-P4 gets WiFi through an on-board companion, so a board can create its own network and serve its pages over it, no router in sight.

Write PHP

Arduino-style, in the language you already know.

A setup()/loop() sketch drives the board; a built-in gpio extension talks to the pins. This is the whole program that blinks an LED.

php index.php
<?php
// runs once at boot
function setup(): void {
    gpio_mode(2, GPIO_OUTPUT);
}

// runs forever, like an Arduino loop
function loop(): void {
    gpio_write(2, 1); delay(500);
    gpio_write(2, 0); delay(500);
}
An LED on GPIO2 blinking on and off every 500 ms, driven from PHP.

Live on the board

Ways to run it

A firmware sketch, or a real web server.

One line in the project config picks how PHP runs on the board. Drive hardware in an Arduino-style loop, or stand up an HTTP server that runs your script per request — the same engine, two execution models today, with a third on the way.

type = "init-loop"

Firmware sketch

setup() runs once at boot, then loop($tick) repeats forever — driven from C so the watchdog stays fed. The way to blink an LED, read a sensor, or drive a display.

Arduino-style GPIO · I²C · SPI runs continuously
type = "web-server"

HTTP web server

A built-in server runs your index.php per request and returns the response over HTTP. Stock Laravel and Symfony pages served straight off the chip, through a per-request SAPI with OPcache.

per-request SAPI routing · sessions Laravel · Symfony
type = "event-driven"

Event-driven

Coming soon

Wake on a hardware event — a GPIO interrupt, a timer, an incoming packet — run a PHP handler, then go back to sleep. The low-power model for battery devices that stay idle most of the time.

interrupt-driven low power sleep between events
Two pieces

The firmware and the tool.

php-baremetal is two repositories: the PHP port itself, and a single command-line tool that scaffolds, builds, flashes and monitors a project without touching ESP-IDF by hand.

Get started

Flash your first board in minutes.

Install the tool, scaffold a project, write your index.php, and flash it. Your PHP is running on the chip.