This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
@platformatic/php-node is a Node.js native addon that embeds PHP within the same process as Node.js, enabling seamless communication without network overhead. It's built with Rust using NAPI-RS for safe and performant bindings.
# Build release version
npm run build
# Build debug version (faster compilation, includes debug symbols)
npm run build:debug
# Run all tests
npm test
# Run specific test file
npx ava __test__/headers.spec.mjs
# Lint JavaScript code
npm run lint
# Create universal binary (macOS)
npm run universal
# Version bump
npm run version# Build with proper rpath for linking libphp
RUSTFLAGS="-C link-args=-Wl,-rpath,\$ORIGIN" npm run build
# Run Rust tests
cargo test
# Run binary directly
cargo run- Rust (
/src): Single-crate implementation- PHP embedding and SAPI implementation
- NAPI bindings exposing Rust to Node.js (when
napi-supportfeature is enabled) - Binary target for standalone testing (
src/main.rs) - Library target for NAPI usage (
src/lib.rs)
- JavaScript: Node.js API layer (
index.js,index.d.ts) - PHP: Embedded runtime via libphp.{so,dylib}
-
PHP Class (
index.js): Main entry point for creating PHP environments- Manages rewriter rules for URL routing
- Handles request/response lifecycle
- Supports both sync and async request handling
-
Request/Response Model: Web standards-compatible implementation
Requestclass with headers, body, methodResponseclass with status, headers, bodyHeadersclass with case-insensitive header handling
-
Rewriter System: Apache mod_rewrite-like functionality
- Conditional rules with regex patterns
- Environment variable support
- Rule chaining with [L], [R], [C] flags
-
SAPI Implementation: Custom PHP SAPI in Rust
- Direct Zend API usage for performance
- Thread-safe with TSRM support
- Reusable PHP environments across requests
-
System Dependencies Required:
- Linux:
libssl-dev libcurl4-openssl-dev libxml2-dev libsqlite3-dev libonig-dev re2c libpq5 - macOS:
openssl@3 curl sqlite libxml2 oniguruma postgresql@16
- Linux:
-
PHP Runtime: Must have
libphp.so(Linux) orlibphp.dylib(macOS) in project root -
Testing: AVA framework with 3-minute timeout due to PHP startup overhead
-
Type Definitions:
index.d.tsis auto-generated by NAPI-RS - do not edit manually -
Platform Support: x64 Linux, x64/arm64 macOS (pre-built binaries in
/npm) -
Recent Architecture Changes:
- Consolidated from multi-crate workspace to single crate named
php - NAPI support is now feature-gated with
napi-supportfeature - Binary target supports both library (
rlib) and dynamic library (cdylib) outputs
- Consolidated from multi-crate workspace to single crate named
- Implement in Rust under
src/with#[cfg(feature = "napi-support")] - Use
#[napi]attributes for exposed functions/classes - Run
npm run buildto regenerate TypeScript definitions
- Core logic in
src/sapi.rsandsrc/embed.rs - JavaScript wrapper in
index.js - Request/response types from
http-handlercrate
- Check INTERNALS.md for PHP embedding details
- Use
npm run build:debugfor debug symbols - PHP superglobals set via
SG(...)macro in Rust code
The rewriter system supports Apache mod_rewrite-like functionality:
- Create rules with conditions (header, host, method, path, query)
- Apply rewriters (header, href, method, path, query, status)
- Use flags like [L] (last), [R] (redirect), [C] (chain)
- Example:
new Rewriter([{ conditions: [{type: 'path', args: ['^/old/(.*)$']}], rewriters: [{type: 'path', args: ['^/old/(.*)$', '/new/$1']}] }])
index.js: Main JavaScript API, exports PHP, Request, Response, Headers, Rewriter classessrc/lib.rs: Library entry point, exports core types and NAPI bindingssrc/main.rs: Binary entry point for standalone testingsrc/embed.rs: CoreEmbedtype for handling PHP requestssrc/sapi.rs: PHP SAPI implementation (low-level PHP integration)src/runtime.rs: NAPI runtime implementation (whennapi-supportfeature enabled)__test__/*.spec.mjs: Test files for each component