Working with WebAssembly and PHP: Advanced Level

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: Why WebAssembly in PHP?

In the world of web development, PHP remains one of the most popular languages for the server side. However, when it comes to high-performance computing — image processing, complex mathematics, on-the-fly code compilation, or using code written in C/C++/Rust — native PHP often falls short. This is where WebAssembly (WASM) comes to the rescue.

WebAssembly is a binary instruction format that executes at near-native speed. Traditionally associated with browsers, modern runtimes (Wasmer, Wasmtime) allow running WASM modules on the server, including from PHP. In this article, we will explore advanced techniques for integrating WebAssembly into PHP applications: from environment setup to creating complex modules and performance optimization.



1. Environment Setup: Wasmer and PHP Extension

To work with WebAssembly in PHP, we need a special extension. The most mature and documented option is wasmer-php.

Installing Wasmer

First, install the Wasmer runtime itself:

curl https://get.wasmer.io -sSfL | sh# Or via package manager (macOS/Linux)brew install wasmer

Installing the PHP Extension

The extension can be installed via PECL or compiled manually:

# Via PECLsudo pecl install wasmer

# Or build from source (for advanced users)git clone https://github.com/wasmerio/wasmer-php.gitcd wasmer-phpphpize./configuremakesudo make install

After installation, add extension=wasmer.so to your php.ini and restart the server. Verify it works:

<?phpecho class_exists('\\\\Wasmer\\\\Instance') ? 'WASM Ready' : 'Not installed';?>


2. Loading and Executing a WASM Module from PHP

Suppose we have a compiled module math.wasm that exports a function add(a, b) (written in Rust or C). Let's load it and call it from PHP.

Basic Example: Calling a Function

<?phpuse Wasmer\\Instance;use Wasmer\\Module;use Wasmer\\Memory;use Wasmer\\Value;

// 1. Load the module$wasm_bytes = file_get_contents(__DIR__ . '/math.wasm');$module = new Module($wasm_bytes);

// 2. Create an instance$instance = new Instance($module);

// 3. Get the exported function$add = $instance->exports->get('add');

// 4. Call with arguments$result = $add(5, 7);

echo "Result: " . $result->toInt(); // Will output: 12?>

Important: WASM functions work with simple types (i32, i64, f32, f64). For complex structures (strings, arrays), passing via linear memory (Memory) is required.



Working with Memory: Passing Strings

If your WASM module expects a string, you need to write it into shared memory and pass a pointer:

<?php// Assume the WASM function 'greet' takes a pointer to a string (i32)$memory = $instance->exports->get('memory');$greet = $instance->exports->get('greet');

// Write the string to memory (with a null byte at the end)$input = "Hello from PHP!";$ptr = 100; // arbitrary address, must be free$memory->write($ptr, $input . "\\0");

// Call the function$result_ptr = $greet($ptr);

// Read the result from memory$output = '';$offset = $result_ptr->toInt();while (($byte = $memory->read($offset, 1)) !== "\\0") { $output .= $byte; $offset++;}echo $output; // Greeting from WASM?>


3. Building Your Own WASM Module (Rust → PHP)

For maximum performance, Rust is often used. Let's look at a minimal example.

Rust Code

Create a new project:

cargo new --lib wasm_mathcd wasm_math

File Cargo.toml:

[lib]crate-type = ["cdylib"]

[depend

Blogs

Book Recommendations