An open API service indexing awesome lists of open source software.

https://github.com/thecodingmachine/yaco

YACO (Yet Another COmpiler) is a PHP tool that generates a PHP container based on entry definitions.
https://github.com/thecodingmachine/yaco

Last synced: 9 months ago
JSON representation

YACO (Yet Another COmpiler) is a PHP tool that generates a PHP container based on entry definitions.

Awesome Lists containing this project

README

          

[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/thecodingmachine/yaco/badges/quality-score.png?b=1.2)](https://scrutinizer-ci.com/g/thecodingmachine/yaco/?branch=1.2)
[![Build Status](https://travis-ci.org/thecodingmachine/yaco.svg?branch=1.2)](https://travis-ci.org/thecodingmachine/yaco)
[![Coverage Status](https://coveralls.io/repos/thecodingmachine/yaco/badge.svg?branch=1.2&service=github)](https://coveralls.io/github/thecodingmachine/yaco?branch=1.2)

# 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*](https://github.com/container-interop/definition-interop/).

## Installation

You can install this package through Composer:

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

The packages adheres to the [SemVer](http://semver.org/) 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*](https://github.com/container-interop/definition-interop/)) and to transform those
into a PHP class that implements the [`ContainerInterface`](https://github.com/container-interop/container-interop/)

```php
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:

```php
$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](https://github.com/mnapoli/assembly).

Here is a complete sample using Yaco and Assembly:

**Compile phase:**
```php
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:**
```php
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*](https://github.com/container-interop/service-provider).

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

Here is a sample:

```php
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:

```php
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](https://github.com/container-interop/container-interop/blob/master/docs/Delegate-lookup.md) 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:

```php
// $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:

```php
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.