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 ;
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.