SlideShare a Scribd company logo
Lithium (#li3)
The framework with the best of both worlds
Richard McIntyre: @mackstar

★ Lithium core team

★ Freelancer - Leeds/Manchester

★ Most recently at BBC, Mamas & Papas, UOR

★ Engineer on BBC Olympics App

★ Lived in Japan 15 years

★ Done PHP for donkeys
Lithium Best
Frameworks
Lithium Best
I’ve seen it
✦ Symfony 2        ✦ Merb

✦ Zend Framework   ✦ Sinatra

✦ CakePHP          ✦ Spring

✦ Code Igniter     ✦ Stripes (Java)

✦ Drupal 6&7       ✦ Django
                       Wordpress
✦ Silex
                   ✦




✦ Rails
Lithium Best
many
frameworks
are
like
this
Each software solution should be in proportion to
the problem being solved.
Each software solution should be in proportion to
the problem being solved.

                            -some lazy bugger
Each software solution should be in proportion to
the problem being solved.

                            -some lazy bugger
                                           me
<?php

use BehatMinkExtensionContextMinkContext;

class FeatureContext extends MinkContext
{
   /**
    * @Then /^I wait for the suggestion box to appear$/
    */
   public function myNameHasAMeaninglessExistance()
   {
      $this->getSession()->wait(5000, "$('.suggestions-results').children().length >
0");
   }
}
All problems in computer science can be solved
by another level of indirection. Except for the
problem of too many layers of indirection.

                 Butler Lampson, David Wheeler
Code Sexy-ness
There’s nothing like the look of beautiful Ruby code in the morning.
Gracefully colored by TextMate and rendered in Bitstream Vera pt 12.
@dhh
Developer Happy-ness
Any fool can write code that a computer can understand. Good
programmers write code that humans can understand.
                                                        –Martin Fowler
Light Footprint
Light Footprint
Looking for a hackers Framework?




Light Footprint
Fast, Flexible and Rad
World 1




Full Stack Framework
   Convention Over Configuration
github.com/UnionOfRad/framework
The Photo Blog Tutorial
   github.com/nateabele/photoblog
Model
namespace photoblogmodels;

class Photos extends lithiumdataModel {

    public $validates = array();

    protected $_meta = array('source' => 'fs.files');

    public function save($entity, $data = null, array $options = array()) {
      if ($data) {
        $entity->set($data);
      }
      if ($entity->tags && !is_array($entity->tags)) {
        $entity->tags = array_map('trim', explode(',', $entity->tags));
      }
      return parent::save($entity, null, $options);
    }
}
Model
namespace photoblogmodels;

class Photos extends lithiumdataModel {

    public $validates = array();

    protected $_meta = array('source' => 'fs.files');

    public function save($entity, $data = null, array $options = array()) {
      if ($data) {
        $entity->set($data);
      }
      if ($entity->tags && !is_array($entity->tags)) {
        $entity->tags = array_map('trim', explode(',', $entity->tags));
      }
      return parent::save($entity, null, $options);
    }
}
Model
namespace photoblogmodels;

class Photos extends lithiumdataModel {

    public $validates = array();

    protected $_meta = array('source' => 'fs.files');

    public function save($entity, $data = null, array $options = array()) {
      if ($data) {
        $entity->set($data);
      }
      if ($entity->tags && !is_array($entity->tags)) {
        $entity->tags = array_map('trim', explode(',', $entity->tags));
      }
      return parent::save($entity, null, $options);
    }
}
Views

<?=$this->form->create($photo, array('type' => 'file')); ?>
 <?=$this->form->field('title'); ?>
 <?=$this->form->field('description'); ?>
 <?php if (!$photo->exists()): ?>
  <?=$this->form->field('file', array('type' => 'file')); ?>
 <?php endif; ?>
 <?=$this->form->field('tags', array('label' =>
                             'Add tags separated by commas')); ?>
 <?=$this->form->submit('Save'); ?>
<?=$this->form->end(); ?>
Views

<?=$this->form->create($photo, array('type' => 'file')); ?>
 <?=$this->form->field('title'); ?>
 <?=$this->form->field('description'); ?>
 <?php if (!$photo->exists()): ?>
  <?=$this->form->field('file', array('type' => 'file')); ?>
 <?php endif; ?>
 <?=$this->form->field('tags', array('label' =>
                             'Add tags separated by commas')); ?>
 <?=$this->form->submit('Save'); ?>
<?=$this->form->end(); ?>
Views

<?=$this->form->create($photo, array('type' => 'file')); ?>
 <?=$this->form->field('title'); ?>
 <?=$this->form->field('description'); ?>
 <?php if (!$photo->exists()): ?>
  <?=$this->form->field('file', array('type' => 'file')); ?>
 <?php endif; ?>
 <?=$this->form->field('tags', array('label' =>
                             'Add tags separated by commas')); ?>
 <?=$this->form->submit('Save'); ?>
<?=$this->form->end(); ?>
<h1>
 <?=$this->title($photo->title); ?>
 <em>[
   <?=$this->html->link(
               'edit', array('Photos::edit', 'id' => $photo->_id)
          ); ?> ]</em>
</h1>

<p><?=$photo->description; ?></p>

<?php if ($photo->tags): ?>
 Tags:
 <?php foreach ($photo->tags as $tag): ?>
  <?=$this->html->link(
      $tag, array('Photos::index', 'args' => array($tag))
   ); ?>
 <?php endforeach; ?>
<?php endif; ?>

<?=$this->html->image(
      "/photos/view/{$photo->_id}.jpeg", array(
         'alt' => $photo->title, 'width' => "100%"
      )
); ?>
<h1>
 <?=$this->title($photo->title); ?>
 <em>[
   <?=$this->html->link(
               'edit', array('Photos::edit', 'id' => $photo->_id)
          ); ?> ]</em>
</h1>

<p><?=$photo->description; ?></p>

<?php if ($photo->tags): ?>
 Tags:
 <?php foreach ($photo->tags as $tag): ?>
  <?=$this->html->link(
      $tag, array('Photos::index', 'args' => array($tag))
   ); ?>
 <?php endforeach; ?>
<?php endif; ?>

<?=$this->html->image(
      "/photos/view/{$photo->_id}.jpeg", array(
         'alt' => $photo->title, 'width' => "100%"
      )
); ?>
<h1>
 <?=$this->title($photo->title); ?>
 <em>[
   <?=$this->html->link(
               'edit', array('Photos::edit', 'id' => $photo->_id)
          ); ?> ]</em>
</h1>

<p><?=$photo->description; ?></p>

<?php if ($photo->tags): ?>
 Tags:
 <?php foreach ($photo->tags as $tag): ?>
  <?=$this->html->link(
      $tag, array('Photos::index', 'args' => array($tag))
   ); ?>
 <?php endforeach; ?>
<?php endif; ?>

<?=$this->html->image(
      "/photos/view/{$photo->_id}.jpeg", array(
         'alt' => $photo->title, 'width' => "100%"
      )
); ?>
Controller

namespace photoblogcontrollers;

use photoblogmodelsPhotos;
use li3_geoextensionsGeocoder;

class PhotosController extends lithiumactionController {

 public function index($tags = null) {
   $conditions = $tags ? compact('tags') : array();
   $photos = Photos::all(compact('conditions'));
   return compact('photos');
 }

 public function view() {
   $photo = Photos::first($this->request->id);
   return compact('photo');
 }
Controller

namespace photoblogcontrollers;

use photoblogmodelsPhotos;
use li3_geoextensionsGeocoder;

class PhotosController extends lithiumactionController {

 public function index($tags = null) {
   $conditions = $tags ? compact('tags') : array();
   $photos = Photos::all(compact('conditions'));
   return compact('photos');
 }

 public function view() {
   $photo = Photos::first($this->request->id);
   return compact('photo');
 }
Controller

namespace photoblogcontrollers;

use photoblogmodelsPhotos;
use li3_geoextensionsGeocoder;

class PhotosController extends lithiumactionController {

 public function index($tags = null) {
   $conditions = $tags ? compact('tags') : array();
   $photos = Photos::all(compact('conditions'));
   return compact('photos');
 }

 public function view() {
   $photo = Photos::first($this->request->id);
   return compact('photo');
 }
public function near($place = null) {
 $this->_render['template'] = 'index';
 $coords = Geocoder::find('google', $place);

    $photos = Photos::within(array($coords, $coords), array('limit' => 1));
    return compact('photos');
}

public function add() {
  $photo = Photos::create();
  if (($this->request->data) && $photo->save($this->request->data)) {
    $this->redirect(array('Photos::view', 'id' => $photo->_id));
  }
  $this->_render['template'] = 'edit';
  return compact('photo');
}

public function edit() {
  $photo = Photos::find($this->request->id);
  if (!$photo) {
    $this->redirect('Photos::index');
  }
  if (($this->request->data) && $photo->save($this->request->data)) {
    $this->redirect(array('Photos::view', 'id' => $photo->_id));
  }
  return compact('photo');
}
public function near($place = null) {
 $this->_render['template'] = 'index';
 $coords = Geocoder::find('google', $place);

    $photos = Photos::within(array($coords, $coords), array('limit' => 1));
    return compact('photos');
}

public function add() {
  $photo = Photos::create();
                                              Geo Location
  if (($this->request->data) && $photo->save($this->request->data)) {
    $this->redirect(array('Photos::view', 'id' => $photo->_id));
  }
  $this->_render['template'] = 'edit';
  return compact('photo');
}

public function edit() {
  $photo = Photos::find($this->request->id);
  if (!$photo) {
    $this->redirect('Photos::index');
  }
  if (($this->request->data) && $photo->save($this->request->data)) {
    $this->redirect(array('Photos::view', 'id' => $photo->_id));
  }
  return compact('photo');
}
Routes
use   lithiumnethttpRouter;
use   lithiumcoreEnvironment;
use   lithiumactionResponse;
use   photoblogmodelsPhotos;

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

/**
 * Connect the testing routes.
 */
if (!Environment::is('production')) {
  Router::connect('/test/{:args}', array('controller' => 'lithiumtestController'));
  Router::connect('/test', array('controller' => 'lithiumtestController'));
}
Routes
use   lithiumnethttpRouter;
use   lithiumcoreEnvironment;
use   lithiumactionResponse;
use   photoblogmodelsPhotos;

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

/**
 * Connect the testing routes.
                                                                               By-Passes
 */
if (!Environment::is('production')) {                                       the framework
  Router::connect('/test/{:args}', array('controller' => 'lithiumtestController'));
  Router::connect('/test', array('controller' => 'lithiumtestController'));
}
Routes
use   lithiumnethttpRouter;
use   lithiumcoreEnvironment;
use   lithiumactionResponse;
use
        It’s PHP you can
      photoblogmodelsPhotos;

Router::connect('/photos/view/{:id:[0-9a-f]{24}}.jpeg', array(), function($request) {
 return new Response(array( you
            doarray('Content-type' => 'image/jpeg'),
                  what
   'headers' =>
                   want
   'body' => Photos::first($request->id)->file->getBytes()
 ));
});

/**
 * Connect the testing routes.
 */
if (!Environment::is('production')) {
  Router::connect('/test/{:args}', array('controller' => 'lithiumtestController'));
  Router::connect('/test', array('controller' => 'lithiumtestController'));
}
Structure
Features
✦ Full stack MVC          ✦ Object based record-
                            sets
✦ Logger
                          ✦ Command Line
✦ Caching                   Framework

✦ Sessions/Cookies        ✦ Authentication

✦ Full templating suite   ✦ Validator

✦ Integrated TDD suite    ✦ Http Services
Boring
Now for some fun!
World 2




Kick-ass de-coupled hacker happy framework
Are you a
slave to your
framework?
Lithium Best
Lithium Best
Flexible, transparent boostrap process
Database

namespace models;

class Posts extends lithiumdataModel {

}
define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries');
require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php';

use lithiumcoreLibraries;
Libraries::add('lithium');

use lithiumdataConnections;
Connections::add('default', array(
  'type' => 'MongoDb',
  'database' => 'phpnw',
  'host' => 'localhost'
));

Libraries::add('models', array('path' => __DIR__ . '/models'));

use modelsPosts;
$posts = Posts::create(array('title' => 'Hi Guys'));
$posts->save();
define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries');
require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php';

use lithiumcoreLibraries;
Libraries::add('lithium');                  Simple lithium setup
use lithiumdataConnections;
Connections::add('default', array(
  'type' => 'MongoDb',
  'database' => 'phpnw',
  'host' => 'localhost'
));

Libraries::add('models', array('path' => __DIR__ . '/models'));

use modelsPosts;
$posts = Posts::create(array('title' => 'Hi Guys'));
$posts->save();
define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries');
require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php';

use lithiumcoreLibraries;
Libraries::add('lithium');

use lithiumdataConnections;
Connections::add('default', array(
  'type' => 'MongoDb',
  'database' => 'phpnw',                       DB Config
  'host' => 'localhost'
));

Libraries::add('models', array('path' => __DIR__ . '/models'));

use modelsPosts;
$posts = Posts::create(array('title' => 'Hi Guys'));
$posts->save();
define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries');
require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php';

use lithiumcoreLibraries;
Libraries::add('lithium');

use lithiumdataConnections;
Connections::add('default', array(
  'type' => 'MongoDb',
  'database' => 'phpnw',
  'host' => 'localhost'
));                                         Add models ‘app’
Libraries::add('models', array('path' => __DIR__ . '/models'));

use modelsPosts;
$posts = Posts::create(array('title' => 'Hi Guys'));
$posts->save();
define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries');
require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php';

use lithiumcoreLibraries;
Libraries::add('lithium');

use lithiumdataConnections;
Connections::add('default', array(
  'type' => 'MongoDb',
  'database' => 'phpnw',
  'host' => 'localhost'
));

        DB Save
Libraries::add('models', array('path' => __DIR__ . '/models'));

use modelsPosts;
$posts = Posts::create(array('title' => 'Hi Guys'));
$posts->save();
Routes

define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries');
require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php';

use lithiumcoreLibraries;
Libraries::add('lithium');

use lithiumnethttpRouter;
use lithiumactionRequest;

$request = new Request();
$router = new Router();

$router->connect('/cool-root', array('controller' => 'Yea'));
$router->connect('/cool-root/{:application_id:[0-9]{1}}', array('controller' => 'Yea'));
$router->parse($request);

echo Router::match('Yea::index');
echo Router::match(array('Yea::index', 'application_id' => 1));
Routes

define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries');
require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php';

use lithiumcoreLibraries;
Libraries::add('lithium');

use lithiumnethttpRouter;
use lithiumactionRequest;

$request = new Request();
$router = new Router();

$router->connect('/cool-root', array('controller' => 'Yea'));
$router->connect('/cool-root/{:application_id:[0-9]{1}}', array('controller' => 'Yea'));
$router->parse($request);

echo Router::match('Yea::index');
echo Router::match(array('Yea::index', 'application_id' => 1));
Routes

define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries');
require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php';

use lithiumcoreLibraries;
Libraries::add('lithium');

use lithiumnethttpRouter;
use lithiumactionRequest;

$request = new Request();
$router = new Router();

$router->connect('/cool-root', array('controller' => 'Yea'));
$router->connect('/cool-root/{:application_id:[0-9]{1}}', array('controller' => 'Yea'));
$router->parse($request);

echo Router::match('Yea::index');
echo Router::match(array('Yea::index', 'application_id' => 1));
Routes

define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries');
require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php';

use lithiumcoreLibraries;
Libraries::add('lithium');

use lithiumnethttpRouter;
use lithiumactionRequest;

$request = new Request();
$router = new Router();

$router->connect('/cool-root', array('controller' => 'Yea'));
$router->connect('/cool-root/{:application_id:[0-9]{1}}', array('controller' => 'Yea'));
$router->parse($request);

echo Router::match('Yea::index');
echo Router::match(array('Yea::index', 'application_id' => 1));
Lithium Best
/cool-root/4
/cool-root/4

$router->connect('/cool-root/{:application_id:[0-9]{1}}',
                    array('controller' => 'Yea'));
/cool-root/4

$router->connect('/cool-root/{:application_id:[0-9]{1}}',
                    array('controller' => 'Yea'));



  object(lithiumactionRequest)[1]
   public 'url' => string '/cool-root/4' (length=12)
   public 'params' =>
    array (size=3)
      'application_id' => string '4' (length=1)
      'controller' => string 'Yea' (length=3)
      'action' => string 'index' (length=5)
Adaptable Classes

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

require   LITHIUM_LIBRARY_PATH     .   '/lithium/core/Libraries.php';
require   LITHIUM_LIBRARY_PATH     .   '/lithium/core/Object.php';
require   LITHIUM_LIBRARY_PATH     .   '/lithium/core/StaticObject.php';
require   LITHIUM_LIBRARY_PATH     .   '/lithium/core/Environment.php';
require   LITHIUM_LIBRARY_PATH     .   '/lithium/core/Adaptable.php';

use lithiumcoreAdaptable;

class Email extends Adaptable{

    protected static $_configurations = array();
    protected static $_adapters = 'emails';

}
Adaptable Classes

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

require   LITHIUM_LIBRARY_PATH     .   '/lithium/core/Libraries.php';
require   LITHIUM_LIBRARY_PATH     .   '/lithium/core/Object.php';
require   LITHIUM_LIBRARY_PATH     .   '/lithium/core/StaticObject.php';
require   LITHIUM_LIBRARY_PATH     .   '/lithium/core/Environment.php';
require   LITHIUM_LIBRARY_PATH     .   '/lithium/core/Adaptable.php';

use lithiumcoreAdaptable;

class Email extends Adaptable{

    protected static $_configurations = array();
    protected static $_adapters = 'emails';

}
namespace adapters;
use lithiumcoreLibraries;
Libraries::add('lithium');                      class EmailTest
Libraries::add('adapters',                      {
     array('path' => __DIR__ . '/adapters'));     public function send() {
Libraries::paths(                                   echo 'email test send';
     array('emails' => array(                     }
        '{:library}{:name}')));                }
Email::config(array(
  'development' => array(
    'adapter' => 'EmailReal'
  ),                                            namespace adapters;
  'test' => array(
    'adapter' => 'EmailTest'                    class EmailReal
  ),                                            {
));                                               public function send() {
                                                    echo 'email real send';
use lithiumcoreEnvironment;                     }
                                                }
Environment::set('test');
$env = Environment::get();

Email::adapter($env)->send();
namespace adapters;
use lithiumcoreLibraries;
Libraries::add('lithium');                      class EmailTest
Libraries::add('adapters',                      {
     array('path' => __DIR__ . '/adapters'));     public function send() {
Libraries::paths(                                   echo 'email test send';
     array('emails' => array(                     }
        '{:library}{:name}')));                }
Email::config(array(
  'development' => array(
    'adapter' => 'EmailReal'
  ),                                            namespace adapters;
  'test' => array(
    'adapter' => 'EmailTest'                    class EmailReal
  ),                                            {
));                                               public function send() {
                                                    echo 'email real send';
use lithiumcoreEnvironment;                     }
                                                }
Environment::set('test');
$env = Environment::get();

Email::adapter($env)->send();
namespace adapters;
use lithiumcoreLibraries;
Libraries::add('lithium');                      class EmailTest
Libraries::add('adapters',                      {
     array('path' => __DIR__ . '/adapters'));     public function send() {
Libraries::paths(                                   echo 'email test send';
     array('emails' => array(                     }
        '{:library}{:name}')));                }
Email::config(array(
  'development' => array(
    'adapter' => 'EmailReal'
  ),                                            namespace adapters;
  'test' => array(
    'adapter' => 'EmailTest'                    class EmailReal
  ),                                            {
));                                               public function send() {
                                                    echo 'email real send';
use lithiumcoreEnvironment;                     }
                                                }
Environment::set('test');
$env = Environment::get();

Email::adapter($env)->send();
namespace adapters;
use lithiumcoreLibraries;
Libraries::add('lithium');                      class EmailTest
Libraries::add('adapters',                      {
     array('path' => __DIR__ . '/adapters'));     public function send() {
Libraries::paths(                                   echo 'email test send';
     array('emails' => array(                     }
        '{:library}{:name}')));                }
Email::config(array(
  'development' => array(
    'adapter' => 'EmailReal'
  ),                                            namespace adapters;
  'test' => array(
    'adapter' => 'EmailTest'                    class EmailReal
  ),                                            {
));                                               public function send() {
                                                    echo 'email real send';
use lithiumcoreEnvironment;                     }
                                                }
Environment::set('test');
$env = Environment::get();

Email::adapter($env)->send();
Environment::set('development');

class EmailAnother extends Adaptable{             Already
    protected static $_configurations = array();
    protected static $_adapters = 'emails';
                                                  Environment
    public static function send() {
      static::adapter('default')->send();
                                                  Aware
    }

}

EmailAnother::config(array(
  'default' => array(
    'test' => array (
      'adapter' => 'EmailTest'
    ),
    'development' => array(
      'adapter' => 'EmailReal'
    ),
  )
));

EmailAnother::send();
Environment::set('development');

class EmailAnother extends Adaptable{             Already
    protected static $_configurations = array();
    protected static $_adapters = 'emails';
                                                  Environment
    public static function send() {
      static::adapter('default')->send();
                                                  Aware
    }

}

EmailAnother::config(array(
  'default' => array(
    'test' => array (
      'adapter' => 'EmailTest'
    ),
    'development' => array(
      'adapter' => 'EmailReal'
    ),
  )
));

EmailAnother::send();
Environment::set('development');

class EmailAnother extends Adaptable{             Already
    protected static $_configurations = array();
    protected static $_adapters = 'emails';
                                                  Environment
    public static function send() {
      static::adapter('default')->send();
                                                  Aware
    }

}

EmailAnother::config(array(
  'default' => array(
    'test' => array (
      'adapter' => 'EmailTest'
    ),
    'development' => array(
      'adapter' => 'EmailReal'
    ),
  )
));

EmailAnother::send();
Environment::set('development');

class EmailAnother extends Adaptable{             Already
    protected static $_configurations = array();
    protected static $_adapters = 'emails';
                                                  Environment
    public static function send() {
      static::adapter('default')->send();
                                                  Aware
    }

}

EmailAnother::config(array(
  'default' => array(
    'test' => array (
      'adapter' => 'EmailTest'
    ),
    'development' => array(
      'adapter' => 'EmailReal'
    ),
  )
));

EmailAnother::send();
Filters
define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries');

require LITHIUM_LIBRARY_PATH . '/lithium/core/Object.php';
require LITHIUM_LIBRARY_PATH . '/lithium/util/Collection.php';
require LITHIUM_LIBRARY_PATH . '/lithium/util/collection/Filters.php';

class Action extends lithiumcoreObject {

    public function doSomethingStupid() {
      return $this->_filter(__METHOD__, $params, function($self, $params) {
          $result = ‘Your girlfriend is angry at you’;
          return $result;
      });
    }
}

$action = new Action;
$action->applyFilter('doSomethingStupid', function($self, $params, $chain) {
  echo 'About to do something stupid,';
  $result = $chain->next($self, $params, $chain);
  echo 'You IDIOT!!!!!';
  return $result;
});

$action->doSomthingStupid();
define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries');

require LITHIUM_LIBRARY_PATH . '/lithium/core/Object.php';
require LITHIUM_LIBRARY_PATH . '/lithium/util/Collection.php';
require LITHIUM_LIBRARY_PATH . '/lithium/util/collection/Filters.php';

class Action extends lithiumcoreObject {

    public function doSomethingStupid() {
      return $this->_filter(__METHOD__, $params, function($self, $params) {
          $result = ‘Your girlfriend is angry at you’;
          return $result;

    }
      });
                                                                                 Make
}
                                                                               Filterable
$action = new Action;
$action->applyFilter('doSomethingStupid', function($self, $params, $chain) {
  echo 'About to do something stupid,';
  $result = $chain->next($self, $params, $chain);
  echo 'You IDIOT!!!!!';
  return $result;
});

$action->doSomthingStupid();
define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries');

require LITHIUM_LIBRARY_PATH . '/lithium/core/Object.php';
require LITHIUM_LIBRARY_PATH . '/lithium/util/Collection.php';
require LITHIUM_LIBRARY_PATH . '/lithium/util/collection/Filters.php';

class Action extends lithiumcoreObject {

    public function doSomethingStupid() {
      return $this->_filter(__METHOD__, $params, function($self, $params) {
          $result = ‘Your girlfriend is angry at you’;
          return $result;
      });
    }
}

$action = new Action;
$action->applyFilter('doSomethingStupid', function($self, $params, $chain) {
  echo 'About to do something stupid,';
  $result = $chain->next($self, $params, $chain);
  echo 'You IDIOT!!!!!';
  return $result;
});

$action->doSomthingStupid();
use lithiumanalysisLogger;

Logger::config(array(
  'default' => array(
    'adapter' => 'File',
    'path' => __DIR__ . '/crap/logs/'
  )
));


$action = new Action;
$action->applyFilter('doSomethingStupid', function($self, $params, $chain) {

 Logger::debug(date("D M j G:i:s") . " " . 'About to do something stupid,');

 $result = $chain->next($self, $params, $chain);

 Logger::debug(date("D M j G:i:s") . " " . 'You total moron!');

 return $result;

});

$action->doSomthingStupid();
use lithiumanalysisLogger;

Logger::config(array(
  'default' => array(
    'adapter' => 'File',
    'path' => __DIR__ . '/crap/logs/'
  )
));


$action = new Action;
$action->applyFilter('doSomethingStupid', function($self, $params, $chain) {

 Logger::debug(date("D M j G:i:s") . " " . 'About to do something stupid,');

 $result = $chain->next($self, $params, $chain);

 Logger::debug(date("D M j G:i:s") . " " . 'You total moron!');

 return $result;

});

$action->doSomthingStupid();
use lithiumanalysisLogger;

Logger::config(array(
  'default' => array(
    'adapter' => 'File',
    'path' => __DIR__ . '/crap/logs/'
  )
));


$action = new Action;
$action->applyFilter('doSomethingStupid', function($self, $params, $chain) {

 Logger::debug(date("D M j G:i:s") . " " . 'About to do something stupid,');

 $result = $chain->next($self, $params, $chain);

 Logger::debug(date("D M j G:i:s") . " " . 'You total moron!');

 return $result;

});

$action->doSomthingStupid();
use lithiumanalysisLogger;

Logger::config(array(
  'default' => array(
    'adapter' => 'File',
    'path' => __DIR__ . '/crap/logs/'
  )
));


$action = new Action;
$action->applyFilter('doSomethingStupid', function($self, $params, $chain) {

 Logger::debug(date("D M j G:i:s") . " " . 'About to do something stupid,');

 $result = $chain->next($self, $params, $chain);

 Logger::debug(date("D M j G:i:s") . " " . 'You total moron!');

 return $result;

});

$action->doSomthingStupid();
Lithium Best
Find
Cache

 Find
Log

Cache

 Find
Log

Cache

 Find
Log

Cache

 Find
Log

Cache

 Find
Posts::applyFilter('find', function($self, $params, $chain) {

 $result = $chain->next($self, $params, $chain);
 $search = http_build_query($params['options']);
 Logger::debug(
   'Search for: ' . $search . 'returned' . $result->to('json')
 );
 return $result;

});

Posts::applyFilter('find', function($self, $params, $chain) {

 $key = // Make a cache key from params['options']
 if ($result = Cache::read('default', $key)) {
   return $result;
 }
 $result = $chain->next($self, $params, $chain);
 Cache::write('default', $key, $result));
 return $result;

});
Posts::applyFilter('find', function($self, $params, $chain) {

 $result = $chain->next($self, $params, $chain);
 $search = http_build_query($params['options']);
 Logger::debug(
   'Search for: ' . $search . 'returned' . $result->to('json')
 );
 return $result;

});
                     Logging Filter
Posts::applyFilter('find', function($self, $params, $chain) {

 $key = // Make a cache key from params['options']
 if ($result = Cache::read('default', $key)) {
   return $result;
 }
 $result = $chain->next($self, $params, $chain);
 Cache::write('default', $key, $result));
 return $result;

});
Posts::applyFilter('find', function($self, $params, $chain) {

 $result = $chain->next($self, $params, $chain);
 $search = http_build_query($params['options']);
 Logger::debug(

 );                                                     Caching Filter
   'Search for: ' . $search . 'returned' . $result->to('json')

 return $result;

});

Posts::applyFilter('find', function($self, $params, $chain) {

 $key = // Make a cache key from params['options']
 if ($result = Cache::read('default', $key)) {
   return $result;
 }
 $result = $chain->next($self, $params, $chain);
 Cache::write('default', $key, $result));
 return $result;

});
Full Page Caching
Cache::config(array(
  'default' => array(
    'adapter' =>
      'lithiumstoragecacheadapter' . ($apcEnabled ? 'Apc' : 'File')
  )
));

Dispatcher::applyFilter('run', function($self, $params, $chain) {
 $key = md5(LITHIUM_APP_PATH) . '.app.cache.'.md5($params['request']->url);
 if($cache = Cache::read('default', $key)) {
   return $cache;
 }

 $result = $chain->next($self, $params, $chain);

  Cache::write('default', $key, $result, '+1 day');
  return $result;
});
Full Page Caching
                                                 Set Cache Configuration
Cache::config(array(
  'default' => array(
    'adapter' =>
      'lithiumstoragecacheadapter' . ($apcEnabled ? 'Apc' : 'File')
  )
));

Dispatcher::applyFilter('run', function($self, $params, $chain) {
 $key = md5(LITHIUM_APP_PATH) . '.app.cache.'.md5($params['request']->url);
 if($cache = Cache::read('default', $key)) {
   return $cache;
 }

 $result = $chain->next($self, $params, $chain);

  Cache::write('default', $key, $result, '+1 day');
  return $result;
});
Full Page Caching
Cache::config(array(
  'default' => array(
    'adapter' =>
      'lithiumstoragecacheadapter' . ($apcEnabled ? 'Apc' : 'File')
  )
));

Dispatcher::applyFilter('run', function($self, $params, $chain) {
 $key = md5(LITHIUM_APP_PATH) . '.app.cache.'.md5($params['request']->url);
 if($cache = Cache::read('default', $key)) {
   return $cache;
 }

 $result = $chain->next($self, $params, $chain);
                                                      Filter on Dispatcher::run
  Cache::write('default', $key, $result, '+1 day');   Checks for cache w/key
  return $result;
});
Full Page Caching
Cache::config(array(
  'default' => array(
    'adapter' =>
      'lithiumstoragecacheadapter' . ($apcEnabled ? 'Apc' : 'File')
  )
));


      w/out cache content carry on
Dispatcher::applyFilter('run', function($self, $params, $chain) {
 $key = md5(LITHIUM_APP_PATH) . '.app.cache.'.md5($params['request']->url);

        running - saving to cache
 if($cache = Cache::read('default', $key)) {
   return $cache;
 }

 $result = $chain->next($self, $params, $chain);

  Cache::write('default', $key, $result, '+1 day');
  return $result;
});
Content Rendering
namespace dispatcher_appcontrollers;

class YeaController extends lithiumactionController{
 public function index() {
   $yeah = true;
   return compact('yeah');
 }

    public function render(array $options = array()) {
      return 'The response of Yeah is: ' . $this->_render['data']['yeah'];
    }
}
Content Rendering
namespace dispatcher_appcontrollers;

class YeaController extends lithiumactionController{
 public function index() {
   $yeah = true;
   return compact('yeah');
 }

    public function render(array $options = array()) {
      return 'The response of Yeah is: ' . $this->_render['data']['yeah'];
    }
}
Content Rendering
namespace dispatcher_appcontrollers;

class YeaController extends lithiumactionController{
 public function index() {
   $yeah = true;
                      Overwrite ‘render’ method
   return compact('yeah');
 }

    public function render(array $options = array()) {
      return 'The response of Yeah is: ' . $this->_render['data']['yeah'];
    }
}
define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries');

require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php';

use lithiumcoreLibraries;

Libraries::add('lithium');
Libraries::add('dispatcher_app', array('path' => __DIR__ . '/dispatcher_app'));

use lithiumnethttpRouter;
$router = new Router();

Router::connect('/cool-root', array('controller' => 'Yea', 'library' => 'dispatcher_app'));

echo lithiumactionDispatcher::run(
  new lithiumactionRequest()
);
define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries');

require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php';

use lithiumcoreLibraries;

Libraries::add('lithium');
                                 Create Routing
Libraries::add('dispatcher_app', array('path' => __DIR__ . '/dispatcher_app'));

use lithiumnethttpRouter;
$router = new Router();

Router::connect('/cool-root', array('controller' => 'Yea', 'library' => 'dispatcher_app'));

echo lithiumactionDispatcher::run(
  new lithiumactionRequest()
);
define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries');

require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php';

use lithiumcoreLibraries;

Libraries::add('lithium');
Libraries::add('dispatcher_app', array('path' => __DIR__ . '/dispatcher_app'));

use lithiumnethttpRouter;
$router = new Router();

                                                 Run Dispatcher
Router::connect('/cool-root', array('controller' => 'Yea', 'library' => 'dispatcher_app'));

echo lithiumactionDispatcher::run(
  new lithiumactionRequest()
);
Media Class
Media::type('ajax', array('application/xhtml+xml', 'text/html'), array(
  'view' => 'lithiumtemplateView',
  'paths' => array(
    'template' => array(
      '{:library}/views/{:controller}/{:template}.ajax.php',
      '{:library}/views/{:controller}/{:template}.html.php'
    ),
    'layout' => '{:library}/views/layouts/default.ajax.php'
  ),
  'conditions' => array('ajax' => true)
));




                                        Easily setup
                                      template paths
Media::type('jpg', 'image/jpeg', array('cast' => false, 'encode' => function($data) {
  return $data['photo']->file->getBytes();
}));

Media::type('json', 'application/json', array('cast' => false, 'encode' => function($data) {
  return json_encode($data);
}));

Media::type('json', 'application/json', array(
   'cast' => false, 'encode' => 'json_encode')
);
Media::type('jpg', 'image/jpeg', array('cast' => false, 'encode' => function($data) {
  return $data['photo']->file->getBytes();
}));

                                                            Handle Images
Media::type('json', 'application/json', array('cast' => false, 'encode' => function($data) {
  return json_encode($data);
}));

Media::type('json', 'application/json', array(
   'cast' => false, 'encode' => 'json_encode')
);
Media::type('jpg', 'image/jpeg', array('cast' => false, 'encode' => function($data) {
  return $data['photo']->file->getBytes();
}));

Media::type('json', 'application/json', array('cast' => false, 'encode' => function($data) {
  return json_encode($data);
}));

Media::type('json', 'application/json', array(
   'cast' => false, 'encode' => 'json_encode')
);
                                                        Handle JSON
Error Handling
Error Handling
use lithiumcoreErrorHandler;
use lithiumcoreStaticObject;

class IThrowAnException
{
  public function method() {
    throw new Exception('Yo');
  }
}

class IDontThrow extends StaticObject
{
  public static function method($bar) {
    static::_filter(__FUNCTION__, $params, function($self, $params) {
      $object = new IThrowAnException;
      $object->method();
    });
  }
}

ErrorHandler::apply('IDontThrow::method', array(), function($info, $params) {
  echo 'Exception raised with message - ' . $info['exception']->getMessage();
});

IDontThrowAnException::method();
Error Handling
use lithiumcoreErrorHandler;
use lithiumcoreStaticObject;

class IThrowAnException
{
  public function method() {
    throw new Exception('Yo');
  }
}

class IDontThrow extends StaticObject
{
  public static function method($bar) {
    static::_filter(__FUNCTION__, $params, function($self, $params) {
      $object = new IThrowAnException;
      $object->method();
    });
  }
}

ErrorHandler::apply('IDontThrow::method', array(), function($info, $params) {
  echo 'Exception raised with message - ' . $info['exception']->getMessage();
});

IDontThrowAnException::method();
Error Handling
use lithiumcoreErrorHandler;
use lithiumcoreStaticObject;

class IThrowAnException
{
  public function method() {
    throw new Exception('Yo');
  }                                                                             Filterable
}

class IDontThrow extends StaticObject
{
  public static function method($bar) {
    static::_filter(__FUNCTION__, $params, function($self, $params) {
      $object = new IThrowAnException;
      $object->method();
    });
  }
}

ErrorHandler::apply('IDontThrow::method', array(), function($info, $params) {
  echo 'Exception raised with message - ' . $info['exception']->getMessage();
});

IDontThrowAnException::method();
Error Handling
use lithiumcoreErrorHandler;
use lithiumcoreStaticObject;

class IThrowAnException
{
  public function method() {
    throw new Exception('Yo');
  }
}

class IDontThrow extends StaticObject
{
  public static function method($bar) {
    static::_filter(__FUNCTION__, $params, function($self, $params) {
      $object = new IThrowAnException;
      $object->method();
    });
  }
}

ErrorHandler::apply('IDontThrow::method', array(), function($info, $params) {
  echo 'Exception raised with message - ' . $info['exception']->getMessage();
});

IDontThrowAnException::method();
ErrorHandler::apply('lithiumactionDispatcher::run', array(),
 function($info, $params) {
 $response = new Response(array(
   'request' => $params['request'],
   'status' => $info['exception']->getCode(),
   'trace' => $info['exception']->getTrace(),
 ));

 Media::render($response, compact('info', 'params'), array(
  'controller' => 'errors',
  'template' => 'default',
  'layout' => 'default',
  'library' => 'golf',
  'request' => $params['request'],

  ));
  return $response;
});




                                                        Example
Create
ErrorHandler::apply('lithiumactionDispatcher::run', array(),
 function($info, $params) {
                                                                  Response
 $response = new Response(array(
   'request' => $params['request'],
   'status' => $info['exception']->getCode(),
   'trace' => $info['exception']->getTrace(),
 ));

 Media::render($response, compact('info', 'params'), array(
  'controller' => 'errors',
  'template' => 'default',
  'layout' => 'default',
  'library' => 'golf',
  'request' => $params['request'],

  ));
  return $response;
});




                                                        Example
ErrorHandler::apply('lithiumactionDispatcher::run', array(),
 function($info, $params) {
 $response = new Response(array(
   'request' => $params['request'],
   'status' => $info['exception']->getCode(),
   'trace' => $info['exception']->getTrace(),
 ));

 Media::render($response, compact('info', 'params'), array(
  'controller' => 'errors',
  'template' => 'default',
  'layout' => 'default',
  'library' => 'golf',                                            Media
  'request' => $params['request'],
                                                                  Render
  ));
  return $response;
});




                                                        Example
Zendy Love

Libraryies::add(
  'prefix' => 'Zend_',
  'includePath' => '/htdocs/libraries/Zend/trunk/library',
  'bootstrap' => 'Loader/Autoloader.php',
  'loader' => array('Zend_Loader_Autoloader', 'autoload'),
  'transform' => function($class) { return str_replace('_', '/', $class) . '.php'; }
);
define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries');
define('LITHIUM_APP_PATH', __DIR__ . '/templates');

require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php';

use   lithiumcoreLibraries;
use   lithiumcoreEnvironment;
use   lithiumactionDispatcher;
use   lithiumg11nMessage;
use   lithiumnethttpMedia;

Libraries::add('lithium');
Libraries::add('li3_docs');
Libraries::add('templates', array('path' => __DIR__ . '/templates',
                               'default' => true));
Libraries::add('adapters', array('path' => __DIR__ . '/adapters'));

Libraries::add('li3_docs', array(
    'index' => array('lithium', 'adapters')
));




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

require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php';

use   lithiumcoreLibraries;                                          Sets up
use   lithiumcoreEnvironment;
use
use
      lithiumactionDispatcher;
      lithiumg11nMessage;
                                                                      Libraries
use   lithiumnethttpMedia;

Libraries::add('lithium');
Libraries::add('li3_docs');
Libraries::add('templates', array('path' => __DIR__ . '/templates',
                               'default' => true));
Libraries::add('adapters', array('path' => __DIR__ . '/adapters'));

Libraries::add('li3_docs', array(
    'index' => array('lithium', 'adapters')
));




                            Libraries Example
$locale = 'en';
$locales = array('en' => 'English');

Environment::set('development', compact('locale', 'locales'));
Environment::set('development'); }
    $file = "{$config['path']}/config/routes.php";
    file_exists($file) ? call_user_func(function() use ($file) { include $file; }) : null;
  }
  return $chain->next($self, $params, $chain);
});

