The Puli Bridge for Symfony

Puli supports a bridge for the Symfony components. The bridge provides a file locator for the Symfony Config component that locates configuration files through a Puli repository. With this locator, you can refer from one configuration file to another by its Puli path:

# routing.yml
_acme_demo:
    resource: /acme/demo-bundle/config/routing.yml

Installation

Important

Before you continue, install the Puli CLI and the Repository Component in your project.

Install the Puli Bridge with Composer:

$ composer require puli/symfony-bridge:^1.0

Configuration

To locate configuration files with Puli, create a new PuliFileLocator and pass it to your file loaders:

use Puli\SymfonyBridge\Config\PuliFileLocator;
use Symfony\Component\Routing\Loader\YamlFileLoader;

$loader = new YamlFileLoader(new PuliFileLocator($repo));

// Locates the file through Puli's repository
$routes = $loader->load('/acme/blog/config/routing.yml');

The PuliFileLocator receives Puli’s ResourceRepository as only argument.

Chained Locators

If you want to use the PuliFileLocator and Symfony’s conventional FileLocator side by side, you can use them both by wrapping them into a FileLocatorChain:

use Puli\SymfonyBridge\Config\PuliFileLocator;
use Puli\SymfonyBridge\Config\FileLocatorChain;
use Puli\SymfonyBridge\Config\ChainableFileLocator;
use Symfony\Component\Routing\Loader\YamlFileLoader;

$locatorChain = new FileLocatorChain(array(
    new PuliFileLocator($repo),
    // Symfony's FileLocator expects a list of paths
    new ChainableFileLocator(array(__DIR__)),
));

$loader = new YamlFileLoader($locatorChain);

// Loads the file from __DIR__/config/routing.yml
$routes = $loader->load('config/routing.yml');

ChainableFileLocator is a simple extension of Symfony’s FileLocator that supports the interface required by the locator chain. Note that this locator must come after the PuliFileLocator in the chain.

Puli also provides a chainable version of the file locator bundled with the Symfony HttpKernel component: Use the ChainableKernelFileLocator if you want to load configuration files from Symfony bundles:

use Puli\SymfonyBridge\Config\PuliFileLocator;
use Puli\SymfonyBridge\Config\FileLocatorChain;
use Puli\SymfonyBridge\Config\ChainableFileLocator;
use Puli\SymfonyBridge\HttpKernel\ChainableKernelFileLocator;

$locatorChain = new FileLocatorChain(array(
    new PuliFileLocator($repo),
    new ChainableKernelFileLocator($httpKernel),
    new ChainableFileLocator(array(__DIR__)),
));

$loader = new YamlUserLoader($locatorChain);

// Loads the file from AcmeBlogBundle
$routes = $loader->load('@AcmeBlogBundle/Resources/config/routing.yml');

Take care again that the ChainableKernelFileLocator comes last in the chain.

Limitations

Due to limitations with Symfony’s FileLocatorInterface, relative file references are not properly supported. Let’s load some routes for example:

$routes = $loader->load('/acme/blog/config/routing-dev.yml');

Assume that this file contains the following import:

# routing-dev.yml
_main:
    resource: routing.yml

What happens if we override this file in the Puli repository?

// Load files from /path/to/blog
$repo->add('/acme/blog', '/path/to/blog');

// Override just routing.yml with a custom file
$repo->add('/acme/blog/config/routing.yml', '/path/to/routing.yml');

// Load the routes
$routes = $loader->load('/acme/blog/config/routing-dev.yml');

// Expected: Routes loaded from
//  - /path/to/blog/config/routing-dev.yml
//  - /path/to/routing.yml

// Actual: Routes loaded from
//  - /path/to/blog/config/routing-dev.yml
//  - /path/to/blog/config/routing.yml

This is a limitation in Symfony and cannot be worked around. For this reason, PuliFileLocator does not support relative file paths.