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.

Ca57a7cfac69ba3abf517470f3770aae?s=128

Jeremy Lindblom

October 02, 2015
Tweet

Transcript

  1. Composing a Better Phuture by Jeremy Lindblom @jeremeamia

  2. • Composer • Packages • SemVer • Autoloading • PSRs

    Composing a Better Phuture
  3. But first, a history lesson. (Don’t worry, we’ll only cover

    a few years)
  4. PHP is “mostly dead” 2008

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

  6. ♥ for Git/GitHub grow 2010

  7. PSR-0 & Composer 2011

  8. HaPHPy 20th Birthday 2015

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

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

  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
  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
  15. getcomposer.org packagist.org

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

  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
  18. Installing Composer curl -sS https://getcomposer.org/installer | php mv composer.phar /usr/local/bin/composer

  19. Installing Your Dependencies For development: composer install and composer update

    For production: composer install --no-dev --optimize-autoloader
  20. your-project-root/ |— src/ |— tests/ |— vendor/ |— composer.json |—

    composer.lock What does that do?
  21. SHOULD YOU COMMIT YOUR composer.lock FILE? THE ANSWER MAY SHOCK

    YOU!
  22. For Applications? ?

  23. For Applications? YES!

  24. For Applications? For Libraries? ? YES!

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

  26. How do you use your installed code? <?php require ‘vendor/autoload.php’;

    $client = new GuzzleHttp\Client(); $response = $client->get(‘http://example.com’);
  27. 1. Dependency Manager 2. Autoloader Generator What is Composer?

  28. — Includes —

  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
  30. Includes = Why I Started Using PHP header.php sidebar.php main.php

  31. None
  32. include include_once require require_once Including vs. Requiring What’s the difference

    between all of these?
  33. Including Classes - Not Fun <?php // 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’); // ...
  34. The Bottom Line Explicit includes/requires are: 1. Necessary and helpful

    for procedural code. 2. Cumbersome and harmful for object- oriented code.
  35. — Autoloaders —

  36. What is an Autoloader? 1. A callback triggered when a

    non-existent class is referenced.
  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.
  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
  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; } }
  40. Registering Autoloaders $loader = new Autoloader(__DIR__); spl_autoload_register([$loader, ‘load’]);

  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
  42. — PSRs & PHP-FIG —

  43. None
  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
  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; } }
  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; } }
  47. Class to load: Zend\Http\Client Include file: <source-root>/Zend/Http/Client.php Autoloading PSRs (PSR-0)

  48. Source root base namespace: Zend\Http Class to load: Zend\Http\Client Include

    file: <source-root>/Client.php Autoloading PSRs (PSR-4)
  49. Base Namespace in composer.json { ... "autoload": { "psr-4": {

    "Zend\\Http\\": "src/" } } }
  50. — Optimization —

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

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

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

  54. BAD GOOD 2 1

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

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

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

  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;
  59. One Autoloader to rule them all.

  60. Composing a Better Phuture by Jeremy Lindblom @jeremeamia