The State of Lithium
-
Upload
nate-abele -
Category
Technology
-
view
2.671 -
download
4
description
Transcript of The State of Lithium
THE STATE OF LITHIUMli3_nyc::init() // 2012-02-07
SPONSORS
AGENDA• State of the framework
• New features
• Upcoming features
• Community plugins
• Library management & The Lab
• Tips & tricks
• Q&A / Demos!
STATE OF THE FRAMEWORK
PROJECT & COMMUNITY STATS
• ~130 plugin repositories on GitHub
• 350+ commits from 40+ contributors since 0.10
• 60+ commits to the manual since 0.10
• Closed 250+ issues since moving to GitHub
• 175 pull requests submitted since moving to GitHub
ROADMAP PROGRESS
• Cookie signing / encryption
• CSRF protection
• Error Handling
• Manual / automatic SQL result mapping
• Relationship support
NEW FEATURES
ENCRYPT & SIGN COOKIES
Session::config(array('default' => array( 'adapter' => 'Cookie', 'strategies' => array( 'Hmac' => array('secret' => '$f00bar$'), 'Encrypt' => array('secret' => '$f00bar$') ))));
NEST ROUTESRouter::connect("/admin/{:args}", array('admin' => true), array( 'continue' => true));
Router::connect("/{:locale:en|de|jp}/{:args}", array(), array( 'continue' => true));
Router::connect("/{:args}.{:type}", array(), array( 'continue' => true));
HANDLE ERRORS
$method = array(Connections::get('default'), 'read');
ErrorHandler::apply($method, array(), function($error, $params) { $queryParams = json_encode($params['query']); $msg = "Query error: {$error['message']}";
Logger::warning("{$msg}, data: {$queryParams}"); return new DocumentSet();});
PROTECT FORMS<?=$this->form->create(); ?> <?=$this->security->requestToken(); ?> <?=$this->form->field('title'); ?> <?=$this->form->submit('Submit'); ?><?=$this->form->end(); ?>
public function add() { if ( $this->request->data && !RequestToken::check($this->request) ) { // Badness!! }}
UPCOMING FEATURES
HTTP SERVICE CLASSES
$http = new Http(array( ... 'methods' => array( 'do' => array('method' => 'post', 'path' => '/do') )));
$response = $http->do(new Query(array( 'data' => array('title' => 'sup'))));// var_dump($response->data());
POST /do HTTP/1.1…
title=sup
FILTER / SORT COLLECTIONS
$users->find(array("type" => "author"))->sort("name");
$users->first(array("name" => "Nate"));
MULTIBYTE CLASS
• Supports mbstring, intl, iconv & (womp, womp) plain PHP
• Only one method right now: strlen()
• More would be good… open a pull request
SCHEMA CLASS
• Arbitrary data types
• Arbitrary handlers
• Example: hash modified passwords before writing
• Other example: JSON en/decode arbitrary data for MySQL
PLUGINS
LI3_DOCTRINE2
• Works with Lithium stuff:
• Connections
• Authentication
• Forms
• Sessions
• Validation
Connections::add('default', array( 'type' => 'Doctrine', 'driver' => 'pdo_mysql', 'host' => 'localhost', 'user' => 'root', 'password' => 'password', 'dbname' => 'my_db'));/** * @Entity * @Table(name="users") */class User extends \li3_doctrine2\models\BaseEntity { /** * @Id * @GeneratedValue * @Column(type="integer") */ private $id;
/** * @Column(type="string",unique=true) */ private $email; ...}
LI3_FILESYSTEMuse li3_filesystem\storage\FileSystem;
FileSystem::config(array( 'default' => array( 'adapter' => 'File' ), 'ftp' => array( 'adapter' => 'Stream', 'wrapper' => 'ftp', 'path' => 'user:[email protected]/pub/' }));
FileSystem::write('default', '/path/to/file', $data);
LI3_ACCESSAccess::config(array( 'asset' => array( 'adapter' => 'Rules', 'allowAny' => true, 'default' => array('isPublic', 'isOwner', 'isParticipant'), 'user' => function() { return Accounts::current(); }, 'rules' => array( 'isPublic' => function($user, $asset, $options) { ... }, 'isOwner' => function($user, $asset, $options) { ... }, 'isParticipant' => function($user, $asset, $options) { ... } ) ) ...);
LI3_ACCESSAccess::config(array( ... 'action' => array( 'adapter' => 'Rules', 'default' => array('isPublic', 'isAuthenticated'), 'allowAny' => true, 'user' => function() { return Accounts::current(); }, 'rules' => array( 'isPublic' => function($user, $request, array $options) { ... }, 'isAuthenticated' => function($user, $request, array $options) { ... }, 'isAdmin' => function($user, $asset, $options) { ... } ) ));
LI3_ACCESSDispatcher::applyFilter('_call', function($self, $params, $chain) { $opts = $params['params']; $request = $params['request']; $ctrl = $params['callable'];
if ($access = Access::check('action', null, $ctrl, $opts)) { // Reject } if ($access = Access::check('action', null, $ctrl, array('rules' => 'isAdmin') + $opts)) { // Reject } return $chain->next($self, $params, $chain);});
class PostsController extends Base {
public $publicActions = array('index', 'view');}
http://bit.ly/li3plugins
THE LAB
TIPS & TRICKS
RETURN ON REDIRECT
class PostsController extends Base {
public function view($post) { if (!$post) { $this->redirect("Posts::index"); } // Herp derp }}
FAT FILTERS == BADDispatcher::applyFilter('run', function($self, $params, $chain) { // Herp // Derp // Herp // Derp // Herp // Derp // Herp // Derp // Herp // Derp // Herp (repeat x100)});
DEFINE YOUR SCHEMA!
{ count: 5, ...}...{ count: "5", ...}
DON’T FEAR THE SUBCLASSclass Base extends \lithium\data\Model {
public function save($entity, $data = null, array $options = array()) { if ($data) { $entity->set($data); } if (!$entity->exists()) { $entity->created = new MongoDate(); } $entity->updated = new MongoDate(); return parent::save($entity, null, $options); }}
class Posts extends Base { ...}
QUICK & DIRTY ADMIN
Dispatcher::config(array('rules' => array( 'admin' => array(
'action' => 'admin_{:action}' )
)));
Router::connect( '/admin/{:args}', array('admin' => true), array('continue' => true));
class PostsController extends Base {
public function admin_index() { ... }
public function index() { ... }}
Q&A / DEMOS
THANKS!