building lithium apps

57
BUILDING LITHIUM APPS LIKE A BOSS Pace University, NYC · 10-19-2010

Upload: nate-abele

Post on 10-May-2015

9.887 views

Category:

Technology


1 download

DESCRIPTION

Building Lithium Apps (Like a Boss) was a workshop presented on the structure and philosophy of the Lithium framework and its applications, and how best to take advantage of them.

TRANSCRIPT

Page 1: Building Lithium Apps

BUILDING LITHIUMAPPS LIKE A BOSSPace University, NYC · 10-19-2010

Page 2: Building Lithium Apps

ARCHITECTURE

Page 3: Building Lithium Apps

?

Page 4: Building Lithium Apps

architecture |ˈärkiˌtek ch ər|

Page 5: Building Lithium Apps

noun! the complex or carefully designed structure of! something

Page 6: Building Lithium Apps

noun! Orderly arrangement of parts; structure

Page 7: Building Lithium Apps

noun! the conceptual structure and logical organization of a computer! or computer-based system

Page 8: Building Lithium Apps

“ARCHITECTURE” IN PHP

Page 9: Building Lithium Apps
Page 10: Building Lithium Apps

“PROCEDURAL”

Page 11: Building Lithium Apps

“OBJECT-ORIENTED”

Page 12: Building Lithium Apps

Procedural Object-Oriented

Page 13: Building Lithium Apps

Procedural Object-Oriented

Page 14: Building Lithium Apps

PARADIGMS

Event-Driven

Aspect-Oriented

Declarative

Procedural

Functional

Object-Oriented

Page 15: Building Lithium Apps

PARADIGMS

Event-Driven

Aspect-Oriented

Declarative

Procedural

Functional

Object-Oriented

Page 16: Building Lithium Apps

PARADIGMS

Event-Driven

Aspect-Oriented

Declarative

Procedural

Functional

Object-Oriented

Page 17: Building Lithium Apps

PARADIGMS

Event-Driven

Aspect-Oriented

Declarative

Procedural

Functional

Object-Oriented

Page 18: Building Lithium Apps

BOOTSTRAP / DISPATCH

Page 19: Building Lithium Apps

index.php

/posts

?url=/posts

Page 20: Building Lithium Apps

index.php

/posts

?url=/posts

config/bootstrap.php

config/bootstrap/libraries.php

config/bootstrap/cache.php

config/bootstrap/connections.php

config/bootstrap/action.php

...

Page 21: Building Lithium Apps

index.php

/posts

?url=/posts

config/bootstrap.php

config/bootstrap/libraries.php

config/bootstrap/cache.php

config/bootstrap/connections.php

config/bootstrap/action.php

...

lithium\action\Dispatcher::run(new lithium\action\Request()

)

Page 22: Building Lithium Apps

config/bootstrap/cache.php

Cache::config(array( 'local' => array( 'adapter' => 'Apc' ), 'distributed' => array( 'adapter' => 'Memcached', 'servers' => array( array('127.0.0.1', 11211, 100) array('127.0.0.2', 11211, 100) ) )));

Page 23: Building Lithium Apps

config/bootstrap/connections.php

Connections::add('default', array( 'development' => array( 'type' => 'MongoDb', 'host' => 'localhost', 'database' => 'foo' ), 'production' => array( 'type' => 'MongoDb', 'host' => 'db.host', 'database' => 'foo.prod' )));

Connections::add('cassandra', array( 'type' => 'Cassandra', 'keyspace' => 'foo'));

Page 24: Building Lithium Apps

STATICS & STATE

Page 25: Building Lithium Apps

new lithium\action\Request()

$_GET $_POST $_SERVER

Page 26: Building Lithium Apps

CONFIGURATION

REQUEST

Page 27: Building Lithium Apps

FILTERS

Page 28: Building Lithium Apps

A.K.A. ASPECT-ORIENTED PROGRAMMING

Page 29: Building Lithium Apps

