Decoupled Libraries for PHP 5.4: The Aura Project
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
6,404
On Slideshare
6,221
From Embeds
183
Number of Embeds
11

Actions

Shares
Downloads
33
Comments
0
Likes
8

Embeds 183

http://auraphp.github.com 130
http://lanyrd.com 16
http://pulsobursatil.internexo.com 11
http://www.php-talks.com 7
http://feeds.feedburner.com 6
http://127.0.0.1 3
http://auraphp.github.io 3
http://auraphp.com 3
http://us-w1.rockmelt.com 2
http://nuevosurco.wordpress.com 1
http://localhost 1

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Decoupled Libraries for PHP 5.4: The Aura Project php|tek 24 May 2012 joind.in/6495 paul-m-jones.com @pmjones
  • 2. Read These
  • 3. About Me• 8 years USAF Intelligence• PHP since 1999• Developer, Senior Developer, Team Lead, Architect,VP Engineering• Aura project, benchmarking series, Solar framework, Savant template system, Zend_DB, Zend_View• PEAR Group member, ZCE Education Advisory Board
  • 4. Overview• Background of libraries vs. frameworks• Principles of decoupled libraries• Individual Aura libraries
  • 5. Some Background
  • 6. Frameworks: Bad!• PHP 4 and early PHP 5: “framework” a bad word (“CMS” was ok)• Libraries and collections: Horde, PEAR, phpLib, phpClasses• Not unified in operation: different constructor signatures, different method verbiage, different usage idioms, tough to combine• Started Solar as a PHP 5 E_STRICT library collection
  • 7. Frameworks: Good!• Rails: “framework” suddenly acceptable• Cake, CodeIgniter, Symfony, Zend• Tapped into user needs• All delivered as a monolithic whole• Re-branded Solar libraries as a framework
  • 8. Frameworks: Good?• Seeing a shift away from framework devotion• Want to use just part of a framework? Difficult.• Download entire framework and try to use one part ...• ... except it has dependencies.• Have to set up parts you don’t care about.
  • 9. Frameworks: Re-Evaluating• PHP 5.3: Lithium, Symfony 2, Zend Framework 2• Micro-frameworks: Glue, Limonade, Silex, Slim • Context, router/dispatcher, HTTP request/response, session manager• Component systems: Symfony (kind of)
  • 10. Aura
  • 11. Rewrite Solar• Solar Framework: 5+ years old• Monolithic, tough to use just parts of it• Extract components and rewrite using PHP 5.4• Independent, de-coupled library packages
  • 12. Driving Principles• Libraries primary, framework secondary• No package depends on any other (self-contained)• Tests and assets encapsulated within package• Some repetition• Carry data across package boundaries using transfer objects
  • 13. Use Dependency Injection• Solar used service locator and universal constructor• In Aura, that would mean a package dependency• So, all packages are set up for dependency injection• You can use any DI container you like
  • 14. Service Locator Examplesclass Foo{ protected $db; public function __construct() { $this->db = Locator::get(db); }}class Foo{ protected $db; public function __construct(Locator $locator) { $this->db = $locator->get(db); }}
  • 15. Dependency Injection Examples class Foo { protected $db; public function __construct(Database $db) { $this->db = $db; } } class Foo { protected $db; public function setDb(Database $db) { $this->db = $db; } }
  • 16. Package Organization
  • 17. Aura.Router
  • 18. Description Aura Router is a PHP package that implements web routing. Given a URI path and a copy of $_SERVER, it will extract controller, action, andparameter values for a specific application route.
  • 19. Instantiation// create the map object directly ...$map = require /path/to/Aura.Router/scripts/instance.php;// ... or add to autoloader, then:use AuraRouterMap;use AuraRouterRouteFactory;$map = new Map(new RouteFactory);
  • 20. Creating Routes// add a simple named route without params$map->add(home, /);// add a simple unnamed route with params$map->add(null, /{:controller}/{:action}/{:id:(d+)});// add a complex named route$map->add(read, /blog/read/{:id}{:format}, [ params => [ id => (d+), format => (..+)?, ], values => [ controller => blog, action => read, format => .html, ],));
  • 21. Matching Routes // get the incoming request URI path $path = parse_url($_SERVER[REQUEST_URI], PHP_URL_PATH); // get the route based on the path and server $route = $map->match($path, $_SERVER); The `match()` method does not parse the URI oruse `$_SERVER` internally. This is because different systems may have different ways of representing that information; e.g., through a URI object or a context object. As long as you can pass the string path and a server array, you can use Aura Router in your application foundation or framework.
  • 22. Route Values$route = $map->match(/blog/read/42.json, $_SERVER);var_export($route->values);// shows these values:[ controller => blog, action => read, id => 42, format => .json,]
  • 23. Dispatching Routes$params = $route->values;$class = ucfirst($params[controller]) . Page;unset($params[controller]);$method = $params[action] . Action;unset($params[action]);$object = new $class();echo $object->$method($params);
  • 24. Micro-Framework Route$map->add(read, /blog/read/{:id}{:format}, [ params => [ id => (d+), format => (..+)?, ], values => [ controller => function ($args) { $id = (int) $args[id]; return "Reading blog ID {$id}"; }, format => .html, ],));
  • 25. Micro-Framework Dispatcher$params = $route->values;$controller = $params[controller];unset($params[controller]);echo $controller($params);
  • 26. Generating Paths$map->add(read, /blog/read/{:id}{:format} // ...// ...$path = $map->generate(read, [ id => 42, format => .atom,]);// $path => "/blog/read/42.atom"$href = htmlspecialchars($path, ENT_QUOTES, UTF-8);echo <a href="$href">Atom feed for this blog entry</a>;
  • 27. Aura.Web
  • 28. DescriptionThe Aura Web package provides tools to build web page controllers, including an `AbstractPage` for action methods, a`Context` class for disovering the request environment, and a `Response` transferobject that describes the eventual HTTP response. (Note that the `Response` transfer object is not itself an HTTP response.)
  • 29. Setup// include all package files,// or add to your autoloaderinclude /path/to/Aura.Web/src.php;// create a page controllernamespace VendorPackageWeb;use AuraWebAbstractPage;class Page extends AbstractPage{ // controller body}
  • 30. Instantiation and Callinguse VendorPackageWebPage;use AuraWebContext;use AuraWebResponse as ResponseTransfer;$params = [ action => hello, noun => world, format => .html,];$page = new Page( new Context($GLOBALS), new ResponseTransfer, $params);$response_transfer = $page->exec();
  • 31. Important Parts• $params[‘action’] and $params[‘format’]• $this->context for get/post/files/accept/etc• $this->response for headers, cookies, content• $this->data for data to be rendered• $this->render() for rendering• (pre|post)(Exec/Action/Render) hooks
  • 32. Action Methodnamespace VendorPackageWeb;use AuraWebAbstractPage;class Page extends AbstractPage{ protected function actionHello($noun = null) { $noun = htmlspecialchars($noun, ENT_QUOTES, UTF-8); $content = "Hello, {$noun}!"; $this->response->setContent($content); }}
  • 33. Data and Renderingprotected function actionHello($noun = null){ $this->data->noun = $noun;}protected function render(){ // escape all data $data = []; foreach ((array) $this->data as $key => $val) { $data[$key] = htmlspecialchars($val, ENT_QUOTES, UTF-8); } // what format? if ($this->getFormat() == .json) { // json $this->response->setContentType(application/json); $content = json_encode([ success => true, content => $data, ]); } else { // html by default $content = "Hello, {$data[noun]}!"; } $this->response->setContent($content);}
  • 34. Response Delivery• ResponseTransfer object is *not* an HTTP response• Must convert it to a real HTTP response• Allows any HTTP library, or none
  • 35. Delivery Code$headers = $response_transfer->getHeaders();foreach ($headers as $label => $value) { header($label, $value);}$cookies = $response_transfer->getCookies();foreach ($cookies as $cookie) { setcookie( $cookie[value], $cookie[expire], $cookie[path], $cookie[domain], $cookie[secure], $cookie[httponly] );}echo $response_transfer->getContent();
  • 36. Full-Stack Framework
  • 37. Packages• Aura.Autoload • Aura.Router• Aura.Cli • Aura.Signal• Aura.Di • Aura.Sql• Aura.Http • Aura.View• Aura.Marshal • Aura.Web
  • 38. Aura.Framework and System• Aura.Framework package to connect all the others together into a cohesive full-stack framework• “System” package to provide a project skeleton
  • 39. Conclusion
  • 40. • Frameworks vs libraries• Principles and packages• Still much to extract from Solar: filters, session manager, i18n/l10n• Google Beta• Join the project: auraphp.github.com
  • 41. Thanks! joind.in/6495auraphp.github.compaul-m-jones.com @pmjones