Interop
Interop
Phasis bridges PHP and JavaScript values in place, without serialization. The same array referenced from PHP and JS is one object in memory — mutations in one language are visible from the other. The same goes for callables (PHP Closure ↔ JS function), Maps, and most other value types.
This section covers the rules.
Pages
- Values — primitive and object conversion: numbers, strings, BigInt, booleans, null/undefined, arrays, objects, Date, RegExp. Identity-preserving vs copying conversions.
- Host functions — bind PHP
callableas JS function via$engine->setGlobal(). Argument unwrapping rules, return-value wrapping, exception bridging. - Shared objects — pass a PHP object into JS, mutate from JS, observe changes from PHP. Reference semantics, property visibility, lifetime.
- Fetch transport — swap the default
ext-curlHTTP backend for Guzzle, Symfony HttpClient, a mock, or a deny-all. Plus the policy hook for allowlisting, header injection, and per-tenant binding. - Cookie jar — mount a
get(url)/set(url, header)jar to persist cookies across fetches. In-memory, Symfony BrowserKit, or a JS-sideMap. - AbortController patterns — timeout, race, propagation,
AbortSignal.any/.timeout, and how a custom PHP transport polls the signal mid-transfer.
Quick example
$engine = new Phasis\Engine();
// 1. Bind a PHP callable as a JS function
$engine->setGlobal('greet', fn (string $name) => "Hello, $name!");
echo $engine->eval('greet("world")'); // → Hello, world!
// 2. Share a PHP object — mutation in JS is visible from PHP
class Counter { public int $value = 0; }
$counter = new Counter();
$engine->setGlobal('counter', $counter);
$engine->eval('counter.value += 5');
echo $counter->value; // → 5
// 3. Call a JS function from PHP
$engine->eval('function add(a, b) { return a + b; }');
echo $engine->call('add', 2, 3); // → 5See also
- API reference — the full
Phasis\Enginesurface. - Web APIs — Web Platform Pack and Fetch Pack live on top of the same interop layer.