Vrzno

Vrzno requires PHP 8.1+

VRZNO is the first PHP extension built for php-wasm. Once it’s compiled with PHP, it can be served to any browser and executed client side. It can also run in NodeJS and CloudFlare workers.

How is this possible?

VRZNO is a bridge between Javascript and PHP in an extremely nontraditional sense. It lets you pass objects, arrays, callbacks, and classes between PHP & Javascript, as well as scalar values. ## 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/[email protected]/+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 using the new operator, and call the instance method, toISOString:

<?php
$window = new Vrzno;
$Date = $window->Date;

$d = new $Date;

var_dump($d, $d->toISOString());

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;

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 method x.y(), then the property x.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 from PHP.