Awesome
What is VRZNO?
(/vərəˈzɑːnoʊ/ | vər-ə-ZAH-noh )
VRZNO is a bridge between Javascript & PHP in an extremely nontraditional sense. It lets you pass objects, arrays, callbacks, and classes between PHP & Javascript, as well as scalar values.
Vrzno requires PHP 8.1+
NOTE: The PDO Connectors have been moved into their own extensions:
- CloudFlare D1: https://github.com/seanmorris/pdo-cfd1
- PGLite pgSQL: https://github.com/seanmorris/pdo-pglite
Contents
- new Vrzno
- PHP Functions
- Javascript Object and Classes
- Callbacks
- Arrays
- toString & __toString
- URL fopen
- Limitations
How is this possible?
VRZNO is the first PHP extension built for php-wasm. Once its compiled with PHP, it can be served to any browser and executed client side. It can also run in NodeJS and CloudFlare workers.
https://github.com/seanmorris/php-wasm
new Vrzno
Creates a new Vrzno
object that holds a reference to Javascript's globalThis
object. In the browser this corresponds to window
.
<?php
$window = new Vrzno;
PHP Functions
vrzno_await($promise)
Wait on a Promise-like object to resolve within PHP before proceeding with the script. This will pause execution of PHP in the same way the await
keyword does when used in Javascript.
<?php
$window = new Vrzno;
$response = vrzno_await($window->fetch('https://api.weather.gov/gridpoints/TOP/40,74/forecast'));
$json = vrzno_await($response->json());
var_dump($json);
vrzno_import($module_url)
Import a javascript library asynchronously. This is the PHP equivalent of Javascript's dynamic import()
.
See a demo: https://codepen.io/SeanMorris227/pen/LYqNNrE
<?php
$import = vrzno_import('https://cdn.jsdelivr.net/npm/@observablehq/plot@0.6/+esm');
vrzno_env($name)
Takes a string, and returns a value passed into the PHP Object's constructor.
For example, if you invoke PhpNode
like this in Javascript:
import { PhpNode } from './PhpNode.mjs';
import gi from 'node-gtk';
const Gtk = gi.require('Gtk', '3.0');
const WebKit2 = gi.require('WebKit2');
const php = new PhpNode({Gtk, gi, WebKit2});
You can access those values in PHP like so:
<?php
$gi = vrzno_env('gi');
$Gtk = vrzno_env('Gtk');
$WebKit2 = vrzno_env('WebKit2');
vrzno_target($vrzno)
Get the targetId
as an integer from a Vrzno
object.
Javascript Object and Classes
Classes and objects are fully marshalled through Vrzno. You can use Javascript classes by bringing them in like any other object, and things should work as normal.
For example, we'll pull in the Javascript Date
object and call the static function now()
on it:
<?php
$window = new Vrzno;
$Date = $window->Date;
var_dump($Date->now());
Since the Date
object is also technically a class in Javascript, we can create a new instance in PHP with the new
operator, and call the instance method, toISOString
:
<?php
$window = new Vrzno;
$Date = $window->Date;
$d = new $Date;
var_dump($d, $d->toISOString());
Callbacks
Functions are fully marshalled as well. In this example, we'll create an anonymous PHP callback that calls the Javascript function window.alert()
, and then pass the PHP callback to Javascript's setTimeout()
function, which will call it after 1 second.
As you can see, functions from both languages are crossing the boundary here:
<?php
$window = new Vrzno;
$window->setTimeout( fn() => $window->alert('Done!'), 1000);
Since we can create new objects from classes, we can even use this to create promises:
<?php
$window = new Vrzno;
$Promise = $window->Promise;
$p = new $Promise(function($accept, $reject) use ($window) {
$window->setTimeout( fn() => $accept('Pass.'), 1000);
});
$p->then(var_dump(...))->catch(var_dump(...));
Arrays
Both string and integer properties are fully marshalled for both PHP and JS arrays.
toString & __toString
The Javascript .toString
method and the PHP ->__toString
method are proxied to each other to ensure proper stringification in both languages.
URL fopen
Vrzno implements a fetch-backend for the http
and https
stream wrappers, which respects the allow_url_fopen
ini directive.
<?php
var_dump( file_get_contents('https://jsonplaceholder.typicode.com/users') );
You can use the stream_context_create
like normal to modify the request:
<?php
$opts = ['http' => [
'method' => 'POST',
'content' => json_encode(['value' => 'foobar'])
]];
$context = stream_context_create($opts);
var_dump(
file_get_contents('https://jsonplaceholder.typicode.com/users', false, $context)
);
Currently the following context options are implemented:
- method
- content
- header
- ignore_errors
More information on HTTP context options can be found here:
https://www.php.net/manual/en/context.http.php
Limitations
-
The Javascript object model places properties and methods in the same namespace. PHP however uses separate namespaces for properties and methods. This means an object in PHP can have a property
$x->y
as well as a method$x->y()
. However if a Javascript object has a methodx.y()
, then the propertyx.y
must resolve to the same callback as the method.Currently, when a PHP object is passed into a Javascript execution environment, method names take precedence over property names. This means if a PHP object has both a method
$x->y()
, and a property$x->y
, then the property will be inaccessible from Javascript. -
PHP Classes are not yet accessible from Javascript. I.e. there is no way to pass a class out of PHP and call
new
on it from Javascript. -
Static methods are not yet proxied.