Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

860 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

logo

Ray.Compiler

Scrutinizer Code Quality codecov Type Coverage Continuous Integration

Pre-compile Ray.Di bindings to PHP code for maximum performance. The compiled injector runs faster than the standard injector by avoiding runtime reflection and binding resolution.

Installation

composer require ray/compiler

Usage

Ray.Compiler provides two main components:

  1. Compiler: Compiles Ray.Di bindings into PHP code.
  2. CompiledInjector: High-performance injector that executes pre-compiled code.

Basic Usage

Pre-compile your dependencies:

use Ray\Compiler\Compiler;

$compiler = new Compiler();
// Compile Ray.Di bindings to PHP files
$compiler->compile(
    $module,    // AbstractModule: Your application's module
    $scriptDir  // string: Directory path where compiled PHP files will be generated
);

Use the compiled injector:

use Ray\Compiler\CompiledInjector;

$injector = new CompiledInjector($scriptDir);
$instance = $injector->getInstance(YourInterface::class);

Compiler Integration

Create a compile script:

try {
    $scripts = (new Compiler())->compile(
        new AppModule(),
        __DIR__ . '/di'
    );
    printf("Compiled %d files.\n", count($scripts));
} catch (CompileException $e) {
    fprintf(STDERR, "Compilation failed: %s\n", $e->getMessage());
    exit(1);
}

Add compile script to your composer.json:

{
    "scripts": {
        "post-install-cmd": ["php bin/compile.php"]
    }
}

Warming Up Singletons on Coroutine Runtime Servers

Compilation also generates singletons.json, a list of singleton bindings that can be instantiated without caller context. CompiledInjector::warmup() instantiates them all eagerly:

$injector = new CompiledInjector($scriptDir);
$injector->warmup(); // call once at worker startup

In a long-lived or coroutine runtime (Swoole, OpenSwoole), lazy singleton initialization can race when construction yields, producing duplicate instances. Calling warmup() before concurrent request handling begins removes that window.

This is only needed for runtimes that handle requests concurrently within one process. Standard PHP-FPM workers normally process one request at a time, so no warm-up is required there.

An injection-point-dependent singleton would capture whichever consumer constructs it first, making the shared instance order-dependent. Such bindings must use prototype scope or remove the injection-point dependency.

  • Compilation throws SingletonRequiresInjectionPoint for an injection-point-dependent singleton.
  • warmup() throws SingletonsFileNotFound if singletons.json is missing. Recompile with the current Ray.Compiler version.

Version Control

Compiled DI code is considered an environment-specific build artifact and should not be committed to version control. This approach ensures that your repository remains clean and build artifacts do not cause merge conflicts or unexpected behavior across different environments.

Add the compile directory to your .gitignore:

/tmp/di/

Documentation

About

A dependency injection compiler for Ray.Di

Topics

Resources

Contributing

Security policy

Stars

5 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages