decoupled libraries for php 5.4: the aura project

42
Decoupled Libraries for PHP 5.4: The Aura Project php|tek 24 May 2012 joind.in/6495 paul-m-jones.com @pmjones

Upload: pmjones88

Post on 25-Dec-2014

6.132 views

Category:

Technology


2 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Decoupled Libraries for PHP 5.4: The Aura Project

Decoupled Libraries for PHP 5.4:The Aura Project

php|tek24 May 2012

joind.in/6495

paul-m-jones.com@pmjones

Page 2: Decoupled Libraries for PHP 5.4: The Aura Project

Read These

Page 3: Decoupled Libraries for PHP 5.4: The Aura Project

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

Page 4: Decoupled Libraries for PHP 5.4: The Aura Project

Overview

• Background of libraries vs. frameworks

• Principles of decoupled libraries

• Individual Aura libraries

Page 5: Decoupled Libraries for PHP 5.4: The Aura Project

Some Background

Page 6: Decoupled Libraries for PHP 5.4: The Aura Project

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

Page 7: Decoupled Libraries for PHP 5.4: The Aura Project

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

Page 8: Decoupled Libraries for PHP 5.4: The Aura Project

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.

Page 9: Decoupled Libraries for PHP 5.4: The Aura Project

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)

Page 10: Decoupled Libraries for PHP 5.4: The Aura Project

Aura

Page 11: Decoupled Libraries for PHP 5.4: The Aura Project

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

Page 12: Decoupled Libraries for PHP 5.4: The Aura Project

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

Page 13: Decoupled Libraries for PHP 5.4: The Aura Project

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

Page 14: Decoupled Libraries for PHP 5.4: The Aura Project

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'); }}

Page 15: Decoupled Libraries for PHP 5.4: The Aura Project

Dependency Injection Examplesclass Foo{ protected $db; public function __construct(Database $db) { $this->db = $db; }}

class Foo{ protected $db; public function setDb(Database $db) { $this->db = $db; }}

Page 16: Decoupled Libraries for PHP 5.4: The Aura Project

Package Organization

Page 17: Decoupled Libraries for PHP 5.4: The Aura Project

Aura.Router

Page 18: Decoupled Libraries for PHP 5.4: The Aura Project

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, and parameter values for a specific application route.

Page 19: Decoupled Libraries for PHP 5.4: The Aura Project

Instantiation

// create the map object directly ...$map = require '/path/to/Aura.Router/scripts/instance.php';

// ... or add to autoloader, then:use Aura\Router\Map;use Aura\Router\RouteFactory;$map = new Map(new RouteFactory);

Page 20: Decoupled Libraries for PHP 5.4: The Aura Project

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', ],));

Page 21: Decoupled Libraries for PHP 5.4: The Aura Project

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 or use `$_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.

Page 22: Decoupled Libraries for PHP 5.4: The Aura Project

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',]

Page 23: Decoupled Libraries for PHP 5.4: The Aura Project

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);

Page 24: Decoupled Libraries for PHP 5.4: The Aura Project

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', ],));

Page 25: Decoupled Libraries for PHP 5.4: The Aura Project

Micro-Framework Dispatcher

$params = $route->values;$controller = $params['controller'];unset($params['controller']);echo $controller($params);

Page 26: Decoupled Libraries for PHP 5.4: The Aura Project

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>';

Page 27: Decoupled Libraries for PHP 5.4: The Aura Project

Aura.Web

Page 28: Decoupled Libraries for PHP 5.4: The Aura Project

Description

The 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` transfer

object that describes the eventual HTTP response. (Note that the `Response` transfer object is not itself an HTTP

response.)

Page 29: Decoupled Libraries for PHP 5.4: The Aura Project

Setup

// include all package files,// or add to your autoloaderinclude '/path/to/Aura.Web/src.php';

// create a page controllernamespace Vendor\Package\Web;use Aura\Web\AbstractPage;class Page extends AbstractPage{ // controller body}

Page 30: Decoupled Libraries for PHP 5.4: The Aura Project

Instantiation and Callinguse Vendor\Package\Web\Page;use Aura\Web\Context;use Aura\Web\Response as ResponseTransfer;

$params = [ 'action' => 'hello', 'noun' => 'world', 'format' => '.html',];

$page = new Page( new Context($GLOBALS), new ResponseTransfer, $params);

$response_transfer = $page->exec();

Page 31: Decoupled Libraries for PHP 5.4: The Aura Project

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

Page 32: Decoupled Libraries for PHP 5.4: The Aura Project

Action Method

namespace Vendor\Package\Web;use Aura\Web\AbstractPage;class Page extends AbstractPage{ protected function actionHello($noun = null) { $noun = htmlspecialchars($noun, ENT_QUOTES, 'UTF-8'); $content = "Hello, {$noun}!"; $this->response->setContent($content); }}

Page 33: Decoupled Libraries for PHP 5.4: The Aura Project

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);}

Page 34: Decoupled Libraries for PHP 5.4: The Aura Project

Response Delivery

• ResponseTransfer object is *not* an HTTP response

• Must convert it to a real HTTP response

• Allows any HTTP library, or none

Page 35: Decoupled Libraries for PHP 5.4: The Aura Project

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();

Page 36: Decoupled Libraries for PHP 5.4: The Aura Project

Full-Stack Framework

Page 37: Decoupled Libraries for PHP 5.4: The Aura Project

Packages

• Aura.Autoload

• Aura.Cli

• Aura.Di

• Aura.Http

• Aura.Marshal

• Aura.Router

• Aura.Signal

• Aura.Sql

• Aura.View

• Aura.Web

Page 38: Decoupled Libraries for PHP 5.4: The Aura Project

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

Page 39: Decoupled Libraries for PHP 5.4: The Aura Project
Page 40: Decoupled Libraries for PHP 5.4: The Aura Project

Conclusion

Page 41: Decoupled Libraries for PHP 5.4: The Aura Project

• 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