Media::applyFilter('_handle', function($self, $params, $chain) {
  $params['handler'] += array('outputFilters' => array());
  $params['handler']['outputFilters'] += Message::aliases();
  return $chain->next($self, $params, $chain);
});

echo lithiumactionDispatcher::run(new lithiumactionRequest());
Locale &
$locale = 'en';
                                                                                          Routes
$locales = array('en' => 'English');

Environment::set('development', compact('locale', 'locales'));
Environment::set('development'); }
    $file = "{$config['path']}/config/routes.php";
    file_exists($file) ? call_user_func(function() use ($file) { include $file; }) : null;
  }
  return $chain->next($self, $params, $chain);
});

Media::applyFilter('_handle', function($self, $params, $chain) {
  $params['handler'] += array('outputFilters' => array());
  $params['handler']['outputFilters'] += Message::aliases();
  return $chain->next($self, $params, $chain);
});

echo lithiumactionDispatcher::run(new lithiumactionRequest());
$locale = 'en';
$locales = array('en' => 'English');

Environment::set('development', compact('locale', 'locales'));
Environment::set('development'); }
    $file = "{$config['path']}/config/routes.php";
    file_exists($file) ? call_user_func(function() use ($file) { include $file; }) : null;
  }
  return $chain->next($self, $params, $chain);
});

