Puli

Universal Packages system for PHP

Michaël Garrez

02/2016

Composer

Composer is a dependency management

solution for PHP

It allows a project to specify which packages and version it depends on

Packagist

Packagist (official composer packages repository) contains multiple types of packages :

 

  • Symfony Bundles
  • Laravel Packages
  • Silex providers
  • Simple libraries
  • ...

Packages

At the moment, PHP Frameworks have their own package management system.

Packages

Puli provides a framework agnostic packages management system.

 

A Puli package is a PHP directory that contains a puli.json file.

Resource repository

Puli provides a framework agnostic way to access resources in your project and in your composer packages.

For Puli, resources are all type of files except PHP files.

Resource repository

Take an example with Symfony

<?php

...


public function blogIndexAction()
{
    return $this->render('blog/index.html.twig');
}

app/Resources/views/blog/index.html.twig

Symfony provides its own way to load templates from the application / bundles

Resource repository

How do you load a twig template which is in composer package ?

<?php

...


public function blogIndexAction()
{
    return $this->render(__DIR__ . ' ????? ');
}

vendor/test/test-library/template/test.html.twig

Resource repository

Puli provides a Repository system which provides makes resources accessible through a Puli path.

 

A repository is an implementation of 

Puli's ResourceRepository interface.

Resource repository

Same example using Puli :

<?php

...


public function blogIndexAction()
{
    $factoryClass = PULI_FACTORY_CLASS;
    $factory = new $factoryClass();

    $repo = $factory->createRepository();

    return $this->render($repo->get('/test/template/test.html.twig')->getBody());
}

vendor/test/test-library/template/test.html.twig

php puli.phar map /test /

Puli-Cli

Resource repository

Puli composer plugin

Puli composer plugin builds a Repository and a Discovery based on the puli.json files from all your composer packages

(including your project).

Natively Puli will build a Repository and a Discovery based on your project puli.json file.

Resource Discovery

Puli provides a way to connect Composer packages that consume resources with other packages that provides resources

Resource Discovery

Let's take as example a project where you have among others 2 composer packages :

  • thor/translator Translation composer package
  • batman/blog Blog management system

Resource Discovery

Your batman/blog package provides several translation files :

  • messages.en.yml
  • messages.fr.yml

Your thor/translator package provides a way to inject YAML translation files :

<?php

$translator = new Translator([
    'vendor/batman/blog/translations/messages.fr.yml',
    'vendor/batman/blog/translations/messages.en.yml'
]);

This works but require you to work to plug them together.

Plus, this is hardly scalable.

Resource Discovery

Puli provides a system of binding to resolve this issue.

 

The owner of batman/blog will bind his translations files to thor/translations and thor/translator will fetch them :

Resource Discovery

All the owner of batman/blog has to do is to bind his

translation files to the correct binding :

php puli.phar bind /translations/*.yml thor/translations

This will update the puli.json file contained in the package.

Resource Discovery

The owner of thor/translator has to require an 

instance of ResourceDiscovery to be provided :

<?php

class Translator
{
    public function __construct(ResourceDiscovery $discovery)
    {
        $this->discovery = $discovery;
    }

    protected function getTranslationFiles()
    {
        $bindings = $this->discovery->findByType('thor/translations');

        foreach ($bindings as $binding) {
            foreach ($binding->getResources() as $resource) {
                $this->translationFiles[] = $resource->getPath();
            }
        }
    }
}

Resource Discovery

As a user all you have to do is to provide a ResourceDiscovery

for your Translator package :

<?php

$factoryClass = PULI_FACTORY_CLASS;
$factory = new $factoryClass();

$repo = $factory->createRepository();
$discovery = $factory->createDiscovery($repo);

$translator = new Translator($discovery);

Resource Discovery

You can also bind classes :

<?php

$plugins = [];

foreach ($discovery->findBindings('test/plugin') as $binding) {
    $className = $binding->getClassName();
    $plugin    = new $className($discovery);
		
    $plugins[] = $plugin;
}

Puli.io

By Babacooll

Puli.io

  • 1,136