claviron-php-embed 0.2.0-alpha.17

Managed in-process PHP execution, application hosting, and native extensions for Claviron
docs.rs failed to build claviron-php-embed-0.2.0-alpha.17
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.

claviron-php-embed

Managed in-process PHP execution through Claviron's SAPI and OS/ZTS threads.

This crate links the PHP engine into the host through ext-php-rs. Rust owns admission, thread capacity, execution generations, and drain; PHP executes the application. No FastCGI socket or external php command sits between an HTTP request and this engine.

Use claviron::ephp with the facade's php_embed feature alongside the desired server composition. Edge can mix PHP with native services and other applications; Runner surrounds a single application owner without virtual-host selection.

Execution models

  • Script requests: a reusable thread runs PHP request startup, the selected script, and request shutdown for each HTTP request. Reusing the thread does not retain that request's PHP objects. Ordinary Laravel front-controller execution does not require an Octane loop.
  • Persistent applications: a named boot script remains alive, receives explicit request/event messages, and returns explicit responses. The PHP adapter owns framework request construction and cleanup between messages.
  • Tasks: the optional TaskService integration runs PHP programs on separate execution threads. Task timing, placement, cancellation, and supervision belong to the task system, not an HTTP application pool.

All share one process SAPI, extension table, and INI selection. Persistent instances and request threads have separate Zend contexts, but they are not security or crash-isolation boundaries. Use separate processes where that is required; FastCGI is the external-FPM alternative.

Register an embedded runtime

Configured registration uses ephp::register(state) and the optional php.yaml under the runtime configuration directory. A missing file retains the configured one-thread request-pool default. An explicitly registered runtime is reused by that convenience entry instead of being replaced.

For configuration-free composition, a callback can declare a request pool:

use claviron::{
    ephp::{PhpEmbedRuntime, RequestPool},
    runtime::{AppState, registry},
};

fn register_php(state: &AppState) -> registry::Result<()> {
    PhpEmbedRuntime::builder()
        .request_pool(RequestPool::fixed(2))
        .build()
        .register(state)
}

This declares two execution threads; it does not start PHP or mount an HTTP route. With the facade's Server, pass it to Server::with_definitions(register_php) so the explicit definition precedes built-in defaults; ordinary Server::register callbacks run after those defaults. Select server and php_embed for these APIs, then compose the ingress and PHP route separately. An empty builder declares no request pool. Register all programs and host extensions before native startup; a second independent embedded runtime in the same process is not supported.

PhpEmbedRuntime is the shared provider. PhpScriptService and PhpApplicationService own separate runnable generations and drain. Application controllers expose those owners through the common application manager instead of copying their live state.

Configuration and capacity

The startup document separates engine INI settings, lifecycle policy, sapi request-pool policy, named applications, management, events, launch, and optional metrics. sapi: null disables the script request pool, not the shared engine capabilities or named applications.

Request and application pools support fixed or elastic capacity, idle retention, and optional idle-instance rotation. Capacity is local to each serving process. HTTP route policy controls body limits, queue wait, and response handling; application execution limits and instance replacement are separate contracts. An accepted request is not automatically replayed when an instance fails.

The resolved php.yaml execution plan is startup configuration, not a live Congif reload owner. Service restarts reuse it; changing INI, definitions, or the frozen startup plan requires process replacement. Execution environment files have a separate observation path through Dotenw: script requests pin a route-owned snapshot, while persistent owners can replace their own execution after valid environment changes. That does not make arbitrary engine configuration live.

Persistent application protocol

An application enters the explicit claviron_application_receive() / claviron_application_respond() protocol after boot. Receive also carries application events and returns null when admission ends. The response contract is buffered and preserves binary bodies and repeated headers.

This is not transparent SAPI reuse: echo, header(), $_POST, $_FILES, and php://input are not automatically remapped for each received message. The framework adapter supplies that request boundary and its cleanup. The next request is not admitted to an instance until PHP re-enters receive after its post-response work. Streaming and protocol upgrades are not supplied by this buffered application contract.

Native capabilities and environment

extension::PhpEmbedExtension contributes compiled-in functions, classes, enums, per-thread setup, and optional Zend observers. Contributions are frozen before SAPI startup, with metadata owned for the process lifetime. This is not PHP's dynamic extension loader, and registration is not a per-request action.

Optional bridges expose configured cache stores, database leases, authentication, log channels, events, and invocations. A compiled symbol does not establish that its backing host service is prepared. Authentication projects a verified native request identity rather than trusting a PHP-supplied credential. Native PHP objects and Zend values do not cross execution-thread lifetimes.

Declared environment values and trusted HTTP/TLS metadata reach PHP through the execution context. Named environment access is not the same as dumping the process environment; putenv changes remain execution-local rather than changing other applications' libc environment.

Evaluation, console, and lifecycle

evaluate::PhpEvaluator executes trusted source bytes and returns owned PhpValue data without an HTTP listener or service pool. Objects, resources, cycles, and excessive nesting are rejected; evaluation is not a sandbox. console::PhpConsole runs a caller-owned command with terminal streams and an exit status. Both share native startup with hosted execution; declare INI and extensions before the first use and offload their blocking calls appropriately.

Shutdown stops admission and drains owned work. A missing grace deadline means indefinite drain. Guest execution budgets and cooperative cancellation remain distinct from graceful policy; interrupting PHP does not guarantee termination of arbitrary blocking native extension code. One service's control grants no authority over another service's execution.

OPcache invalidation interception is enabled by default in this implementation; APCu interception is opt-in. When configured, invalidation signals use the existing bounded fleet event transport and apply at PHP execution boundaries. They do not replicate cache values or guarantee acknowledged delivery. They are not a substitute for the shared Claviron cache store.

Requirements and optional capabilities

Embedding requires a compatible PHP ZTS build with embed headers/library and the ext-php-rs native toolchain. PHP and PHP_CONFIG must describe the same installation; use stable toolchain paths across builds. A CLI-only PHP binary does not by itself provide the embedding library.

Facade features such as auth, cache, postgres, mysql, tasks, log-pipeline, and metrics extend an already selected embedded runtime. The engine remains framework-neutral. The companion Composer package is claviron/sapi; Laravel layers its own adapters above it.

Status and license

Part of Claviron's alpha development series; APIs may change. This README describes the current source tree, not the placeholder package on crates.io.

The Rust crate is licensed under either MIT or Apache-2.0, at your option. The companion Composer package declares its license in its manifest.