lithium\action\Dispatcher { //...

public static function run($request, ...) { // Pass the request to the Router $params = $classes['router']::process($request);

// Do some checking...

// Get a controller... return static::call($controller); }}

There are no routes here yet

Page 30: Building Lithium Apps

Dispatcher::applyFilter('run', function($self, $params, $chain) {

foreach (Libraries::get() as $name => $config) { // Some sanity checking goes here... include "{$config['path']}/config/routes.php"; } return $chain->next($self, $params, $chain);});

config/bootstrap/action.php

Page 31: Building Lithium Apps

lithium\action\Dispatcher { //...

public static function run($request, ...) { // Pass the request to the Router $params = $classes['router']::process($request);

// Do some checking...

// Get a controller... // $controller = ... return static::call($controller); }}

Dispatcher::applyFilter('run', function($self, $params, $chain) {

foreach (Libraries::get() as $name => $config) { // Some sanity checking goes here... include "{$config['path']}/config/routes.php"; } return $chain->next($self, $params, $chain);});

Page 32: Building Lithium Apps

CONTROLLERS

Page 33: Building Lithium Apps

use app\models\Posts;

app\controllers\PostsController {

public function index() { $posts = Posts::all(); return compact('posts'); }}

Page 34: Building Lithium Apps

class WeblogController < ActionController::Base

def index @posts = Post.find :all

respond_to do |format| format.html format.xml { render :xml => @posts.to_xml } format.rss { render :action => "feed.rxml" } end endend

Page 35: Building Lithium Apps

class WeblogController < ActionController::Base

def index @posts = Post.find :all

respond_to do |format| format.html format.xml { render :xml => @posts.to_xml } format.rss { render :action => "feed.rxml" } end endend

Page 36: Building Lithium Apps

lithium\net\http\Media {

$formats = array( 'html' => array(...), 'json' => array(...), 'xml' => array(...), '...' );}

array('posts' => ...

)

Page 37: Building Lithium Apps

new lithium\action\Response()

Page 38: Building Lithium Apps

new lithium\action\Response()

Controller

View

Dispatcher index.php

Page 39: Building Lithium Apps

REQUEST / RESPONSE

Page 40: Building Lithium Apps

Router::connect('/photos/{:id:[0-9a-f]{24}}.jpg', array(), function($request) { return new Response(array( 'type' => 'jpg', 'body' => Photo::first($request->id)->file->getBytes() ));});

Page 41: Building Lithium Apps

/** * This handles both the home page and the archives pages. */Router::connect('/{:page}', array('page' => 1), array( 'pattern' => '@^/?(?P<page>\d+)$|^\/?$@', 'keys' => array('page' => true), 'handler' => function($request) use ($render) { $page = intval($request->page); $posts = Posts::recent(compact('page'));

return new Response(array( 'body' => $render('index', compact('posts'), compact('request')) )); }));

/** * Handles adding new posts. */Router::connect('/add', array(), function($request) use ($render) { $post = Posts::create();

if (($request->data) && $post->save($request->data)) { return new Response(array('location' => '/')); } return new Response(array( 'body' => $render('edit', compact('post'), compact('request')) ));});

/** * Edits existing pages. */Router::connect('/{:slug:[a-z0-9\-]+}/edit', array('edit' => true), function($request) use ($render) { $conditions = array('slug' => $request->slug); $post = Posts::first(compact('conditions'));

if (($request->data) && $post->save($request->data)) { return new Response(compact('request') + array('location' => array('slug' => $post->slug))); } return new Response(array( 'body' => $render('edit', compact('post'), compact('request')) ));});

/** * Handles single page views. */Router::connect('/{:slug:[a-z0-9\-]+}', array(), function($request) use ($render) { $conditions = array('slug' => $request->slug, 'published' => true); $post = Posts::first(compact('conditions'));

return new Response(array( 'status' => $post ? 200 : 404, 'body' => $render($post ? 'view' : 'error', compact('post'), compact('request')) ));});

Page 42: Building Lithium Apps

WAX ON,

WAX OFF

Page 43: Building Lithium Apps
Page 44: Building Lithium Apps
Page 45: Building Lithium Apps

DEPENDENCIES

Page 46: Building Lithium Apps

class User {

public function somethingUseful() { Logger::info("Something useful is happening"); // ... }}

Page 47: Building Lithium Apps

class User {

public function somethingUseful() { Logger::info("Something useful is happening"); // ... }}

FALE

Super dumb!!

Page 48: Building Lithium Apps

COUPLING RELEVANCE

Page 49: Building Lithium Apps

Post::applyFilter('save', function($self, $params, $chain) { $entity =& $params['entity'];

if (!$entity->exists()) { $entity->created = time(); } return $chain->next($self, $params, $chain);});

?

Page 50: Building Lithium Apps

Post::applyFilter('save', function($self, $params, $chain) { $entity =& $params['entity'];

if (!$entity->exists()) { $entity->created = time(); } return $chain->next($self, $params, $chain);});

?FALE

Page 51: Building Lithium Apps

class WebService {

protected $_classes = array( 'socket' => 'lithium\net\http\socket\Context', 'request' => 'lithium\net\http\Request', 'response' => 'lithium\net\http\Response' );}

Page 52: Building Lithium Apps

use app\models\Post;use li3_elasticsearch\extensions\data\behavior\Searchable;

Post::applyFilter('save', function($self, $params, $chain) { $entity =& $params['entity']; $id = $entity->guid; Searchable::add('public_posts', 'stream', $id, $entity->to('array')); return $chain->next($self, $params, $chain);});

Page 53: Building Lithium Apps

REUSABILITY

Page 54: Building Lithium Apps

require LITHIUM_LIBRARY_PATH . '/lithium/core/Object.php';require LITHIUM_LIBRARY_PATH . '/lithium/core/StaticObject.php';require LITHIUM_LIBRARY_PATH . '/lithium/util/Collection.php';require LITHIUM_LIBRARY_PATH . '/lithium/util/collection/Filters.php';require LITHIUM_LIBRARY_PATH . '/lithium/util/Inflector.php';require LITHIUM_LIBRARY_PATH . '/lithium/util/String.php';require LITHIUM_LIBRARY_PATH . '/lithium/core/Adaptable.php';require LITHIUM_LIBRARY_PATH . '/lithium/core/Environment.php';require LITHIUM_LIBRARY_PATH . '/lithium/net/Message.php';require LITHIUM_LIBRARY_PATH . '/lithium/net/http/Message.php';require LITHIUM_LIBRARY_PATH . '/lithium/net/http/Media.php';require LITHIUM_LIBRARY_PATH . '/lithium/net/http/Request.php';require ....

define('LITHIUM_APP_PATH', dirname(dirname(__DIR__)));define('LITHIUM_LIBRARY_PATH', LITHIUM_APP_PATH . '/../libraries');

Remove whenplugin-izing

config/bootstrap/libraries.php

Make conditional

Page 55: Building Lithium Apps

Libraries::add('my_application', array('default' => true

));

Page 56: Building Lithium Apps

my_awesome_plugin/ config/ bootstrap.php routes.php anything_in_an_app/

Required

Optional

Unless youdisable it

Libraries::add('my_awesome_plugin', array( 'bootstrap' => false));

Happens in the filterwe saw in action.php

Page 57: Building Lithium Apps

DEMO...