Namespaces and Autoloading (php[world] 2014)

23d971deeb3975a7d28246192fbbe7b7?s=47 Beau Simensen
November 11, 2014

Namespaces and Autoloading (php[world] 2014)

Want to make sure that your class names don't overwrite the class names for any other projects on the server? Hate having long class names like [insert ridiculously long classname here]? Namespaces were introduced in PHP 5.3 to help address these common issues. Learn how to namespace classes and see how namespaces and class autoloading can make your coding experience much nicer!

23d971deeb3975a7d28246192fbbe7b7?s=128

Beau Simensen

November 11, 2014
Tweet

Transcript

  1. 8.

    # class User { } include "src/user.inc"; ! # class

    User { } include "vendor/3rd-party/lib/user.php" ! PHP Fatal error: Cannot redeclare class User
  2. 9.

    Commodity Names User Item Session Factory! List Client Post Entry

    Server Log! Cache Logger Input Command! ...
  3. 11.
  4. 12.
  5. 13.
  6. 22.
  7. 27.
  8. 28.

    \

  9. 35.

    \\

  10. 38.

    Using \ can be awkward, but it is better than

    some of the alternatives that were considered
  11. 40.
  12. 51.

    namespace Acme\Account; ! use Acme\Account\User; ! class User { public

    static function err($message) { throw new User\Exception\SomeError($message); } } ! namespace Acme\Account\User\Exception; ! class SomeError extends \Exception { } ! \Acme\Account\User::err("Confused Yet?");
  13. 58.

    namespace Acme\Account; class User { } ! $ cd Acme/Account

    $ touch User.php ! # Acme/Account/User.php
  14. 59.

    namespace Acme\Account; throw new Exception\SomeError("hi"); ! $ cd Acme/Account $

    cat Exception/SomeError.php ! # Acme/Account/Exception/SomeError.php
  15. 60.

    namespace Acme\Account; throw new Exception("wait, what?"); ! $ cd Acme/Account

    $ cat Exception.php ! # Acme/Account/Exception.php
  16. 61.

    namespace Acme\Account; throw new \Exception("oh, i see!"); ! $ cd

    Acme/Account $ cat /Exception.php ! # Exception.php
  17. 70.

    Two namespaces or classes of the same name cannot be

    imported by use at the same time
  18. 71.

    namespace Acme\Store\Controller; ! use Acme\Account\Errors; use Acme\PayPalClient\Errors; ! PHP Fatal

    error: Cannot use Acme \PayPalClient\Errors as Errors because the name is already in use
  19. 72.

    namespace Acme\Store\Controller; ! use Acme\Account\Errors; use Acme\PayPalClient\Errors; ! PHP Fatal

    error: Cannot use Acme \PayPalClient\Errors as Errors because the name is already in use
  20. 74.

    namespace Acme\Store\Controller; ! use Acme\Account\Errors as AccountErrors; use Acme\PayPalClient\Errors as

    PayPalErrors; ! if ($user->isBad()) { throw new AccountErrors\BadUser( "you know what you did" ); } try { $paypal->tryToCharge($user); } catch (PayPalErrors\TransactionError $e) { throw new AccountErrors\TransportError($e); }
  21. 77.

    namespace Acme\Account; ! use Acme\Account\User; ! class User { public

    static function err($message) { throw new User\Exception\SomeError($message); } } ! namespace Acme\Account\User\Exception; ! class SomeError extends \Exception { } ! \Acme\Account\User::err("A little less confusing?");
  22. 81.
  23. 82.

    You probably won't use most of what you are about

    to learn directly... (it is good history to know, though!)
  24. 85.

    function __autoload($class) { if ($class === "Acme\\Account\\User") { // do

    something to cause this class // to become defined require __DIR__."/src/user.inc"; } }
  25. 89.

    spl_autoload_register( // Registers Acme's autoloader Acme::autoloader ); ! spl_autoload_register( //

    Registers Doctrine's autoloader Doctrine::autoloader ); ! spl_autoload_register(function($class) { // Register a rarely used class if ($class === "Acme\\RarelyUsed\\User") { require __DIR__."/src/user.inc"; } });
  26. 92.
  27. 94.
  28. 111.

    PSR-0 had a handful of other relatively insignificant* issues *

    the significance of the issues varies wildly depending on who you ask
  29. 114.
  30. 115.

    { "autoload": { "psr-0": { "Acme\\Account\\": "src" } } }

    ! new Acme\Account\User(); ! # src/Acme/Account/User.php
  31. 116.

    { "autoload": { "psr-0": { "Acme_Account_": "src" } } }

    ! new Acme_Account_User(); ! # src/Acme/Account/User.php
  32. 119.
  33. 122.

    Overall same idea as PSR-0 in that it maintains a

    direct relationship between namespaces and the filesystem
  34. 129.
  35. 130.

    { "autoload": { "psr-4": { "Acme\\Account\\": "src" } } }

    ! new Acme\Account\User(); ! # src/User.php
  36. 137.

    { "autoload": { "psr-0": { "Acme\\Account\\": "src" } } }

    ! new Acme\Account\User(); ! # src/Acme/Account/User.php
  37. 138.

    { "autoload": { "psr-4": { "Acme\\Account\\": "src/Acme/Account" } } }

    ! new Acme\Account\User(); ! # src/Acme/Account/User.php
  38. 139.