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

Namespaces and Autoloading (ZendCon 2014)

Namespaces and Autoloading (ZendCon 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!

Beau Simensen

October 29, 2014
Tweet

More Decks by Beau Simensen

Other Decks in Programming

Transcript

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

    User { } include "vendor/3rd-party/lib/user.php" ! PHP Fatal error: Cannot redeclare class User
  2. Commodity Names User Item Session Factory! List Client Post Entry

    Server Log! Cache Logger Input Command! ...
  3. \

  4. \\

  5. Using \ can be awkward, but it is better than

    some of the alternatives that were considered
  6. 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?");
  7. namespace Acme\Account; class User { } ! $ cd Acme/Account

    $ touch User.php ! # Acme/Account/User.php
  8. namespace Acme\Account; throw new Exception\SomeError("hi"); ! $ cd Acme/Account $

    cat Exception/SomeError.php ! # Acme/Account/Exception/SomeError.php
  9. namespace Acme\Account; throw new Exception("wait, what?"); ! $ cd Acme/Account

    $ cat Exception.php ! # Acme/Account/Exception.php
  10. namespace Acme\Account; throw new \Exception("oh, i see!"); ! $ cd

    Acme/Account $ cat /Exception.php ! # Exception.php
  11. Two namespaces or classes of the same name cannot be

    imported by use at the same time
  12. 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
  13. 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
  14. 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); }
  15. 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?");
  16. You probably won't use most of what you are about

    to learn directly... (it is good history to know, though!)
  17. function __autoload($class) { if ($class === "Acme\\Account\\User") { // do

    something to cause this class // to become defined require __DIR__."/src/user.inc"; } }
  18. 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"; } });
  19. PSR-0 had a handful of other relatively insignificant* issues *

    the significance of the issues varies wildly depending on who you ask
  20. { "autoload": { "psr-0": { "Acme\\Account\\": "src" } } }

    ! new Acme\Account\User(); ! # src/Acme/Account/User.php
  21. { "autoload": { "psr-0": { "Acme_Account_": "src" } } }

    ! new Acme_Account_User(); ! # src/Acme/Account/User.php
  22. Overall same idea as PSR-0 in that it maintains a

    direct relationship between namespaces and the filesystem
  23. { "autoload": { "psr-4": { "Acme\\Account\\": "src" } } }

    ! new Acme\Account\User(); ! # src/User.php
  24. { "autoload": { "psr-0": { "Acme\\Account\\": "src" } } }

    ! new Acme\Account\User(); ! # src/Acme/Account/User.php
  25. { "autoload": { "psr-4": { "Acme\\Account\\": "src/Acme/Account" } } }

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