YACO (Yet Another COmpiler) is a PHP tool that generates a PHP container based on entry definitions.
PHP
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
src
tests
.gitignore
.travis.yml
LICENSE
README.md
composer.json
phpunit.xml.dist

README.md

Scrutinizer Code Quality Build Status Coverage Status

YACO - Yet another compiler

YACO (Yet Another COmpiler) is a PHP tool that generates a PHP container based on entry definitions. It is fully compatible with entry definitions from definition-interop.

Installation

You can install this package through Composer:

{
    "require": {
        "thecodingmachine/yaco": "^1.2"
    }
}

The packages adheres to the SemVer specification, and there will be full backward compatibility between minor versions.

Usage

This package contains a Compiler class. The goal of this class is to take a number of "entry definitions" (as defined in definition-interop) and to transform those into a PHP class that implements the ContainerInterface

use TheCodingMachine\Yaco\Compiler;

$compiler = new Compiler();

// ...

foreach ($definitions as $identifier => $definition) {
    /* @var $definition Interop\Container\Definition\DefinitionInterface */
    $compiler->addDefinition($identifier, $definition);
}

// Let's dump the code of the My\Container class.
file_put_contents("Container.php", $compiler->compile("My\\Container"));

Now, you can instantiate your container using this code:

$container = new My\Container();

$service = $container->get('a_service');

Note: Yaco is consuming container definitions (implementing Interop\Container\Definition\DefinitionInterface). Out of the box, Yaco does not provide any classes implementing this interface. However, you can find such classes in a package like mnapoli/assembly.

Here is a complete sample using Yaco and Assembly:

Compile phase:

use TheCodingMachine\Yaco\Compiler;
use function \Assembly\object;
use function \Assembly\alias;

$compiler = new Compiler();

$loggerDefinition = object('MyLogger')
    ->setConstructorArguments('warning')
    ->addMethodCall('setDebug', true);

$compiler->addDefinition('logger', $loggerDefinition);

// Let's dump the code of the My\Container class.
file_put_contents("Container.php", $compiler->compile("My\\Container"));

Usage:

require_once('Container.php');

$container = new My\Container();
$logger = $container->get('logger');

Note: the My\Container class implements the Interop\Container\ContainerInterface. Therefore, it can be used with any framework compatible with container-interop.

Service provider support

This package supports container agnostic service providers as defined in container-interop/service-provider.

To register service providers, you must pass to the compiler a TheCodingMachine\ServiceProvider\Registry object.

Here is a sample:

use TheCodingMachine\Yaco\Compiler;
use TheCodingMachine\ServiceProvider\Registry;

$registry = new Registry([
    MyServiceProvider::class
]);

// The registry is passed as first argument to the compiler. 
$compiler = new Compiler($registry);

// Let's dump the code of the My\Container class.
file_put_contents("MyContainer.php", $compiler->compile("MyContainer"));

Important! When you want to use the compiled container, you have to pass a registry containing the same service providers, in the same order.

Below is an instantiation of the container generated by the code above:

use TheCodingMachine\ServiceProvider\Registry;

$registry = new Registry([
    MyServiceProvider::class
]);

// The registry is passed as first argument to the compiler. 
$container = new MyContainer($registry);

$service = $container->get('a_service');

Miscellaneous

Delegate lookup support

Containers generated by Yaco support the "delegate lookup" feature of container-interop.

If you pass a container as the second argument to the generated container, all dependency lookups will be done on the passed container rather than on the generated container.

Here is a sample:

// $rootContainer is a composite container from the acclimate library
$rootContainer = new Acclimate\CompositeContainer();

$myContainer = new MyContainer(null, $rootContainer);

$rootContainer->addContainer($myContainer);

Definition providers

You can directly register a definition provider using the register method:

use TheCodingMachine\Yaco\Compiler;

$compiler = new Compiler();

// ...

$compiler->register($definitionProvider);

// Let's dump the code of the My\Container class.
file_put_contents("Container.php", $compiler->compile("My\\Container"));

Definition providers are classes implementing the Interop\Container\Definition\DefinitionProviderInterface. They provide a list of container definitions to be compiled by the compiler.