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

Composing a Better Phuture

Composing a Better Phuture

Composer is both a dependency management and autoloader generation tool for PHP. This presentation highlights how and why we use Composer.

Jeremy Lindblom

October 02, 2015
Tweet

More Decks by Jeremy Lindblom

Other Decks in Programming

Transcript

  1. Composing
    a Better
    Phuture
    by Jeremy Lindblom
    @jeremeamia

    View Slide

  2. ● Composer
    ● Packages
    ● SemVer
    ● Autoloading
    ● PSRs
    Composing a Better Phuture

    View Slide

  3. But first, a history lesson.
    (Don’t worry, we’ll only cover a few years)

    View Slide

  4. PHP is “mostly dead”
    2008

    View Slide

  5. is “mostly dead”
    2008
    2009
    PHP 5.3.0 is released

    View Slide

  6. ♥ for Git/GitHub grow
    2010

    View Slide

  7. PSR-0 & Composer
    2011

    View Slide

  8. HaPHPy 20th Birthday
    2015

    View Slide

  9. View Slide

  10. View Slide

  11. 1. Dependency Manager
    2. Autoloader Generator
    What is Composer?

    View Slide

  12. 1. Dependency Manager
    2. Autoloader Generator
    What is Composer?

    View Slide

  13. Dependency Management
    ● Declare, resolve, and install
    project-specific dependencies
    ● Use others’ code
    ○ Use open source packages
    ○ Focus on your biz features
    ○ Avoid “NIH syndrome”
    ● Create reusable packages in your own org

    View Slide

  14. Before Composer
    ● Compile PHP with extensions
    ● System-level package managers
    ● PEAR packages (system-system)
    ● Include 3rd-party code in source
    ● Git submodules
    Composer inspired by bundler and npm

    View Slide

  15. getcomposer.org packagist.org

    View Slide

  16. https://github.com/engrade/engrade-php-sdk/blob/master/composer.json
    Composer.json Example

    View Slide

  17. Specifying Versions
    MAJOR.MINOR.PATCH (SemVer.org)
    “{vendor}/{package}”: “{version constraints}”
    ● “>=3.1.4” – Use any version >= 3.1.4
    ● “3.1.*” – Use any patch version of 3.1
    ● “~3.2” – Use any 3.x version >= 3.2

    View Slide

  18. Installing Composer
    curl -sS https://getcomposer.org/installer | php
    mv composer.phar /usr/local/bin/composer

    View Slide

  19. Installing Your Dependencies
    For development:
    composer install
    and
    composer update
    For production:
    composer install --no-dev --optimize-autoloader

    View Slide

  20. your-project-root/
    |— src/
    |— tests/
    |— vendor/
    |— composer.json
    |— composer.lock
    What does that do?

    View Slide

  21. SHOULD YOU COMMIT
    YOUR composer.lock
    FILE? THE ANSWER MAY
    SHOCK YOU!

    View Slide

  22. For Applications?
    ?

    View Slide

  23. For Applications?
    YES!

    View Slide

  24. For Applications? For Libraries?
    ?
    YES!

    View Slide

  25. For Applications? For Libraries?
    Sure.
    YES!

    View Slide

  26. How do you use your installed code?
    require ‘vendor/autoload.php’;
    $client = new GuzzleHttp\Client();
    $response = $client->get(‘http://example.com’);

    View Slide

  27. 1. Dependency Manager
    2. Autoloader Generator
    What is Composer?

    View Slide

  28. — Includes —

    View Slide

  29. a.php
    CODE
    CODE
    include ‘b.php’;
    CODE
    Includes = Why I Started Using PHP
    b.php
    CODE
    CODE
    CODE
    CODE
    Executed code
    CODE
    CODE
    CODE
    CODE
    CODE
    CODE
    CODE

    View Slide

  30. Includes = Why I Started Using PHP
    header.php
    sidebar.php main.php

    View Slide

  31. View Slide

  32. include
    include_once
    require
    require_once
    Including vs. Requiring
    What’s the difference
    between all of these?

    View Slide

  33. Including Classes - Not Fun
    // NOTE: Assuming one class per file
    require_once(‘classes/user.class.php’);
    require_once(‘classes/page.class.php’);
    require_once(‘classes/role.class.php’);
    require_once(‘classes/db.class.php’);
    // ...

    View Slide

  34. The Bottom Line
    Explicit includes/requires are:
    1. Necessary and helpful for
    procedural code.
    2. Cumbersome and harmful for object-
    oriented code.

    View Slide

  35. — Autoloaders —

    View Slide

  36. What is an Autoloader?
    1. A callback triggered when a non-existent
    class is referenced.

    View Slide

  37. What is an Autoloader?
    1. A callback triggered when a non-existent
    class is referenced.
    2. A function that provides a definition for a
    specified class name.

    View Slide

  38. Autoloader Advantages
    ● Classes are loaded on demand
    ○ No need to write specific include statements
    ○ Class never loaded unless it’s needed
    ● Leads to better code maintainability
    ● Easy to write

    View Slide

  39. Simple Autoloader Implementation
    class Autoloader {
    public function __construct($root) {...}
    public function load($class) {
    $path = $path->root;
    $path .= str_replace(‘\\’, ‘/’, $class);
    if (file_exists($path)) require $path;
    }
    }

    View Slide

  40. Registering Autoloaders
    $loader = new Autoloader(__DIR__);
    spl_autoload_register([$loader, ‘load’]);

    View Slide

  41. Autoloader Implementation Tips
    ● You can have multiple autoloaders.
    ● Don’t throw errors/exceptions if a file
    doesn’t exist. Let the other autoloaders try.
    ● Don’t use the __autoload() function.
    ● Use Composer’s autoloader.
    ○ You don’t have to write your own
    ○ It already follows the PSR autoloading standards

    View Slide

  42. — PSRs & PHP-FIG —

    View Slide

  43. View Slide

  44. ● FIG = Framework Interop Group
    ● PSR = PHP Standards Recommendation
    ○ Autoloading: PSR-0, PSR-4
    ○ Others:
    ■ PSR-1, PSR-2 - Coding style
    ■ PSR-3 - Logging interface
    ■ PSR-7 - HTTP message interface
    PHP-FIG

    View Slide

  45. Autoloader Implementation Revisited
    class Autoloader {
    public function __construct($root) {...}
    public function load($class) {
    $path = $path->root;
    $path .= str_replace(‘\\’, ‘/’, $class);
    if (file_exists($path)) require $path;
    }
    }

    View Slide

  46. Autoloader Implementation Revisited
    class Autoloader {
    public function __construct($root) {...}
    public function load($class) {
    $path = $path->root;
    $path .= str_replace(‘\\’, ‘/’, $class);
    if (file_exists($path)) require $path;
    }
    }

    View Slide

  47. Class to load: Zend\Http\Client
    Include file:
    /Zend/Http/Client.php
    Autoloading PSRs (PSR-0)

    View Slide

  48. Source root base namespace: Zend\Http
    Class to load: Zend\Http\Client
    Include file:
    /Client.php
    Autoloading PSRs (PSR-4)

    View Slide

  49. Base Namespace in composer.json
    {
    ...
    "autoload": {
    "psr-4": {
    "Zend\\Http\\": "src/"
    }
    }
    }

    View Slide

  50. — Optimization —

    View Slide

  51. BAD
    GOOD
    There are many ways to implement autoloaders.

    View Slide

  52. All classes in one file; no autoloader
    BAD
    GOOD

    View Slide

  53. Many autoloaders; Each can only load 1 class
    BAD
    GOOD

    View Slide

  54. BAD
    GOOD
    2 1

    View Slide

  55. BAD
    GOOD
    Composer autoloader
    (1 autoloader handles all classes)

    View Slide

  56. BAD
    GOOD
    Composer optimized autoloader
    (1 autoloader; fast lookup; no file_exists)

    View Slide

  57. Classmap Autoloading
    In your project root:
    composer install --no-dev --optimize-autoloader

    View Slide

  58. Classmap Autoloading
    $paths = [...]; // class => file mappings
    if (isset($paths[$class])) require $paths[$class];
    // vs.
    $path = $root . str_replace(‘\\’, ‘/’, $class);
    if (file_exists($path)) require $path;

    View Slide

  59. One Autoloader to rule them all.

    View Slide

  60. Composing
    a Better
    Phuture
    by Jeremy Lindblom
    @jeremeamia

    View Slide