Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Puli: PHP's Next Package Revolution

Puli: PHP's Next Package Revolution

The development of Composer packages is thriving. But much effort is duplicated, creating "bundles", "modules" or "plugins" for different frameworks. Why not join forces and create universal packages together?

Puli, a new PHP toolkit, is a step to make this possible. With Puli, Composer packages become "intelligent". Enable any package in any project (Plug 'n Play) simply by running "composer install" - independent of your framework. Are you ready for the future of PHP?

Bernhard Schussek

January 29, 2016
Tweet

More Decks by Bernhard Schussek

Other Decks in Programming

Transcript

  1. Bernhard Schussek · webmozart.io 1/119
    https://commons.wikimedia.org/wiki/File:View_from_Volcano_Pacaya,_Guatemala.jpg (CC BY-SA 4.0)
    PHP's Next Package Revolution
    Bernhard Schussek (@webmozart) · PHPBenelux 2016, Antwerp

    View Slide

  2. Bernhard Schussek · webmozart.io 2/119
    Shcusek Schuseck
    Shusek
    Schuhsek
    Shuhseck
    Shushek
    Shuseck
    Shusec
    Shushek
    Shushek
    Shushec
    Sussek
    Shussec
    Schußeck
    Scusek
    Shußec
    Schuhsec
    Shußec
    Schushek
    Schusheck
    Not:
    Bernard
    Bernhart
    Bernardt
    Bernharth
    Also Wrong:
    Schusseck
    Schusek
    Shusseck
    Scussek
    Bernhard Schussek

    View Slide

  3. Bernhard Schussek · webmozart.io 3/119
    @webmozart

    View Slide

  4. Bernhard Schussek · webmozart.io 4/119
    Bernhard Schussek
    Symfony Core Developer
    since 2009

    View Slide

  5. Bernhard Schussek · webmozart.io 5/119
    Bernhard Schussek
    Symfony FIG Representative
    since 2013

    View Slide

  6. Bernhard Schussek · webmozart.io 6/119
    Bernhard Schussek
    Puli Core Developer
    since 2014

    View Slide

  7. Bernhard Schussek · webmozart.io 7/119
    Bernhard Schussek
    PHP Trainer and Coach
    Symfony
    Architecture
    Coding Practices
    webmozart.io

    View Slide

  8. Bernhard Schussek · webmozart.io 8/119
    Puli?

    View Slide

  9. Bernhard Schussek · webmozart.io 9/119
    https://www.flickr.com/photos/puliarfanita/7167723539 (CC BY 2.0)

    View Slide

  10. Bernhard Schussek · webmozart.io 10/119
    https://www.flickr.com/photos/puliarfanita/6117985856 (CC BY 2.0)

    View Slide

  11. Bernhard Schussek · webmozart.io 11/119
    https://www.flickr.com/photos/karenhorton/4931092112 (CC BY-NC 2.0)

    View Slide

  12. Bernhard Schussek · webmozart.io 12/119
    https://www.flickr.com/photos/picturesfromwords/9539461080 (CC BY-NC 2.0)

    View Slide

  13. Bernhard Schussek · webmozart.io 13/119
    Puli is a Module System
    for PHP

    View Slide

  14. Bernhard Schussek · webmozart.io 14/119
    Bundles
    Packages
    Modules
    Modules




    View Slide

  15. Bernhard Schussek · webmozart.io 15/119
    Modules

    View Slide

  16. Bernhard Schussek · webmozart.io 16/119
    What is a Puli Module?

    View Slide

  17. Bernhard Schussek · webmozart.io 17/119
    PHP Library ✔

    View Slide

  18. Bernhard Schussek · webmozart.io 18/119
    Symfony Bundle✔

    View Slide

  19. Bernhard Schussek · webmozart.io 19/119
    Your Application✔

    View Slide

  20. Bernhard Schussek · webmozart.io 20/119
    PHP Code
    Resource Files
    puli.json
    Module Configuration
    composer.json
    Installation Instructions
    Puli Module

    View Slide

  21. Bernhard Schussek · webmozart.io 21/119
    Puli is Not the
    Next Composer

    View Slide

  22. Bernhard Schussek · webmozart.io 22/119
    Composer Installs Packages and
    Resolves their Dependencies

    View Slide

  23. Bernhard Schussek · webmozart.io 23/119
    PHP Code
    Resource Files
    puli.json
    Module Configuration
    composer.json
    Installation Instructions
    Autoloading PHP Classes
    Module
    Batman\Blog\BlogController

    View Slide

  24. Bernhard Schussek · webmozart.io 24/119
    Puli Integrates Modules
    and Your Application

    View Slide

  25. Bernhard Schussek · webmozart.io 25/119
    Your Application

    View Slide

  26. Bernhard Schussek · webmozart.io 26/119
    Puli Has 3 Target Audiences

    View Slide

  27. Bernhard Schussek · webmozart.io 27/119
    Framework Developers

    View Slide

  28. Bernhard Schussek · webmozart.io 28/119
    Library/Module Developers

    View Slide

  29. Bernhard Schussek · webmozart.io 29/119
    Application Developers

    View Slide

  30. Bernhard Schussek · webmozart.io 30/119
    Puli for Framework Developers

    View Slide

  31. Bernhard Schussek · webmozart.io 31/119
    Stop Inventing Module Systems

    View Slide

  32. Bernhard Schussek · webmozart.io 32/119
    Packagist
    Libraries
    Symfony
    Bundles
    Laravel
    Packages
    Drupal
    Modules Silex
    Providers

    View Slide

  33. Bernhard Schussek · webmozart.io 33/119
    For Symfony Developers
    Libraries
    Symfony
    Bundles
    Laravel
    Packages
    Drupal
    Modules Silex
    Providers

    View Slide

  34. Bernhard Schussek · webmozart.io 34/119
    For Drupal Developers
    Libraries
    Symfony
    Bundles
    Laravel
    Packages
    Drupal
    Modules Silex
    Providers

    View Slide

  35. Bernhard Schussek · webmozart.io 35/119
    Vanilla PHP Projects
    Libraries
    Symfony
    Bundles
    Laravel
    Packages
    Drupal
    Modules Silex
    Providers

    View Slide

  36. Bernhard Schussek · webmozart.io 36/119
    High Community
    Fragmentation

    View Slide

  37. Bernhard Schussek · webmozart.io 37/119
    Puli Reduces Your Code Base

    View Slide

  38. Bernhard Schussek · webmozart.io 38/119
    Puli Modules Reach a
    Larger Target Audience

    View Slide

  39. Bernhard Schussek · webmozart.io 39/119
    Puli for Library/Module
    Developers

    View Slide

  40. Bernhard Schussek · webmozart.io 40/119
    PHP Code
    Resource Files
    Provide/Use Services
    by Interface
    Http\Client\HttpClient
    =
    Guzzle\GuzzleClient
    React\HttpClient\ReactClient
    Http\Curl\CurlClient

    Module
    PHP Code
    Resource Files
    Module

    View Slide

  41. Bernhard Schussek · webmozart.io 41/119
    Module
    Module
    PHP Code
    Resource Files
    PHP Code
    Resource Files
    Provide/Use Resources
    by Type
    thor/translations-yml
    =
    path/to/trans/messages.en.yml
    path/to/trans/messages.de.yml
    path/to/trans/messages.fr.yml

    View Slide

  42. Bernhard Schussek · webmozart.io 42/119
    PHP Code
    Resource Files
    Access Resources
    by Puli Path
    /batman/blog/config.yml
    =
    path/to/module/res/config.yml
    Module

    View Slide

  43. Bernhard Schussek · webmozart.io 43/119
    Accessing Resources

    View Slide

  44. Bernhard Schussek · webmozart.io 44/119
    $twig->render('/batman/blog/views/index.html.twig');
    Accessing Resources

    View Slide

  45. Bernhard Schussek · webmozart.io 45/119
    Puli Path
    /batman/blog/views/index.html.twig

    View Slide

  46. Bernhard Schussek · webmozart.io 46/119
    batman/blog
    /res
    /batman/blog/views/index.html.twig
    Path Prefix
    Physical Location
    Path Mapping

    View Slide

  47. Bernhard Schussek · webmozart.io 47/119
    /res/views/index.html.twig
    Resolved Path
    /batman/blog/views/index.html.twig
    Physical Location
    Path Prefix
    batman/blog

    View Slide

  48. Bernhard Schussek · webmozart.io 48/119
    puli.json
    {
    "resources": {
    "/batman/blog": "res"
    }
    }
    preview

    View Slide

  49. Bernhard Schussek · webmozart.io 49/119
    {% extend '/batman/blog/views/layout.html.twig' %}
    {% include '../sidebar.html.twig' %}
    {% use 'macros.html.twig' %}
    Tool Integration: Twig

    View Slide

  50. Bernhard Schussek · webmozart.io 50/119
    Accessing Resources
    in Other Modules

    View Slide

  51. Bernhard Schussek · webmozart.io 51/119
    {% extend '/thor/theme/views/layout.html.twig' %}
    Resource Access
    composer.json
    {
    "require": {
    "thor/theme": "^1.0"
    }
    }

    View Slide

  52. Bernhard Schussek · webmozart.io 52/119
    Overriding Resources
    in Other Modules

    View Slide

  53. Bernhard Schussek · webmozart.io 53/119
    batman/blog
    page.html.twig
    thor/theme
    ✔ Within Your Control ✘ Outside Your Control
    layout.html.twig
    {% extends %}
    How to customize?

    View Slide

  54. Bernhard Schussek · webmozart.io 54/119
    page.html.twig
    ✔ Within Your Control ✘ Outside Your Control
    layout.html.twig
    {% extends %}
    layout.html.twig
    copy
    batman/blog thor/theme

    View Slide

  55. Bernhard Schussek · webmozart.io 55/119
    post.html.twig
    ✔ Within Your Control ✘ Outside Your Control
    layout.html.twig
    {% extends %}
    layout.html.twig
    overrides
    batman/blog thor/theme

    View Slide

  56. Bernhard Schussek · webmozart.io 56/119
    thor/theme
    batman/blog
    puli.json
    /thor/theme → res
    puli.json
    /batman/blog → res

    View Slide

  57. Bernhard Schussek · webmozart.io 57/119
    puli.json
    /thor/theme res

    /batman/blog res

    puli.json
    /thor/theme → res/theme
    override
    thor/theme
    batman/blog

    View Slide

  58. Bernhard Schussek · webmozart.io 58/119
    puli.json
    {
    "resources": {
    "/batman/blog": "res",
    "/thor/theme": "res/theme"
    },
    "override": ["thor/theme"]
    }
    Overridden Packages
    preview

    View Slide

  59. Bernhard Schussek · webmozart.io 59/119
    Override Graph

    View Slide

  60. Bernhard Schussek · webmozart.io 60/119
    Accessing Different Versions
    $versions = $repo->getVersions('/thor/theme/config.yml')
    // res/theme/config.yml
    echo $versions->getCurrent()->getBody();
    // vendor/thor/theme/res/config.yml
    echo $versions->getFirst()->getBody();

    View Slide

  61. Bernhard Schussek · webmozart.io 61/119
    Use Services
    Provided by Other Modules

    View Slide

  62. Bernhard Schussek · webmozart.io 62/119
    react/http-client
    http/discovery
    Users Providers
    Http\Client\HttpClient
    Define Binding Type
    ReactClient

    View Slide

  63. Bernhard Schussek · webmozart.io 63/119
    Users Providers
    Discover
    ReactClient
    HttpDiscovery
    react/http-client
    http/discovery Http\Client\HttpClient

    View Slide

  64. Bernhard Schussek · webmozart.io 64/119
    puli.json
    {
    "define": {
    "Http\\Client\\HttpClient": "class"
    }
    }
    preview

    View Slide

  65. Bernhard Schussek · webmozart.io 65/119
    Service Discovery
    $bindings = $discovery->findBindings(HttpClient::class);
    foreach ($bindings as $binding) {
    $className = $binding->getClassName();
    $httpClient = new $className();
    // ...
    }

    View Slide

  66. Bernhard Schussek · webmozart.io 66/119
    Provide Services
    to Other Modules

    View Slide

  67. Bernhard Schussek · webmozart.io 67/119
    Users Providers
    Provide
    ReactClient
    react/http-client
    http/discovery Http\Client\HttpClient

    View Slide

  68. Bernhard Schussek · webmozart.io 68/119
    puli.json
    {
    "provide": {
    "React\\Client": "Http\\Client\\HttpClient"
    }
    }
    preview

    View Slide

  69. Bernhard Schussek · webmozart.io 69/119
    Use Resources
    Provided by Other Modules

    View Slide

  70. Bernhard Schussek · webmozart.io 70/119
    Users Providers
    messages.en.yml
    thor/translations-yml
    Define Binding Type
    batman/blog
    thor/translator

    View Slide

  71. Bernhard Schussek · webmozart.io 71/119
    Users Providers
    Find Resources
    MessageLoader
    thor/translator thor/translations-yml
    messages.en.yml
    batman/blog

    View Slide

  72. Bernhard Schussek · webmozart.io 72/119
    puli.json
    {
    "define": {
    "thor/translations-yml": "resource"
    }
    }
    preview

    View Slide

  73. Bernhard Schussek · webmozart.io 73/119
    Resource Discovery
    $bindings = $discovery->findBindings('thor/translations-
    foreach ($bindings as $binding) {
    foreach ($binding->getResources() as $resource) {
    $yaml = $routing->getBody();
    // ...
    }
    }

    View Slide

  74. Bernhard Schussek · webmozart.io 74/119
    Provide Resources
    to Other Modules

    View Slide

  75. Bernhard Schussek · webmozart.io 75/119
    Users Providers
    Provide
    thor/translator thor/translations-yml
    messages.en.yml
    batman/blog

    View Slide

  76. Bernhard Schussek · webmozart.io 76/119
    puli.json
    {
    "provide": {
    "/batman/blog/trans/*.yml":
    "thor/translations-yml"
    }
    }
    preview

    View Slide

  77. Bernhard Schussek · webmozart.io 77/119
    Puli Provides Everything You
    Need to Integrate your Module
    with Other Modules

    View Slide

  78. Bernhard Schussek · webmozart.io 78/119
    Puli for Application Developers

    View Slide

  79. Bernhard Schussek · webmozart.io 79/119
    Your Code
    Your Application
    Old-School Development

    View Slide

  80. Bernhard Schussek · webmozart.io 80/119
    Package Reuse
    Your Code
    3rd-Party Code
    Your Application

    View Slide

  81. Bernhard Schussek · webmozart.io 81/119
    Your Application
    Your Code
    3rd-Party Code
    Your Application
    More Efficient

    View Slide

  82. Bernhard Schussek · webmozart.io 82/119
    Reuse of Existing
    High-Quality 3rd-Party Code
    is Key to Success

    View Slide

  83. Bernhard Schussek · webmozart.io 83/119
    Libraries
    Symfony
    Bundles
    Laravel
    Packages
    Drupal
    Modules Silex
    Providers
    Without Puli

    View Slide

  84. Bernhard Schussek · webmozart.io 84/119
    Modules
    With Puli

    View Slide

  85. Bernhard Schussek · webmozart.io 85/119
    $loader = new TranslationLoader(array(
    __DIR__.'/res/trans/messages.en.yml',
    __DIR__.'/res/trans/messages.de.yml',
    __DIR__.'/vendor/batman/blog/trans/blog.en.yml',
    __DIR__.'/vendor/batman/blog/trans/blog.de.yml',
    __DIR__.'/vendor/batman/blog/trans/blog.fr.yml',
    // ...
    ));
    $translator = new Translator($loader);
    Application Bootstrapping Without Puli

    View Slide

  86. Bernhard Schussek · webmozart.io 86/119
    Lots of Work Necessary
    to Wire Up Libraries

    View Slide

  87. Bernhard Schussek · webmozart.io 87/119
    Worst Case: Quadratic Effort
    Science Talk for "A Lot"

    View Slide

  88. Bernhard Schussek · webmozart.io 88/119
    $loader = new PuliLoader($discovery);
    $translator = new Translator($loader);
    Application Bootstrapping With Puli

    View Slide

  89. Bernhard Schussek · webmozart.io 89/119
    (almost) Plug 'n Play

    View Slide

  90. Bernhard Schussek · webmozart.io 90/119
    PHP Code
    Resource Files
    Provide/Use Services
    by Interface
    Http\Client\HttpClient
    =
    Guzzle\GuzzleClient
    React\HttpClient\ReactClient
    Http\Curl\CurlClient

    Module
    PHP Code
    Resource Files
    Module

    View Slide

  91. Bernhard Schussek · webmozart.io 91/119
    Module
    Module
    PHP Code
    Resource Files
    PHP Code
    Resource Files
    Use Resources
    by Type
    symfony/translations-yml
    =
    path/to/trans/messages.en.yml
    path/to/trans/messages.de.yml
    path/to/trans/messages.fr.yml

    View Slide

  92. Bernhard Schussek · webmozart.io 92/119
    PHP Code
    Resource Files
    Access Resources
    by Puli Path
    /batman/blog/config.yml
    =
    path/to/module/res/config.yml
    Module

    View Slide

  93. Bernhard Schussek · webmozart.io 93/119
    PHP Code
    Resource Files
    Publish Assets
    public/
    css/
    style.min.css
    images/
    background.png
    Module
    Document Root
    PHP Code
    Resource Files
    Module

    View Slide

  94. Bernhard Schussek · webmozart.io 94/119
    Repository JSON URL Generator
    JSON
    Gulp/Grunt
    +
    puli.js
    Alternative 1: JavaScript

    View Slide

  95. Bernhard Schussek · webmozart.io 95/119
    Gulpfile.js
    var gulp = require('gulp'),
    puli = require('puli').load('.puli/path-mappings.jso
    urls = require('puli-urls');
    gulp.task('vendor', function () {
    puli.src('/batman/blog/public/**/*')
    .pipe(urls())
    .dest('res/public/blog')
    .pipe(urls.mapping())
    .dest('.puli/urls.json');
    });
    preview

    View Slide

  96. Bernhard Schussek · webmozart.io 96/119
    Repository URL Generator
    JSON
    Alternative 2: Asset Component
    Asset

    View Slide

  97. Bernhard Schussek · webmozart.io 97/119
    puli.json
    {
    "config": {
    "assets.root-dir": "res/public"
    },
    "publish": {
    "/batman/blog/public": "res/public/blog/"
    },
    "urls": {
    "*": "/{$path}",
    "*.jpg":
    "{$scheme}://my.cdn.com/{$path}"
    }
    }
    preview

    View Slide

  98. Bernhard Schussek · webmozart.io 98/119
    Resource Installation
    $ puli publish
    Installing /batman/blog/public in at res/public/blog/
    via symlink...
    Done!
    preview

    View Slide

  99. Bernhard Schussek · webmozart.io 99/119
    (in the Module)

    View Slide

  100. Bernhard Schussek · webmozart.io 100/119
    URLs in HTML Templates
    preview

    View Slide

  101. Bernhard Schussek · webmozart.io 101/119
    body {
    background-image: asset_url("/res/public/bg.png");
    // Relative paths
    background-image: asset_url("bg.png");
    }
    CSS Post-Processing
    preview

    View Slide

  102. Bernhard Schussek · webmozart.io 102/119
    https://commons.wikimedia.org/wiki/File:View_from_Volcano_Pacaya,_Guatemala.jpg (CC BY-SA 4.0)
    PHP Community of Modules

    View Slide

  103. Bernhard Schussek · webmozart.io 103/119
    batman/blog
    Request Response
    FIG and PSR-7

    View Slide

  104. Bernhard Schussek · webmozart.io 104/119
    Router Controller
    /hello/world
    PSR for Routing?

    View Slide

  105. Bernhard Schussek · webmozart.io 105/119
    services.xml
    php-fig/di-config symfony/routing
    my/application
    DI Container
    PSR for DI Configuration?

    View Slide

  106. Bernhard Schussek · webmozart.io 106/119
    $container = new Container($discovery);
    $router = $container->get(Router::class);
    $controller = $router->getController('/hello/world');
    $response = $controller->handle($request);
    PHP Applications with Puli

    View Slide

  107. Bernhard Schussek · webmozart.io 107/119
    Current Status

    View Slide

  108. Bernhard Schussek · webmozart.io 108/119
    1.0.0-beta10

    View Slide

  109. Bernhard Schussek · webmozart.io 109/119
    Stable Release in 2016

    View Slide

  110. Bernhard Schussek · webmozart.io 110/119
    Extensive Documentation
    docs.puli.io

    View Slide

  111. Bernhard Schussek · webmozart.io 111/119
    Successfully in Production

    View Slide

  112. Bernhard Schussek · webmozart.io 112/119
    Working Symfony Bundle
    puli/symfony-bundle

    View Slide

  113. Bernhard Schussek · webmozart.io 113/119
    Symfony Distribution
    puli/symfony-puli-edition

    View Slide

  114. Bernhard Schussek · webmozart.io 114/119
    Potential Projects Supporting
    Puli Out-of-the-Box
    Drupal?

    View Slide

  115. Bernhard Schussek · webmozart.io 115/119
    Feedback Wanted
    puli.io
    Twitter: @PuliPHP
    Chat: gitter.im/puli/issues

    View Slide

  116. Bernhard Schussek · webmozart.io 116/119
    Get Involved!
    github.com/puli/issues

    View Slide

  117. Bernhard Schussek · webmozart.io 117/119
    @webmozart

    View Slide

  118. Bernhard Schussek · webmozart.io 118/119
    joind.in/talk/9785b

    View Slide

  119. Bernhard Schussek · webmozart.io 119/119
    Questions?
    Questions?
    Bernhard Schussek
    Bernhard Schussek
    @webmozart
    @webmozart
    https://www.flickr.com/photos/puliarfanita/7167723539 (CC BY 2.0)
    webmozart.io

    View Slide