Media::applyFilter('_handle', function($self, $params, $chain) {
  $params['handler'] += array('outputFilters' => array());
  $params['handler']['outputFilters'] += Message::aliases();
  return $chain->next($self, $params, $chain);
                                                                                             Gets
});                                                                                      translations
echo lithiumactionDispatcher::run(new lithiumactionRequest());
$locale = 'en';
$locales = array('en' => 'English');

Environment::set('development', compact('locale', 'locales'));
Environment::set('development'); }
    $file = "{$config['path']}/config/routes.php";
    file_exists($file) ? call_user_func(function() use ($file) { include $file; }) : null;
  }
  return $chain->next($self, $params, $chain);
});

Media::applyFilter('_handle', function($self, $params, $chain) {
  $params['handler'] += array('outputFilters' => array());
  $params['handler']['outputFilters'] += Message::aliases();
  return $chain->next($self, $params, $chain);
});

echo lithiumactionDispatcher::run(new lithiumactionRequest());




                               Go
Recap
★ Hackers framework
                      Recap
★ Hackers framework
                      Recap
★ Light, fast & fun
★ Hackers framework
                            Recap
★ Light, fast & fun

★ Services have adaptable base
★ Hackers framework
                            Recap
★ Light, fast & fun

★ Services have adaptable base

