
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