thecodingmachine / yaco
YACO (Yet Another COmpiler) is a PHP tool that generates a PHP container based on entry definitions.
Requires
Requires (Dev)
- container-interop/definition-interop-tests: dev-master
- mnapoli/assembly: dev-master
- phpunit/phpunit: ~4.5
- satooshi/php-coveralls: dev-master
README
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.