From 1de6ba5c6735e42b5f462c0b7489bcf172ccdc08 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Wed, 1 Jul 2026 01:33:38 +0900 Subject: feat(php-rpc): query real PHP version and binary for --version Add a minimal shirabe-php-rpc crate that spawns the system PHP as a child process and asks it for runtime information over a Unix domain socket, then use it to fill the `--version` PHP line with the real \PHP_VERSION and \PHP_BINARY instead of fixed placeholder values. See docs/dev/php-rpc.md for the design and scope. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/dev/php-rpc.md | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 docs/dev/php-rpc.md (limited to 'docs/dev/php-rpc.md') diff --git a/docs/dev/php-rpc.md b/docs/dev/php-rpc.md new file mode 100644 index 0000000..9fc6ca3 --- /dev/null +++ b/docs/dev/php-rpc.md @@ -0,0 +1,60 @@ +# PHP RPC + +Composer can require a specific PHP version or loaded extensions, i.e., platform requirements. +To mimic this behavior needs a real PHP runtime. + +This document describes a first design of PHP runtime: a `shirabe-php-rpc` crate that spawns the +system PHP as a child process and asks it for runtime information over a Unix domain socket. + +## Scope + +The crate supports exactly one interaction pattern, and nothing else: + +> Rust calls a named, argument-less PHP function and receives a single fixed-type scalar back. + +- Rust to PHP only. PHP never calls back into Rust. +- No arguments. +- Scalar return values only (string / int / float / bool / null). +- Every failure is ignored: a PHP exception, serialization/deserialization + failure, a missing PHP function, a crashed child, etc. None are handled. + If anything goes wrong, behavior is undefined. +- Windows is unsupported and `panic!`s for now. + +## Locating PHP + +Reuse the existing `PhpExecutableFinder` class to resolve the PHP binary. + +## Transport + +- A Unix domain socket. (No Windows support for now) +- The PHP glue code is a small script written to a temporary file. +- Message frame: `[usize length (little-endian)][payload]`. + - Request payload: the bare PHP function name as raw bytes. + - Response payload: `serialize()` of the function's return value. + +The PHP worker is a single read-eval-respond loop: read a framed function name, +call the matching entry in a fixed dispatch table, send back `serialize($result)`. + +## Global state and public API + +PHP runtime information (e.g., process handle) is held as process-global state +rather than threaded through call sites for now. +The crate exposes plain free functions: + +```rust +shirabe_php_rpc::get_php_version() -> String +``` + +The connection is a process-global `static` (e.g. `OnceLock>`), lazily initialized on +the first call: the first `get_php_version()` spawns the child, performs the handshake, and caches +the connection. Commands that never query PHP never start it. The child lives for the rest of the +process and is left to be reaped at exit (no explicit shutdown message). + +A future revision threads this runtime information through arguments or embeds it in structs; for now +callers just reach for the global getter. + +## Out of scope + +Deferred things: arguments and non-scalar return values, PHP to Rust callbacks +and re-entrancy, object handles / proxies / identity, stub generation, error +propagation, GC / lifecycle, and Windows support. -- cgit v1.3.1