★ Filters are awesome/powerful
★ Hackers framework
                            Recap
★ Light, fast & fun

★ Services have adaptable base

★ Filters are awesome/powerful

★ Everything is a library
★ Hackers framework
                            Recap
★ Light, fast & fun

★ Services have adaptable base

★ Filters are awesome/powerful

★ Everything is a library

★ As much or as little framework as you
  need
★ Hackers framework
                            Recap
★ Light, fast & fun

★ Services have adaptable base

★ Filters are awesome/powerful

★ Everything is a library

★ As much or as little framework as you
  need

★ Great balance weight/power/simplicity
Thanks
github.com/mackstar/phpnw-li3




   @mackstar | #mackstar

More Related Content

PDF
Current state-of-php
PDF
Building Lithium Apps
PDF
Lithium: The Framework for People Who Hate Frameworks, Tokyo Edition
PDF
The Origin of Lithium
PDF
The Zen of Lithium
PDF
Doctrine MongoDB ODM (PDXPHP)
PDF
Advanced symfony Techniques
PDF
Introducing Assetic (NYPHP)
Current state-of-php
Building Lithium Apps
Lithium: The Framework for People Who Hate Frameworks, Tokyo Edition
The Origin of Lithium
The Zen of Lithium
Doctrine MongoDB ODM (PDXPHP)
Advanced symfony Techniques
Introducing Assetic (NYPHP)

What's hot (20)

PDF
PHP 5.3 and Lithium: the most rad php framework
PDF
Dependency Injection IPC 201
PDF
Unit and Functional Testing with Symfony2
PDF
News of the Symfony2 World
PDF
SPL: The Missing Link in Development
PDF
Design Patterns avec PHP 5.3, Symfony et Pimple
PDF
Dependency injection - phpday 2010
PDF
Silex meets SOAP & REST
PPTX
Speed up your developments with Symfony2
PPT
Corephpcomponentpresentation 1211425966721657-8
PDF
PHP 5.3 Overview
PDF
Symfony2 - WebExpo 2010
PDF
Future of HTTP in CakePHP
PDF
Dependency injection in PHP 5.3/5.4
PDF
Advanced Querying with CakePHP 3
PDF
PhpBB meets Symfony2
PDF
New in cakephp3
PDF
Dependency Injection with PHP 5.3
PDF
Symfony2 - OSIDays 2010
PDF
The History of PHPersistence
PHP 5.3 and Lithium: the most rad php framework
Dependency Injection IPC 201
Unit and Functional Testing with Symfony2
News of the Symfony2 World
SPL: The Missing Link in Development
Design Patterns avec PHP 5.3, Symfony et Pimple
Dependency injection - phpday 2010
Silex meets SOAP & REST
Speed up your developments with Symfony2
Corephpcomponentpresentation 1211425966721657-8
PHP 5.3 Overview
Symfony2 - WebExpo 2010
Future of HTTP in CakePHP
Dependency injection in PHP 5.3/5.4
Advanced Querying with CakePHP 3
PhpBB meets Symfony2
New in cakephp3
Dependency Injection with PHP 5.3
Symfony2 - OSIDays 2010
The History of PHPersistence
Ad

Viewers also liked (20)

