Skip to main content

publicloadPHPRuntime

Callable


  • Loads the PHP runtime with the given arguments and data dependencies.

    This function handles the entire PHP initialization pipeline. In particular, it:

    • Instantiates the Emscripten PHP module
    • Wires it together with the data dependencies and loads them
    • Ensures is all happens in a correct order
    • Waits until the entire loading sequence is finished

    Basic usage:

     const phpLoaderModule = await getPHPLoaderModule("7.4");
    const php = await loadPHPRuntime( phpLoaderModule );
    console.log(php.run(`<?php echo "Hello, world!"; `));
    // { stdout: ArrayBuffer containing the string "Hello, world!", stderr: [''], exitCode: 0 }

    The PHP loader module:

    In the basic usage example, phpLoaderModule is not a vanilla Emscripten module. Instead, it’s an ESM module that wraps the regular Emscripten output and adds some extra functionality. It’s generated by the Dockerfile shipped with this repo. Here’s the API it provides:

    // php.wasm size in bytes:
    export const dependenciesTotalSize = 5644199;

    // php.wasm filename:
    export const dependencyFilename = 'php.wasm';

    // Run Emscripten's generated module:
    export default function(jsEnv, emscriptenModuleArgs) {}

    PHP Filesystem:

    Once initialized, the PHP has its own filesystem separate from the project files. It’s provided by Emscripten and uses its FS library.

    The API exposed to you via the PHP class is succinct and abstracts certain unintuitive parts of low-level filesystem interactions.

    Here’s how to use it:

    // Recursively create a /var/www directory
    php.mkdirTree('/var/www');

    console.log(php.fileExists('/var/www/file.txt'));
    // false

    php.writeFile('/var/www/file.txt', 'Hello from the filesystem!');

    console.log(php.fileExists('/var/www/file.txt'));
    // true

    console.log(php.readFile('/var/www/file.txt'));
    // "Hello from the filesystem!

    // Delete the file:
    php.unlink('/var/www/file.txt');

    For more details consult the PHP class directly.

    Data dependencies:

    Using existing PHP packages by manually recreating them file-by-file would be quite inconvenient. Fortunately, Emscripten provides a “data dependencies” feature.

    Data dependencies consist of a dependency.data file and a dependency.js loader and can be packaged with the file_packager.py tool. This project requires wrapping the Emscripten-generated dependency.js file in an ES module as follows:

    1. Prepend export default function(emscriptenPHPModule) {';
    2. Prepend export const dependencyFilename = '<DATA FILE NAME>';
    3. Prepend export const dependenciesTotalSize = <DATA FILE SIZE>;
    4. Append }

    Be sure to use the --export-name="emscriptenPHPModule" file_packager.py option.

    You want the final output to look as follows:

    export const dependenciesTotalSize = 5644199;
    export const dependencyFilename = 'dependency.data';
    export default function(emscriptenPHPModule) {
    // Emscripten-generated code:
    var Module = typeof emscriptenPHPModule !== 'undefined' ? emscriptenPHPModule : {};
    // ... the rest of it ...
    }

    Such a constructions enables loading the dependency.js as an ES Module using import("/dependency.js").

    Once it’s ready, you can load PHP and your data dependencies as follows:

     const [phpLoaderModule, wordPressLoaderModule] = await Promise.all([
    getPHPLoaderModule("7.4"),
    import("/wp.js")
    ]);
    const php = await loadPHPRuntime(phpLoaderModule, {}, [wordPressLoaderModule]);

    Parameters

    Returns Promise<number>

    Loaded runtime id.