PPTX
چراغ پيشاني
PPT
Potassium2
PDF
Pan American Lithium Corp. Investor Presentation
PDF
The lithium market: 2010 review and outlook
PPT
GAC-MAC 2011 - Austman Et Al - Origin, Geology, and Composition of Fraser Lak...
PPT
Lithium Supply &amp; Markets 2010 Chairman\'s Opening Speech
PPTX
Extraction and Applications of Rare Earth Metals and Alloys (Uranium, Lithium...
PDF
Cypress Development Corp. Corporate Presentation
PPTX
Advantage Lithium Corporate Presentation
PPT
Lithium
PDF
International Lithium: Presentation Of Our Strategic Partner - Ganfeng Lithiu...
PDF
International Lithium Introduction Presentation
PPS
Parentswish
PDF
моап 2011 05
DOCX
The little ice age
PPTX
GözMobil
PDF
Visita monòverweb
PPTX
PPTX
[28 8] beantwoording 6 themavragen 1 september 2015
DOC
چراغ پيشاني
Potassium2
Pan American Lithium Corp. Investor Presentation
The lithium market: 2010 review and outlook
GAC-MAC 2011 - Austman Et Al - Origin, Geology, and Composition of Fraser Lak...
Lithium Supply &amp; Markets 2010 Chairman\'s Opening Speech
Extraction and Applications of Rare Earth Metals and Alloys (Uranium, Lithium...
Cypress Development Corp. Corporate Presentation
Advantage Lithium Corporate Presentation
Lithium
International Lithium: Presentation Of Our Strategic Partner - Ganfeng Lithiu...
International Lithium Introduction Presentation
Parentswish
моап 2011 05
The little ice age
GözMobil
Visita monòverweb
[28 8] beantwoording 6 themavragen 1 september 2015
Ad

Similar to Lithium Best (20)

KEY
Keeping it small: Getting to know the Slim micro framework
KEY
Keeping It Small with Slim
PDF
Keeping it Small: Getting to know the Slim Micro Framework
PDF
[Bristol WordPress] Supercharging WordPress Development
PDF
[WLDN] Supercharging word press development in 2018
ODP
CodeIgniter PHP MVC Framework
PDF
Keeping it small - Getting to know the Slim PHP micro framework
PPT
Lecture n
PPT
Language literacy
KEY
Dr. Strangelove or: How I learned to stop worrying and love HTML, CSS and Jav...
PDF
Using and reusing CakePHP plugins
PDF
RESTful API development in Laravel 4 - Christopher Pecoraro
PDF
CakePHP Fundamentals - 1.2 @ OCPHP
PDF
The State of Lithium
PDF
Supercharging WordPress Development - Wordcamp Brighton 2019
PPTX
Introduction to Codeigniter
PDF
20100730 phpstudy
PDF
Intro To Mvc Development In Php
PDF
Laravel intake 37 all days
KEY
Talkaboutlithium
Keeping it small: Getting to know the Slim micro framework
Keeping It Small with Slim
Keeping it Small: Getting to know the Slim Micro Framework
[Bristol WordPress] Supercharging WordPress Development
[WLDN] Supercharging word press development in 2018
CodeIgniter PHP MVC Framework
Keeping it small - Getting to know the Slim PHP micro framework
Lecture n
Language literacy
Dr. Strangelove or: How I learned to stop worrying and love HTML, CSS and Jav...
Using and reusing CakePHP plugins
RESTful API development in Laravel 4 - Christopher Pecoraro
CakePHP Fundamentals - 1.2 @ OCPHP
The State of Lithium
Supercharging WordPress Development - Wordcamp Brighton 2019
Introduction to Codeigniter
20100730 phpstudy
Intro To Mvc Development In Php
Laravel intake 37 all days
Talkaboutlithium

More from Richard McIntyre (8)

PDF
Why Message Driven?
PDF
Semantic BDD with ShouldIT?
PDF
Spout - Building a RESTful web app with Angular.js and BEAR.Sunday
PDF
What is this DI and AOP stuff anyway...
KEY
Using Backbone with CakePHP
KEY
Future of PHP
Why Message Driven?
Semantic BDD with ShouldIT?
Spout - Building a RESTful web app with Angular.js and BEAR.Sunday
What is this DI and AOP stuff anyway...
Using Backbone with CakePHP
Future of PHP

Lithium Best

  • 1. Lithium (#li3) The framework with the best of both worlds
  • 2. Richard McIntyre: @mackstar ★ Lithium core team ★ Freelancer - Leeds/Manchester ★ Most recently at BBC, Mamas & Papas, UOR ★ Engineer on BBC Olympics App ★ Lived in Japan 15 years ★ Done PHP for donkeys
  • 6. I’ve seen it ✦ Symfony 2 ✦ Merb ✦ Zend Framework ✦ Sinatra ✦ CakePHP ✦ Spring ✦ Code Igniter ✦ Stripes (Java) ✦ Drupal 6&7 ✦ Django Wordpress ✦ Silex ✦ ✦ Rails
  • 9. Each software solution should be in proportion to the problem being solved.
  • 10. Each software solution should be in proportion to the problem being solved. -some lazy bugger
  • 11. Each software solution should be in proportion to the problem being solved. -some lazy bugger me
  • 12. <?php use BehatMinkExtensionContextMinkContext; class FeatureContext extends MinkContext { /** * @Then /^I wait for the suggestion box to appear$/ */ public function myNameHasAMeaninglessExistance() { $this->getSession()->wait(5000, "$('.suggestions-results').children().length > 0"); } }
  • 13. All problems in computer science can be solved by another level of indirection. Except for the problem of too many layers of indirection. Butler Lampson, David Wheeler
  • 14. Code Sexy-ness There’s nothing like the look of beautiful Ruby code in the morning. Gracefully colored by TextMate and rendered in Bitstream Vera pt 12. @dhh
  • 15. Developer Happy-ness Any fool can write code that a computer can understand. Good programmers write code that humans can understand. –Martin Fowler
  • 18. Looking for a hackers Framework? Light Footprint
  • 20. World 1 Full Stack Framework Convention Over Configuration
  • 22. The Photo Blog Tutorial github.com/nateabele/photoblog
  • 23. Model namespace photoblogmodels; class Photos extends lithiumdataModel { public $validates = array(); protected $_meta = array('source' => 'fs.files'); public function save($entity, $data = null, array $options = array()) { if ($data) { $entity->set($data); } if ($entity->tags && !is_array($entity->tags)) { $entity->tags = array_map('trim', explode(',', $entity->tags)); } return parent::save($entity, null, $options); } }
  • 24. Model namespace photoblogmodels; class Photos extends lithiumdataModel { public $validates = array(); protected $_meta = array('source' => 'fs.files'); public function save($entity, $data = null, array $options = array()) { if ($data) { $entity->set($data); } if ($entity->tags && !is_array($entity->tags)) { $entity->tags = array_map('trim', explode(',', $entity->tags)); } return parent::save($entity, null, $options); } }
  • 25. Model namespace photoblogmodels; class Photos extends lithiumdataModel { public $validates = array(); protected $_meta = array('source' => 'fs.files'); public function save($entity, $data = null, array $options = array()) { if ($data) { $entity->set($data); } if ($entity->tags && !is_array($entity->tags)) { $entity->tags = array_map('trim', explode(',', $entity->tags)); } return parent::save($entity, null, $options); } }
  • 26. Views <?=$this->form->create($photo, array('type' => 'file')); ?> <?=$this->form->field('title'); ?> <?=$this->form->field('description'); ?> <?php if (!$photo->exists()): ?> <?=$this->form->field('file', array('type' => 'file')); ?> <?php endif; ?> <?=$this->form->field('tags', array('label' => 'Add tags separated by commas')); ?> <?=$this->form->submit('Save'); ?> <?=$this->form->end(); ?>
  • 27. Views <?=$this->form->create($photo, array('type' => 'file')); ?> <?=$this->form->field('title'); ?> <?=$this->form->field('description'); ?> <?php if (!$photo->exists()): ?> <?=$this->form->field('file', array('type' => 'file')); ?> <?php endif; ?> <?=$this->form->field('tags', array('label' => 'Add tags separated by commas')); ?> <?=$this->form->submit('Save'); ?> <?=$this->form->end(); ?>
  • 28. Views <?=$this->form->create($photo, array('type' => 'file')); ?> <?=$this->form->field('title'); ?> <?=$this->form->field('description'); ?> <?php if (!$photo->exists()): ?> <?=$this->form->field('file', array('type' => 'file')); ?> <?php endif; ?> <?=$this->form->field('tags', array('label' => 'Add tags separated by commas')); ?> <?=$this->form->submit('Save'); ?> <?=$this->form->end(); ?>
  • 29. <h1> <?=$this->title($photo->title); ?> <em>[ <?=$this->html->link( 'edit', array('Photos::edit', 'id' => $photo->_id) ); ?> ]</em> </h1> <p><?=$photo->description; ?></p> <?php if ($photo->tags): ?> Tags: <?php foreach ($photo->tags as $tag): ?> <?=$this->html->link( $tag, array('Photos::index', 'args' => array($tag)) ); ?> <?php endforeach; ?> <?php endif; ?> <?=$this->html->image( "/photos/view/{$photo->_id}.jpeg", array( 'alt' => $photo->title, 'width' => "100%" ) ); ?>
  • 30. <h1> <?=$this->title($photo->title); ?> <em>[ <?=$this->html->link( 'edit', array('Photos::edit', 'id' => $photo->_id) ); ?> ]</em> </h1> <p><?=$photo->description; ?></p> <?php if ($photo->tags): ?> Tags: <?php foreach ($photo->tags as $tag): ?> <?=$this->html->link( $tag, array('Photos::index', 'args' => array($tag)) ); ?> <?php endforeach; ?> <?php endif; ?> <?=$this->html->image( "/photos/view/{$photo->_id}.jpeg", array( 'alt' => $photo->title, 'width' => "100%" ) ); ?>
  • 31. <h1> <?=$this->title($photo->title); ?> <em>[ <?=$this->html->link( 'edit', array('Photos::edit', 'id' => $photo->_id) ); ?> ]</em> </h1> <p><?=$photo->description; ?></p> <?php if ($photo->tags): ?> Tags: <?php foreach ($photo->tags as $tag): ?> <?=$this->html->link( $tag, array('Photos::index', 'args' => array($tag)) ); ?> <?php endforeach; ?> <?php endif; ?> <?=$this->html->image( "/photos/view/{$photo->_id}.jpeg", array( 'alt' => $photo->title, 'width' => "100%" ) ); ?>
  • 32. Controller namespace photoblogcontrollers; use photoblogmodelsPhotos; use li3_geoextensionsGeocoder; class PhotosController extends lithiumactionController { public function index($tags = null) { $conditions = $tags ? compact('tags') : array(); $photos = Photos::all(compact('conditions')); return compact('photos'); } public function view() { $photo = Photos::first($this->request->id); return compact('photo'); }
  • 33. Controller namespace photoblogcontrollers; use photoblogmodelsPhotos; use li3_geoextensionsGeocoder; class PhotosController extends lithiumactionController { public function index($tags = null) { $conditions = $tags ? compact('tags') : array(); $photos = Photos::all(compact('conditions')); return compact('photos'); } public function view() { $photo = Photos::first($this->request->id); return compact('photo'); }
  • 34. Controller namespace photoblogcontrollers; use photoblogmodelsPhotos; use li3_geoextensionsGeocoder; class PhotosController extends lithiumactionController { public function index($tags = null) { $conditions = $tags ? compact('tags') : array(); $photos = Photos::all(compact('conditions')); return compact('photos'); } public function view() { $photo = Photos::first($this->request->id); return compact('photo'); }
  • 35. public function near($place = null) { $this->_render['template'] = 'index'; $coords = Geocoder::find('google', $place); $photos = Photos::within(array($coords, $coords), array('limit' => 1)); return compact('photos'); } public function add() { $photo = Photos::create(); if (($this->request->data) && $photo->save($this->request->data)) { $this->redirect(array('Photos::view', 'id' => $photo->_id)); } $this->_render['template'] = 'edit'; return compact('photo'); } public function edit() { $photo = Photos::find($this->request->id); if (!$photo) { $this->redirect('Photos::index'); } if (($this->request->data) && $photo->save($this->request->data)) { $this->redirect(array('Photos::view', 'id' => $photo->_id)); } return compact('photo'); }
  • 36. public function near($place = null) { $this->_render['template'] = 'index'; $coords = Geocoder::find('google', $place); $photos = Photos::within(array($coords, $coords), array('limit' => 1)); return compact('photos'); } public function add() { $photo = Photos::create(); Geo Location if (($this->request->data) && $photo->save($this->request->data)) { $this->redirect(array('Photos::view', 'id' => $photo->_id)); } $this->_render['template'] = 'edit'; return compact('photo'); } public function edit() { $photo = Photos::find($this->request->id); if (!$photo) { $this->redirect('Photos::index'); } if (($this->request->data) && $photo->save($this->request->data)) { $this->redirect(array('Photos::view', 'id' => $photo->_id)); } return compact('photo'); }
  • 37. Routes use lithiumnethttpRouter; use lithiumcoreEnvironment; use lithiumactionResponse; use photoblogmodelsPhotos; Router::connect('/photos/view/{:id:[0-9a-f]{24}}.jpeg', array(), function($request) { return new Response(array( 'headers' => array('Content-type' => 'image/jpeg'), 'body' => Photos::first($request->id)->file->getBytes() )); }); /** * Connect the testing routes. */ if (!Environment::is('production')) { Router::connect('/test/{:args}', array('controller' => 'lithiumtestController')); Router::connect('/test', array('controller' => 'lithiumtestController')); }
  • 38. Routes use lithiumnethttpRouter; use lithiumcoreEnvironment; use lithiumactionResponse; use photoblogmodelsPhotos; Router::connect('/photos/view/{:id:[0-9a-f]{24}}.jpeg', array(), function($request) { return new Response(array( 'headers' => array('Content-type' => 'image/jpeg'), 'body' => Photos::first($request->id)->file->getBytes() )); }); /** * Connect the testing routes. By-Passes */ if (!Environment::is('production')) { the framework Router::connect('/test/{:args}', array('controller' => 'lithiumtestController')); Router::connect('/test', array('controller' => 'lithiumtestController')); }
  • 39. Routes use lithiumnethttpRouter; use lithiumcoreEnvironment; use lithiumactionResponse; use It’s PHP you can photoblogmodelsPhotos; Router::connect('/photos/view/{:id:[0-9a-f]{24}}.jpeg', array(), function($request) { return new Response(array( you doarray('Content-type' => 'image/jpeg'), what 'headers' => want 'body' => Photos::first($request->id)->file->getBytes() )); }); /** * Connect the testing routes. */ if (!Environment::is('production')) { Router::connect('/test/{:args}', array('controller' => 'lithiumtestController')); Router::connect('/test', array('controller' => 'lithiumtestController')); }
  • 41. Features ✦ Full stack MVC ✦ Object based record- sets ✦ Logger ✦ Command Line ✦ Caching Framework ✦ Sessions/Cookies ✦ Authentication ✦ Full templating suite ✦ Validator ✦ Integrated TDD suite ✦ Http Services
  • 43. Now for some fun!
  • 44. World 2 Kick-ass de-coupled hacker happy framework
  • 45. Are you a slave to your framework?
  • 49. Database namespace models; class Posts extends lithiumdataModel { }
  • 50. define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries'); require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php'; use lithiumcoreLibraries; Libraries::add('lithium'); use lithiumdataConnections; Connections::add('default', array( 'type' => 'MongoDb', 'database' => 'phpnw', 'host' => 'localhost' )); Libraries::add('models', array('path' => __DIR__ . '/models')); use modelsPosts; $posts = Posts::create(array('title' => 'Hi Guys')); $posts->save();
  • 51. define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries'); require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php'; use lithiumcoreLibraries; Libraries::add('lithium'); Simple lithium setup use lithiumdataConnections; Connections::add('default', array( 'type' => 'MongoDb', 'database' => 'phpnw', 'host' => 'localhost' )); Libraries::add('models', array('path' => __DIR__ . '/models')); use modelsPosts; $posts = Posts::create(array('title' => 'Hi Guys')); $posts->save();
  • 52. define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries'); require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php'; use lithiumcoreLibraries; Libraries::add('lithium'); use lithiumdataConnections; Connections::add('default', array( 'type' => 'MongoDb', 'database' => 'phpnw', DB Config 'host' => 'localhost' )); Libraries::add('models', array('path' => __DIR__ . '/models')); use modelsPosts; $posts = Posts::create(array('title' => 'Hi Guys')); $posts->save();
  • 53. define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries'); require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php'; use lithiumcoreLibraries; Libraries::add('lithium'); use lithiumdataConnections; Connections::add('default', array( 'type' => 'MongoDb', 'database' => 'phpnw', 'host' => 'localhost' )); Add models ‘app’ Libraries::add('models', array('path' => __DIR__ . '/models')); use modelsPosts; $posts = Posts::create(array('title' => 'Hi Guys')); $posts->save();
  • 54. define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries'); require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php'; use lithiumcoreLibraries; Libraries::add('lithium'); use lithiumdataConnections; Connections::add('default', array( 'type' => 'MongoDb', 'database' => 'phpnw', 'host' => 'localhost' )); DB Save Libraries::add('models', array('path' => __DIR__ . '/models')); use modelsPosts; $posts = Posts::create(array('title' => 'Hi Guys')); $posts->save();
  • 55. Routes define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries'); require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php'; use lithiumcoreLibraries; Libraries::add('lithium'); use lithiumnethttpRouter; use lithiumactionRequest; $request = new Request(); $router = new Router(); $router->connect('/cool-root', array('controller' => 'Yea')); $router->connect('/cool-root/{:application_id:[0-9]{1}}', array('controller' => 'Yea')); $router->parse($request); echo Router::match('Yea::index'); echo Router::match(array('Yea::index', 'application_id' => 1));
  • 56. Routes define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries'); require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php'; use lithiumcoreLibraries; Libraries::add('lithium'); use lithiumnethttpRouter; use lithiumactionRequest; $request = new Request(); $router = new Router(); $router->connect('/cool-root', array('controller' => 'Yea')); $router->connect('/cool-root/{:application_id:[0-9]{1}}', array('controller' => 'Yea')); $router->parse($request); echo Router::match('Yea::index'); echo Router::match(array('Yea::index', 'application_id' => 1));
  • 57. Routes define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries'); require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php'; use lithiumcoreLibraries; Libraries::add('lithium'); use lithiumnethttpRouter; use lithiumactionRequest; $request = new Request(); $router = new Router(); $router->connect('/cool-root', array('controller' => 'Yea')); $router->connect('/cool-root/{:application_id:[0-9]{1}}', array('controller' => 'Yea')); $router->parse($request); echo Router::match('Yea::index'); echo Router::match(array('Yea::index', 'application_id' => 1));
  • 58. Routes define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries'); require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php'; use lithiumcoreLibraries; Libraries::add('lithium'); use lithiumnethttpRouter; use lithiumactionRequest; $request = new Request(); $router = new Router(); $router->connect('/cool-root', array('controller' => 'Yea')); $router->connect('/cool-root/{:application_id:[0-9]{1}}', array('controller' => 'Yea')); $router->parse($request); echo Router::match('Yea::index'); echo Router::match(array('Yea::index', 'application_id' => 1));
  • 62. /cool-root/4 $router->connect('/cool-root/{:application_id:[0-9]{1}}', array('controller' => 'Yea')); object(lithiumactionRequest)[1] public 'url' => string '/cool-root/4' (length=12) public 'params' => array (size=3) 'application_id' => string '4' (length=1) 'controller' => string 'Yea' (length=3) 'action' => string 'index' (length=5)
  • 63. Adaptable Classes define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries'); define('LITHIUM_APP_PATH', __DIR__); require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php'; require LITHIUM_LIBRARY_PATH . '/lithium/core/Object.php'; require LITHIUM_LIBRARY_PATH . '/lithium/core/StaticObject.php'; require LITHIUM_LIBRARY_PATH . '/lithium/core/Environment.php'; require LITHIUM_LIBRARY_PATH . '/lithium/core/Adaptable.php'; use lithiumcoreAdaptable; class Email extends Adaptable{ protected static $_configurations = array(); protected static $_adapters = 'emails'; }
  • 64. Adaptable Classes define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries'); define('LITHIUM_APP_PATH', __DIR__); require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php'; require LITHIUM_LIBRARY_PATH . '/lithium/core/Object.php'; require LITHIUM_LIBRARY_PATH . '/lithium/core/StaticObject.php'; require LITHIUM_LIBRARY_PATH . '/lithium/core/Environment.php'; require LITHIUM_LIBRARY_PATH . '/lithium/core/Adaptable.php'; use lithiumcoreAdaptable; class Email extends Adaptable{ protected static $_configurations = array(); protected static $_adapters = 'emails'; }
  • 65. namespace adapters; use lithiumcoreLibraries; Libraries::add('lithium'); class EmailTest Libraries::add('adapters', { array('path' => __DIR__ . '/adapters')); public function send() { Libraries::paths( echo 'email test send'; array('emails' => array( } '{:library}{:name}'))); } Email::config(array( 'development' => array( 'adapter' => 'EmailReal' ), namespace adapters; 'test' => array( 'adapter' => 'EmailTest' class EmailReal ), { )); public function send() { echo 'email real send'; use lithiumcoreEnvironment; } } Environment::set('test'); $env = Environment::get(); Email::adapter($env)->send();
  • 66. namespace adapters; use lithiumcoreLibraries; Libraries::add('lithium'); class EmailTest Libraries::add('adapters', { array('path' => __DIR__ . '/adapters')); public function send() { Libraries::paths( echo 'email test send'; array('emails' => array( } '{:library}{:name}'))); } Email::config(array( 'development' => array( 'adapter' => 'EmailReal' ), namespace adapters; 'test' => array( 'adapter' => 'EmailTest' class EmailReal ), { )); public function send() { echo 'email real send'; use lithiumcoreEnvironment; } } Environment::set('test'); $env = Environment::get(); Email::adapter($env)->send();
  • 67. namespace adapters; use lithiumcoreLibraries; Libraries::add('lithium'); class EmailTest Libraries::add('adapters', { array('path' => __DIR__ . '/adapters')); public function send() { Libraries::paths( echo 'email test send'; array('emails' => array( } '{:library}{:name}'))); } Email::config(array( 'development' => array( 'adapter' => 'EmailReal' ), namespace adapters; 'test' => array( 'adapter' => 'EmailTest' class EmailReal ), { )); public function send() { echo 'email real send'; use lithiumcoreEnvironment; } } Environment::set('test'); $env = Environment::get(); Email::adapter($env)->send();
  • 68. namespace adapters; use lithiumcoreLibraries; Libraries::add('lithium'); class EmailTest Libraries::add('adapters', { array('path' => __DIR__ . '/adapters')); public function send() { Libraries::paths( echo 'email test send'; array('emails' => array( } '{:library}{:name}'))); } Email::config(array( 'development' => array( 'adapter' => 'EmailReal' ), namespace adapters; 'test' => array( 'adapter' => 'EmailTest' class EmailReal ), { )); public function send() { echo 'email real send'; use lithiumcoreEnvironment; } } Environment::set('test'); $env = Environment::get(); Email::adapter($env)->send();
  • 69. Environment::set('development'); class EmailAnother extends Adaptable{ Already protected static $_configurations = array(); protected static $_adapters = 'emails'; Environment public static function send() { static::adapter('default')->send(); Aware } } EmailAnother::config(array( 'default' => array( 'test' => array ( 'adapter' => 'EmailTest' ), 'development' => array( 'adapter' => 'EmailReal' ), ) )); EmailAnother::send();
  • 70. Environment::set('development'); class EmailAnother extends Adaptable{ Already protected static $_configurations = array(); protected static $_adapters = 'emails'; Environment public static function send() { static::adapter('default')->send(); Aware } } EmailAnother::config(array( 'default' => array( 'test' => array ( 'adapter' => 'EmailTest' ), 'development' => array( 'adapter' => 'EmailReal' ), ) )); EmailAnother::send();
  • 71. Environment::set('development'); class EmailAnother extends Adaptable{ Already protected static $_configurations = array(); protected static $_adapters = 'emails'; Environment public static function send() { static::adapter('default')->send(); Aware } } EmailAnother::config(array( 'default' => array( 'test' => array ( 'adapter' => 'EmailTest' ), 'development' => array( 'adapter' => 'EmailReal' ), ) )); EmailAnother::send();
  • 72. Environment::set('development'); class EmailAnother extends Adaptable{ Already protected static $_configurations = array(); protected static $_adapters = 'emails'; Environment public static function send() { static::adapter('default')->send(); Aware } } EmailAnother::config(array( 'default' => array( 'test' => array ( 'adapter' => 'EmailTest' ), 'development' => array( 'adapter' => 'EmailReal' ), ) )); EmailAnother::send();
  • 74. define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries'); require LITHIUM_LIBRARY_PATH . '/lithium/core/Object.php'; require LITHIUM_LIBRARY_PATH . '/lithium/util/Collection.php'; require LITHIUM_LIBRARY_PATH . '/lithium/util/collection/Filters.php'; class Action extends lithiumcoreObject { public function doSomethingStupid() { return $this->_filter(__METHOD__, $params, function($self, $params) { $result = ‘Your girlfriend is angry at you’; return $result; }); } } $action = new Action; $action->applyFilter('doSomethingStupid', function($self, $params, $chain) { echo 'About to do something stupid,'; $result = $chain->next($self, $params, $chain); echo 'You IDIOT!!!!!'; return $result; }); $action->doSomthingStupid();
  • 75. define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries'); require LITHIUM_LIBRARY_PATH . '/lithium/core/Object.php'; require LITHIUM_LIBRARY_PATH . '/lithium/util/Collection.php'; require LITHIUM_LIBRARY_PATH . '/lithium/util/collection/Filters.php'; class Action extends lithiumcoreObject { public function doSomethingStupid() { return $this->_filter(__METHOD__, $params, function($self, $params) { $result = ‘Your girlfriend is angry at you’; return $result; } }); Make } Filterable $action = new Action; $action->applyFilter('doSomethingStupid', function($self, $params, $chain) { echo 'About to do something stupid,'; $result = $chain->next($self, $params, $chain); echo 'You IDIOT!!!!!'; return $result; }); $action->doSomthingStupid();
  • 76. define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries'); require LITHIUM_LIBRARY_PATH . '/lithium/core/Object.php'; require LITHIUM_LIBRARY_PATH . '/lithium/util/Collection.php'; require LITHIUM_LIBRARY_PATH . '/lithium/util/collection/Filters.php'; class Action extends lithiumcoreObject { public function doSomethingStupid() { return $this->_filter(__METHOD__, $params, function($self, $params) { $result = ‘Your girlfriend is angry at you’; return $result; }); } } $action = new Action; $action->applyFilter('doSomethingStupid', function($self, $params, $chain) { echo 'About to do something stupid,'; $result = $chain->next($self, $params, $chain); echo 'You IDIOT!!!!!'; return $result; }); $action->doSomthingStupid();
  • 77. use lithiumanalysisLogger; Logger::config(array( 'default' => array( 'adapter' => 'File', 'path' => __DIR__ . '/crap/logs/' ) )); $action = new Action; $action->applyFilter('doSomethingStupid', function($self, $params, $chain) { Logger::debug(date("D M j G:i:s") . " " . 'About to do something stupid,'); $result = $chain->next($self, $params, $chain); Logger::debug(date("D M j G:i:s") . " " . 'You total moron!'); return $result; }); $action->doSomthingStupid();
  • 78. use lithiumanalysisLogger; Logger::config(array( 'default' => array( 'adapter' => 'File', 'path' => __DIR__ . '/crap/logs/' ) )); $action = new Action; $action->applyFilter('doSomethingStupid', function($self, $params, $chain) { Logger::debug(date("D M j G:i:s") . " " . 'About to do something stupid,'); $result = $chain->next($self, $params, $chain); Logger::debug(date("D M j G:i:s") . " " . 'You total moron!'); return $result; }); $action->doSomthingStupid();
  • 79. use lithiumanalysisLogger; Logger::config(array( 'default' => array( 'adapter' => 'File', 'path' => __DIR__ . '/crap/logs/' ) )); $action = new Action; $action->applyFilter('doSomethingStupid', function($self, $params, $chain) { Logger::debug(date("D M j G:i:s") . " " . 'About to do something stupid,'); $result = $chain->next($self, $params, $chain); Logger::debug(date("D M j G:i:s") . " " . 'You total moron!'); return $result; }); $action->doSomthingStupid();
  • 80. use lithiumanalysisLogger; Logger::config(array( 'default' => array( 'adapter' => 'File', 'path' => __DIR__ . '/crap/logs/' ) )); $action = new Action; $action->applyFilter('doSomethingStupid', function($self, $params, $chain) { Logger::debug(date("D M j G:i:s") . " " . 'About to do something stupid,'); $result = $chain->next($self, $params, $chain); Logger::debug(date("D M j G:i:s") . " " . 'You total moron!'); return $result; }); $action->doSomthingStupid();
  • 82. Find
  • 88. Posts::applyFilter('find', function($self, $params, $chain) { $result = $chain->next($self, $params, $chain); $search = http_build_query($params['options']); Logger::debug( 'Search for: ' . $search . 'returned' . $result->to('json') ); return $result; }); Posts::applyFilter('find', function($self, $params, $chain) { $key = // Make a cache key from params['options'] if ($result = Cache::read('default', $key)) { return $result; } $result = $chain->next($self, $params, $chain); Cache::write('default', $key, $result)); return $result; });
  • 89. Posts::applyFilter('find', function($self, $params, $chain) { $result = $chain->next($self, $params, $chain); $search = http_build_query($params['options']); Logger::debug( 'Search for: ' . $search . 'returned' . $result->to('json') ); return $result; }); Logging Filter Posts::applyFilter('find', function($self, $params, $chain) { $key = // Make a cache key from params['options'] if ($result = Cache::read('default', $key)) { return $result; } $result = $chain->next($self, $params, $chain); Cache::write('default', $key, $result)); return $result; });
  • 90. Posts::applyFilter('find', function($self, $params, $chain) { $result = $chain->next($self, $params, $chain); $search = http_build_query($params['options']); Logger::debug( ); Caching Filter 'Search for: ' . $search . 'returned' . $result->to('json') return $result; }); Posts::applyFilter('find', function($self, $params, $chain) { $key = // Make a cache key from params['options'] if ($result = Cache::read('default', $key)) { return $result; } $result = $chain->next($self, $params, $chain); Cache::write('default', $key, $result)); return $result; });
  • 91. Full Page Caching Cache::config(array( 'default' => array( 'adapter' => 'lithiumstoragecacheadapter' . ($apcEnabled ? 'Apc' : 'File') ) )); Dispatcher::applyFilter('run', function($self, $params, $chain) { $key = md5(LITHIUM_APP_PATH) . '.app.cache.'.md5($params['request']->url); if($cache = Cache::read('default', $key)) { return $cache; } $result = $chain->next($self, $params, $chain); Cache::write('default', $key, $result, '+1 day'); return $result; });
  • 92. Full Page Caching Set Cache Configuration Cache::config(array( 'default' => array( 'adapter' => 'lithiumstoragecacheadapter' . ($apcEnabled ? 'Apc' : 'File') ) )); Dispatcher::applyFilter('run', function($self, $params, $chain) { $key = md5(LITHIUM_APP_PATH) . '.app.cache.'.md5($params['request']->url); if($cache = Cache::read('default', $key)) { return $cache; } $result = $chain->next($self, $params, $chain); Cache::write('default', $key, $result, '+1 day'); return $result; });
  • 93. Full Page Caching Cache::config(array( 'default' => array( 'adapter' => 'lithiumstoragecacheadapter' . ($apcEnabled ? 'Apc' : 'File') ) )); Dispatcher::applyFilter('run', function($self, $params, $chain) { $key = md5(LITHIUM_APP_PATH) . '.app.cache.'.md5($params['request']->url); if($cache = Cache::read('default', $key)) { return $cache; } $result = $chain->next($self, $params, $chain); Filter on Dispatcher::run Cache::write('default', $key, $result, '+1 day'); Checks for cache w/key return $result; });
  • 94. Full Page Caching Cache::config(array( 'default' => array( 'adapter' => 'lithiumstoragecacheadapter' . ($apcEnabled ? 'Apc' : 'File') ) )); w/out cache content carry on Dispatcher::applyFilter('run', function($self, $params, $chain) { $key = md5(LITHIUM_APP_PATH) . '.app.cache.'.md5($params['request']->url); running - saving to cache if($cache = Cache::read('default', $key)) { return $cache; } $result = $chain->next($self, $params, $chain); Cache::write('default', $key, $result, '+1 day'); return $result; });
  • 95. Content Rendering namespace dispatcher_appcontrollers; class YeaController extends lithiumactionController{ public function index() { $yeah = true; return compact('yeah'); } public function render(array $options = array()) { return 'The response of Yeah is: ' . $this->_render['data']['yeah']; } }
  • 96. Content Rendering namespace dispatcher_appcontrollers; class YeaController extends lithiumactionController{ public function index() { $yeah = true; return compact('yeah'); } public function render(array $options = array()) { return 'The response of Yeah is: ' . $this->_render['data']['yeah']; } }
  • 97. Content Rendering namespace dispatcher_appcontrollers; class YeaController extends lithiumactionController{ public function index() { $yeah = true; Overwrite ‘render’ method return compact('yeah'); } public function render(array $options = array()) { return 'The response of Yeah is: ' . $this->_render['data']['yeah']; } }
  • 98. define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries'); require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php'; use lithiumcoreLibraries; Libraries::add('lithium'); Libraries::add('dispatcher_app', array('path' => __DIR__ . '/dispatcher_app')); use lithiumnethttpRouter; $router = new Router(); Router::connect('/cool-root', array('controller' => 'Yea', 'library' => 'dispatcher_app')); echo lithiumactionDispatcher::run( new lithiumactionRequest() );
  • 99. define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries'); require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php'; use lithiumcoreLibraries; Libraries::add('lithium'); Create Routing Libraries::add('dispatcher_app', array('path' => __DIR__ . '/dispatcher_app')); use lithiumnethttpRouter; $router = new Router(); Router::connect('/cool-root', array('controller' => 'Yea', 'library' => 'dispatcher_app')); echo lithiumactionDispatcher::run( new lithiumactionRequest() );
  • 100. define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries'); require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php'; use lithiumcoreLibraries; Libraries::add('lithium'); Libraries::add('dispatcher_app', array('path' => __DIR__ . '/dispatcher_app')); use lithiumnethttpRouter; $router = new Router(); Run Dispatcher Router::connect('/cool-root', array('controller' => 'Yea', 'library' => 'dispatcher_app')); echo lithiumactionDispatcher::run( new lithiumactionRequest() );
  • 102. Media::type('ajax', array('application/xhtml+xml', 'text/html'), array( 'view' => 'lithiumtemplateView', 'paths' => array( 'template' => array( '{:library}/views/{:controller}/{:template}.ajax.php', '{:library}/views/{:controller}/{:template}.html.php' ), 'layout' => '{:library}/views/layouts/default.ajax.php' ), 'conditions' => array('ajax' => true) )); Easily setup template paths
  • 103. Media::type('jpg', 'image/jpeg', array('cast' => false, 'encode' => function($data) { return $data['photo']->file->getBytes(); })); Media::type('json', 'application/json', array('cast' => false, 'encode' => function($data) { return json_encode($data); })); Media::type('json', 'application/json', array( 'cast' => false, 'encode' => 'json_encode') );
  • 104. Media::type('jpg', 'image/jpeg', array('cast' => false, 'encode' => function($data) { return $data['photo']->file->getBytes(); })); Handle Images Media::type('json', 'application/json', array('cast' => false, 'encode' => function($data) { return json_encode($data); })); Media::type('json', 'application/json', array( 'cast' => false, 'encode' => 'json_encode') );
  • 105. Media::type('jpg', 'image/jpeg', array('cast' => false, 'encode' => function($data) { return $data['photo']->file->getBytes(); })); Media::type('json', 'application/json', array('cast' => false, 'encode' => function($data) { return json_encode($data); })); Media::type('json', 'application/json', array( 'cast' => false, 'encode' => 'json_encode') ); Handle JSON
  • 107. Error Handling use lithiumcoreErrorHandler; use lithiumcoreStaticObject; class IThrowAnException { public function method() { throw new Exception('Yo'); } } class IDontThrow extends StaticObject { public static function method($bar) { static::_filter(__FUNCTION__, $params, function($self, $params) { $object = new IThrowAnException; $object->method(); }); } } ErrorHandler::apply('IDontThrow::method', array(), function($info, $params) { echo 'Exception raised with message - ' . $info['exception']->getMessage(); }); IDontThrowAnException::method();
  • 108. Error Handling use lithiumcoreErrorHandler; use lithiumcoreStaticObject; class IThrowAnException { public function method() { throw new Exception('Yo'); } } class IDontThrow extends StaticObject { public static function method($bar) { static::_filter(__FUNCTION__, $params, function($self, $params) { $object = new IThrowAnException; $object->method(); }); } } ErrorHandler::apply('IDontThrow::method', array(), function($info, $params) { echo 'Exception raised with message - ' . $info['exception']->getMessage(); }); IDontThrowAnException::method();
  • 109. Error Handling use lithiumcoreErrorHandler; use lithiumcoreStaticObject; class IThrowAnException { public function method() { throw new Exception('Yo'); } Filterable } class IDontThrow extends StaticObject { public static function method($bar) { static::_filter(__FUNCTION__, $params, function($self, $params) { $object = new IThrowAnException; $object->method(); }); } } ErrorHandler::apply('IDontThrow::method', array(), function($info, $params) { echo 'Exception raised with message - ' . $info['exception']->getMessage(); }); IDontThrowAnException::method();
  • 110. Error Handling use lithiumcoreErrorHandler; use lithiumcoreStaticObject; class IThrowAnException { public function method() { throw new Exception('Yo'); } } class IDontThrow extends StaticObject { public static function method($bar) { static::_filter(__FUNCTION__, $params, function($self, $params) { $object = new IThrowAnException; $object->method(); }); } } ErrorHandler::apply('IDontThrow::method', array(), function($info, $params) { echo 'Exception raised with message - ' . $info['exception']->getMessage(); }); IDontThrowAnException::method();
  • 111. ErrorHandler::apply('lithiumactionDispatcher::run', array(), function($info, $params) { $response = new Response(array( 'request' => $params['request'], 'status' => $info['exception']->getCode(), 'trace' => $info['exception']->getTrace(), )); Media::render($response, compact('info', 'params'), array( 'controller' => 'errors', 'template' => 'default', 'layout' => 'default', 'library' => 'golf', 'request' => $params['request'], )); return $response; }); Example
  • 112. Create ErrorHandler::apply('lithiumactionDispatcher::run', array(), function($info, $params) { Response $response = new Response(array( 'request' => $params['request'], 'status' => $info['exception']->getCode(), 'trace' => $info['exception']->getTrace(), )); Media::render($response, compact('info', 'params'), array( 'controller' => 'errors', 'template' => 'default', 'layout' => 'default', 'library' => 'golf', 'request' => $params['request'], )); return $response; }); Example
  • 113. ErrorHandler::apply('lithiumactionDispatcher::run', array(), function($info, $params) { $response = new Response(array( 'request' => $params['request'], 'status' => $info['exception']->getCode(), 'trace' => $info['exception']->getTrace(), )); Media::render($response, compact('info', 'params'), array( 'controller' => 'errors', 'template' => 'default', 'layout' => 'default', 'library' => 'golf', Media 'request' => $params['request'], Render )); return $response; }); Example
  • 114. Zendy Love Libraryies::add( 'prefix' => 'Zend_', 'includePath' => '/htdocs/libraries/Zend/trunk/library', 'bootstrap' => 'Loader/Autoloader.php', 'loader' => array('Zend_Loader_Autoloader', 'autoload'), 'transform' => function($class) { return str_replace('_', '/', $class) . '.php'; } );
  • 115. define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries'); define('LITHIUM_APP_PATH', __DIR__ . '/templates'); require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php'; use lithiumcoreLibraries; use lithiumcoreEnvironment; use lithiumactionDispatcher; use lithiumg11nMessage; use lithiumnethttpMedia; Libraries::add('lithium'); Libraries::add('li3_docs'); Libraries::add('templates', array('path' => __DIR__ . '/templates', 'default' => true)); Libraries::add('adapters', array('path' => __DIR__ . '/adapters')); Libraries::add('li3_docs', array( 'index' => array('lithium', 'adapters') )); Libraries Example
  • 116. define('LITHIUM_LIBRARY_PATH', dirname(__DIR__) . '/libraries'); define('LITHIUM_APP_PATH', __DIR__ . '/templates'); require LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php'; use lithiumcoreLibraries; Sets up use lithiumcoreEnvironment; use use lithiumactionDispatcher; lithiumg11nMessage; Libraries use lithiumnethttpMedia; Libraries::add('lithium'); Libraries::add('li3_docs'); Libraries::add('templates', array('path' => __DIR__ . '/templates', 'default' => true)); Libraries::add('adapters', array('path' => __DIR__ . '/adapters')); Libraries::add('li3_docs', array( 'index' => array('lithium', 'adapters') )); Libraries Example
  • 117. $locale = 'en'; $locales = array('en' => 'English'); Environment::set('development', compact('locale', 'locales')); Environment::set('development'); } $file = "{$config['path']}/config/routes.php"; file_exists($file) ? call_user_func(function() use ($file) { include $file; }) : null; } return $chain->next($self, $params, $chain); }); Media::applyFilter('_handle', function($self, $params, $chain) { $params['handler'] += array('outputFilters' => array()); $params['handler']['outputFilters'] += Message::aliases(); return $chain->next($self, $params, $chain); }); echo lithiumactionDispatcher::run(new lithiumactionRequest());
  • 118. Locale & $locale = 'en'; Routes $locales = array('en' => 'English'); Environment::set('development', compact('locale', 'locales')); Environment::set('development'); } $file = "{$config['path']}/config/routes.php"; file_exists($file) ? call_user_func(function() use ($file) { include $file; }) : null; } return $chain->next($self, $params, $chain); }); Media::applyFilter('_handle', function($self, $params, $chain) { $params['handler'] += array('outputFilters' => array()); $params['handler']['outputFilters'] += Message::aliases(); return $chain->next($self, $params, $chain); }); echo lithiumactionDispatcher::run(new lithiumactionRequest());
  • 119. $locale = 'en'; $locales = array('en' => 'English'); Environment::set('development', compact('locale', 'locales')); Environment::set('development'); } $file = "{$config['path']}/config/routes.php"; file_exists($file) ? call_user_func(function() use ($file) { include $file; }) : null; } return $chain->next($self, $params, $chain); }); Media::applyFilter('_handle', function($self, $params, $chain) { $params['handler'] += array('outputFilters' => array()); $params['handler']['outputFilters'] += Message::aliases(); return $chain->next($self, $params, $chain); Gets }); translations echo lithiumactionDispatcher::run(new lithiumactionRequest());
  • 120. $locale = 'en'; $locales = array('en' => 'English'); Environment::set('development', compact('locale', 'locales')); Environment::set('development'); } $file = "{$config['path']}/config/routes.php"; file_exists($file) ? call_user_func(function() use ($file) { include $file; }) : null; } return $chain->next($self, $params, $chain); }); Media::applyFilter('_handle', function($self, $params, $chain) { $params['handler'] += array('outputFilters' => array()); $params['handler']['outputFilters'] += Message::aliases(); return $chain->next($self, $params, $chain); }); echo lithiumactionDispatcher::run(new lithiumactionRequest()); Go
  • 121. Recap
  • 123. ★ Hackers framework Recap ★ Light, fast & fun
  • 124. ★ Hackers framework Recap ★ Light, fast & fun ★ Services have adaptable base
  • 125. ★ Hackers framework Recap ★ Light, fast & fun ★ Services have adaptable base ★ Filters are awesome/powerful
  • 126. ★ Hackers framework Recap ★ Light, fast & fun ★ Services have adaptable base ★ Filters are awesome/powerful ★ Everything is a library
  • 127. ★ Hackers framework Recap ★ Light, fast & fun ★ Services have adaptable base ★ Filters are awesome/powerful ★ Everything is a library ★ As much or as little framework as you need
  • 128. ★ Hackers framework Recap ★ Light, fast & fun ★ Services have adaptable base ★ Filters are awesome/powerful ★ Everything is a library ★ As much or as little framework as you need ★ Great balance weight/power/simplicity
  • 129. Thanks github.com/mackstar/phpnw-li3 @mackstar | #mackstar

Editor's Notes

  • #2: \n
  • #3: Union of Rad - worked with Nate\nTalk to me about japan\n
  • #4: Thank you - engine yard sponsors Lithium - php 5.4\n
  • #5: Lets talk about frameworks - there are too many\n
  • #6: People like to fight about their framework choice\n
  • #7: My favorites\nMy Least favorites\n
  • #8: Bloated\nCarry too much bulk - Symfony/Doctrine - VHeavy\nJava programmers\n
  • #9: \n
  • #10: \n
  • #11: Any body else find this odd?\n
  • #12: \n
  • #13: What drives us -\nIt is important to love the code you write - rails has had a big influence\n
  • #14: Our feelings count\nI don&amp;#x2019;t think we should need a high powered ide\n
  • #15: Lithium is really light 1mb tests 1mb - no bulk\n
  • #16: Lithium is really light 1mb tests 1mb - no bulk\n
  • #17: It is fast to develop in, it will speed up your development time. \nCompare Symfony, ZF, Drupal\n
  • #18: World one - every one familiar with this phrase?\n
  • #19: The repo - skeleton\n
  • #20: Great way to familiarize yourself - next few slides are taken from this project\n
  • #21: Example model - Save override to save tags\n
  • #22: Example model - Save override to save tags\n
  • #23: Example model - Save override to save tags\n
  • #24: View helpers\nCan override these\n
  • #25: View helpers\nCan override these\n
  • #26: View helpers\nCan override these\n
  • #27: &lt;?= escaping\nLink routes\nimage url helper\n
  • #28: &lt;?= escaping\nLink routes\nimage url helper\n
  • #29: &lt;?= escaping\nLink routes\nimage url helper\n
  • #30: Easy to read controllers - simple methods\n
  • #31: Easy to read controllers - simple methods\n
  • #32: Easy to read controllers - simple methods\n
  • #33: Geo-code is here - still really simple\n
  • #34: 1.Completely avoids the framework stack\nCan also use with JSON end points\n2. Its PHP, you can do what you want \n
  • #35: 1.Completely avoids the framework stack\nCan also use with JSON end points\n2. Its PHP, you can do what you want \n
  • #36: 1.Completely avoids the framework stack\nCan also use with JSON end points\n2. Its PHP, you can do what you want \n
  • #37: testing important\neverything is a library\n
  • #38: command line\n
  • #39: But this alone is not massively different to what is out there - like fuel\n
  • #40: It gets more interesting from here\n
  • #41: world 2\n
  • #42: Sky - no framework - create it from scratch - framework constraints\n
  • #43: maybe we feel a bit like this\n
  • #44: Not just 1 programming paradigm - php is very flexible\n
  • #45: \n
  • #46: Make a simple model\n
  • #47: Decoupled example\njust add lithium library - low overhead - all the code you need\nEasily added to DB - These are working examples\n
  • #48: Decoupled example\njust add lithium library - low overhead - all the code you need\nEasily added to DB - These are working examples\n
  • #49: Decoupled example\njust add lithium library - low overhead - all the code you need\nEasily added to DB - These are working examples\n
  • #50: Decoupled example\njust add lithium library - low overhead - all the code you need\nEasily added to DB - These are working examples\n
  • #51: Decoupled example\njust add lithium library - low overhead - all the code you need\nEasily added to DB - These are working examples\n
  • #52: Decoupled example\njust add lithium library - low overhead - all the code you need\nEasily added to DB - These are working examples\n
  • #53: Decoupled example\njust add lithium library - low overhead - all the code you need\nEasily added to DB - These are working examples\n
  • #54: Instantiate request and router\nSet routes - regex - now works (request contains correct controller)\nFull path matching\n\n\n
  • #55: Instantiate request and router\nSet routes - regex - now works (request contains correct controller)\nFull path matching\n\n\n
  • #56: Instantiate request and router\nSet routes - regex - now works (request contains correct controller)\nFull path matching\n\n\n
  • #57: Instantiate request and router\nSet routes - regex - now works (request contains correct controller)\nFull path matching\n\n\n
  • #58: Instantiate request and router\nSet routes - regex - now works (request contains correct controller)\nFull path matching\n\n\n
  • #59: We have an end point, \nfollowing route, \nparses the request object to contain\n
  • #60: We have an end point, \nfollowing route, \nparses the request object to contain\n
  • #61: We have an end point, \nfollowing route, \nparses the request object to contain\n
  • #62: Make simplest adaptable class\n
  • #63: We tell the Lithium where the app and adapters live -normally not needed\n-note emails same as where highlighted in the class \nSet the environment and use the adapter\n
  • #64: We tell the Lithium where the app and adapters live -normally not needed\n-note emails same as where highlighted in the class \nSet the environment and use the adapter\n
  • #65: We tell the Lithium where the app and adapters live -normally not needed\n-note emails same as where highlighted in the class \nSet the environment and use the adapter\n
  • #66: We tell the Lithium where the app and adapters live -normally not needed\n-note emails same as where highlighted in the class \nSet the environment and use the adapter\n
  • #67: We tell the Lithium where the app and adapters live -normally not needed\n-note emails same as where highlighted in the class \nSet the environment and use the adapter\n
  • #68: This time we write it a little more differently\nset up environment aware config\nSending is easy. Base of lithium services. Strategy implementation, very testable. DI in proportion\n
  • #69: This time we write it a little more differently\nset up environment aware config\nSending is easy. Base of lithium services. Strategy implementation, very testable. DI in proportion\n
  • #70: This time we write it a little more differently\nset up environment aware config\nSending is easy. Base of lithium services. Strategy implementation, very testable. DI in proportion\n
  • #71: This time we write it a little more differently\nset up environment aware config\nSending is easy. Base of lithium services. Strategy implementation, very testable. DI in proportion\n
  • #72: This time we write it a little more differently\nset up environment aware config\nSending is easy. Base of lithium services. Strategy implementation, very testable. DI in proportion\n
  • #73: The real fun part, this is a real high point of lithiums architecture.\n
  • #74: Write a method that doesn&amp;#x2019;t really do anything, but this is a filterable class\nEcho-ing is non-sense\n
  • #75: Write a method that doesn&amp;#x2019;t really do anything, but this is a filterable class\nEcho-ing is non-sense\n
  • #76: Write a method that doesn&amp;#x2019;t really do anything, but this is a filterable class\nEcho-ing is non-sense\n
  • #77: We deal with dependencies that have nothing to do with role\nLogger\n
  • #78: We deal with dependencies that have nothing to do with role\nLogger\n
  • #79: We deal with dependencies that have nothing to do with role\nLogger\n
  • #80: We deal with dependencies that have nothing to do with role\nLogger\n
  • #81: We deal with dependencies that have nothing to do with role\nLogger\n
  • #82: Find Example\n
  • #83: Find Example\n
  • #84: Find Example\n
  • #85: Find Example\n
  • #86: Find Example\n
  • #87: Find Example\n
  • #88: It would look like this\n
  • #89: It would look like this\n
  • #90: It would look like this\n
  • #91: Cache is an adaptable class\nBAD - filter classes that relates to itself\n
  • #92: Cache is an adaptable class\nBAD - filter classes that relates to itself\n
  • #93: Cache is an adaptable class\nBAD - filter classes that relates to itself\n
  • #94: Cache is an adaptable class\nBAD - filter classes that relates to itself\n
  • #95: Cache is an adaptable class\nBAD - filter classes that relates to itself\n
  • #96: Override content render - I am doing this\n
  • #97: Override content render - I am doing this\n
  • #98: Override content render - I am doing this\n
  • #99: \n
  • #100: \n
  • #101: \n
  • #102: How controller render works\n
  • #103: Ajax paths - types \n
  • #104: Handle media returned from the controller - images, json, encoding handlers\nHappens in controllers render method\n
  • #105: Handle media returned from the controller - images, json, encoding handlers\nHappens in controllers render method\n
  • #106: Handle media returned from the controller - images, json, encoding handlers\nHappens in controllers render method\n
  • #107: Granular control of exception handling\n
  • #108: Granular control of exception handling\n
  • #109: Granular control of exception handling\n
  • #110: Granular control of exception handling\n
  • #111: Granular control of exception handling\n
  • #112: Granular control of exception handling\n
  • #113: Real example - setting up error handling\n
  • #114: Real example - setting up error handling\n
  • #115: Real example - setting up error handling\n
  • #116: \n
  • #117: \n
  • #118: Set up stuff required by library - do demo\n
  • #119: Set up stuff required by library - do demo\n
  • #120: Set up stuff required by library - do demo\n
  • #121: Set up stuff required by library - do demo\n
  • #122: Set up stuff required by library - do demo\n
  • #123: Recap -really fast development\n
  • #124: Recap -really fast development\n
  • #125: Recap -really fast development\n
  • #126: Recap -really fast development\n
  • #127: Recap -really fast development\n
  • #128: Recap -really fast development\n
  • #129: Recap -really fast development\n
  • #130: \n