Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

How Lithium uses PHP 5.3

gwoo
February 21, 2013

How Lithium uses PHP 5.3

Take a look at the features of PHP 5.3 and how Lithium takes advantage of them.

gwoo

February 21, 2013
Tweet

More Decks by gwoo

Other Decks in Programming

Transcript

  1. Why? • Speed & Memory • Namespaces • Anonymous Functions

    • Late Static Binding • Syntax enhancements • SPL • Phar • ext/intl • ext/fileinfo • ext/sqlite3 • mysqlnd Wednesday, February 24, 2010
  2. Speed & Memory http://sebastian-bergmann.de/archives/745-Benchmark-of-PHP-Branches-3.0-through-5.3-CVS.html Drupal 20% faster Qdig 2% faster

    typo3 30% faster wordpress 15% faster xoops 10% faster http://news.php.net/php.internals/36484 gc_enable() : New Garbage Collector Wednesday, February 24, 2010
  3. Namespaces • Autoloading made easy • \lithium\core\Libraries • \li3_docs\controllers\BrowserController •

    http://groups.google.com/group/php- standards/web/psr-0-final-proposal http://php.net/manual/en/language.namespaces.php Wednesday, February 24, 2010
  4. Namespaces Example <?php namespace app; use \app\models\Post; class PostsController extends

    \lithium\action\Controller { public function index() { $posts = Post::all(); return compact(‘posts’); } } ?> Wednesday, February 24, 2010
  5. <?php function __autoload($className) { $className = ltrim($className, '\\'); $fileName =

    ''; $namespace = ''; if ($lastNsPos = strripos($className, '\\')) { $namespace = substr($className, 0, $lastNsPos); $className = substr($className, $lastNsPos + 1); $fileName = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR; } $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php'; require $fileName; } ?> http://groups.google.com/group/php-standards/web/psr-0-final-proposal Autoloading Wednesday, February 24, 2010
  6. Anonymous Functions • Lambda • assigned to a variable •

    useful for recursion and multiple calls • Closure • added as a method parameter • use() the parent scope http://php.net/manual/en/functions.anonymous.php Wednesday, February 24, 2010
  7. Lambda Example <?php $cube = function ($value) { return ($value

    * $value * $value); }; $result = array_map($cube, array(1, 2, 3)); var_dump($result); /* array 0 => int 1 1 => int 8 2 => int 27 */ ?> Wednesday, February 24, 2010
  8. Another Lambda $multiply = function ($value, $times) use (&$multiply) {

    return ($times > 0) ? $multiply($value * $value, --$times) : $value; }; var_dump($multiply(2, 3)); /* int 256 */ Wednesday, February 24, 2010
  9. Closure Example <?php $data = 'string'; $result = array_filter(array(1, 2,

    'string'), function ($value) use ($data) { return ($value !== $data); }); var_dump($result); /* array 0 => int 1 1 => int 2 */ ?> Wednesday, February 24, 2010
  10. Crazy Example <?php function Y($F) { return current(array(function($f) { return

    $f($f); }))->__invoke(function($f) use ($F) { return $F(function($x) use ($f) { return $f($f)->__invoke($x); }); }); } $factorial = Y(function($fact) { return function($n) use ($fact) { return ($n <= 1) ? 1 : $n * $fact($n - 1); }; }); var_dump($factorial(6)); /* int 720 */ ?> Wednesday, February 24, 2010
  11. Why Static? • Promotes proper application design • Stateless •

    Easier to access Wednesday, February 24, 2010
  12. Late Static Binding <?php class A { public static function

    who() { return __CLASS__; } public static function test() { return static::who(); } } class B extends A { public static function who() { return __CLASS__; } } $result = B::test(); var_dump($result); /* string 'B' (length=1) */ http://php.net/lsb Wednesday, February 24, 2010
  13. Standard PHP Library (SPL) • spl_autoload_register() • Iterators • Exceptions

    • File Handling • Observer/Subject • Stack, Queue, Heap, ObjectStorage http://us.php.net/manual/en/book.spl.php Wednesday, February 24, 2010
  14. Syntax Enhancements • PHP 5 < 5.3 • __set()/__get() •

    __isset()/__unset() • __call() • PHP 5.3 • __callStatic() • __invoke() • ?: http://php.net/manual/en/language.oop5.magic.php Wednesday, February 24, 2010
  15. ext/fileinfo <?php $info = new \finfo(FILEINFO_MIME); $result = $info->file(__FILE__); var_dump($result);

    /* string 'text/x-php; charset=us-ascii' (length=28) */ $result = finfo_file(finfo_open(FILEINFO_MIME), __FILE__); var_dump($result); /* string 'text/x-php; charset=us-ascii' (length=28) */ ?> Wednesday, February 24, 2010
  16. ext/sqlite3 • SQLite is a in-process library that implements a

    self-contained, serverless, zero-configuration, transactional SQL database engine (http://www.sqlite.org/ about.html) • A more compact format for database files. • Support for both UTF-8 and UTF-16 text. • Manifest typing and BLOB support. • New API via Sqlite3 class or sqlite3 functions Wednesday, February 24, 2010
  17. mysqlnd • mysql native driver • faster • easier to

    compile • transparent client, same old mysql/mysqli Wednesday, February 24, 2010
  18. In Lithium • Namespaces • Anonymous Functions • Late Static

    Binding • Syntax Enhancements • SPL • Phar • Sqlite3 Wednesday, February 24, 2010
  19. Lithium Namespaces • action • analysis • console • core

    • g11n • net • security • storage • template • test • tests • util Wednesday, February 24, 2010
  20. Namespace Example <?php namespace app\extensions\helper; class Form extends \lithium\template\helper\Form {

    public function config(array $config = array()) { .... } } Wednesday, February 24, 2010
  21. Anonymous Functions Example <?php Validator::add('role', function ($value, $format, $options) {

    return (in_array($value, array('admin', 'editor', 'user'))); }); ?> Wednesday, February 24, 2010
  22. LSB Example <?php namespace lithium\core; class StaticObject { ... }

    ?> <?php namespace lithium\data; class Model extends \lithium\core\StaticObject { ... } ?> <?php namespace app\models; class Post extends \lithium\data\Model { } ?> Wednesday, February 24, 2010
  23. __callStatic <?php namespace lithium\data; class Model extends \lithium\core\StaticObject { public

    static function __callStatic($method, $params) { ... } ?> <?php namespace app\controllers use app\models\Post; class PostsController extends \lithium\action\Controller { public function index() { $posts = Post::all(); return compact('posts') } } ?> Wednesday, February 24, 2010
  24. __invoke <?php namespace lithium\action; class Controller extends lithium\core\Object { public

    function __invoke($request, $dispatchParams, array $options = array()) { ... } } ?> <?php namespace lithium\action; class Dispatcher extends \lithium\core\StaticObject { protected static function _call($callable, $request, $params) { ... if (is_callable($callable = $params['callable'])) { return $callable($params['request'], $params['params']); } throw new Exception('Result not callable'); ... } } ?> Wednesday, February 24, 2010
  25. SPL Iterators <?php protected function _cleanUp($path = null) { $path

    = $path ?: LITHIUM_APP_PATH . '/resources/tmp/tests'; $path = $path[0] !== '/' ? LITHIUM_APP_PATH . '/resources/tmp/' . $path : $path; if (!is_dir($path)) { return; } $dirs = new RecursiveDirectoryIterator($path); $iterator = new RecursiveIteratorIterator($dirs, RecursiveIteratorIterator::CHILD_FIRST); foreach ($iterator as $item) { if ($item->getPathname() === "{$path}/empty") continue; ($item->isDir()) ? rmdir($item->getPathname()) : unlink($item->getPathname()); } } ?> Wednesday, February 24, 2010
  26. SPL Interfaces <?php /* * @link http://us.php.net/manual/en/class.arrayaccess.php * @link http://us.php.net/manual/en/class.iterator.php

    * @link http://us.php.net/manual/en/class.countable.php */ class Collection extends \lithium\core\Object implements \ArrayAccess, \Iterator, \Countable { ... } ?> Wednesday, February 24, 2010
  27. SPL autoloader <?php namespace lithium\core; class Libraries { ... public

    static function add($name, $config = array()) { ... if (!empty($config['loader'])) { spl_autoload_register($config['loader']); } ... } ... } ?> Wednesday, February 24, 2010
  28. Phar <?php namespace lithium\console\command; use \Phar; class Library extends \lithium\console\Command

    { public function archive() { .... $archive = new Phar("{$path}.phar"); $from = $this->_toPath($from); $result = (boolean) $archive->buildFromDirectory($from, $this->filter); ... $archive->compress(Phar::GZ); return true; } } ?> Wednesday, February 24, 2010
  29. Sqlite3 <?php Connections::add('default', array( 'type' => 'database', 'adapter' => 'Sqlite3',

    'database' => LITHIUM_APP_PATH . '/resources/db/sqlite.db' )); ?> Wednesday, February 24, 2010
  30. By Lithium • Simple, Uniform API • Unified Constructor •

    Adaptable • Filters (Aspect Oriented Programming) • $_classes (Dependency Injection) • Collections Wednesday, February 24, 2010
  31. Simple Uniform API • logical namespaces and classes • simple

    method names • <= 3 params per method • $config • $options Wednesday, February 24, 2010
  32. Unified Constructor • $config • always an array • check

    for $_autoConfig • _init() and __init() Wednesday, February 24, 2010
  33. Adaptable • \security\Auth • \storage\Session • \storage\Cache • \g11n\Catalog •

    \data\Connections • \analysis\Logger Wednesday, February 24, 2010
  34. Filters • Aspect Oriented Programming secondary or supporting functions are

    isolated from the main program's business logic...increase modularity by allowing the separation of cross-cutting concerns... (http://en.wikipedia.org/wiki/Aspect-oriented_programming) • modify core functionality without extending a class • define your own callbacks • @filter Wednesday, February 24, 2010
  35. Routes Filter <?php use \lithium\action\Dispatcher; Dispatcher::applyFilter('run', function($self, $params, $chain) {

    include __DIR__ . '/routes.php'; return $chain->next($self, $params, $chain); }); ?> Wednesday, February 24, 2010
  36. Asset Filter <?php use \lithium\action\Dispatcher; use \lithium\core\Libraries; use \lithium\net\http\Media; Dispatcher::applyFilter('_callable',

    function($self, $params, $chain) { list($plugin, $asset) = explode('/', $params['request']->url, 2) + array("", ""); if ($asset && $library = Libraries::get($plugin)) { $asset = "{$library['path']}/webroot/{$asset}"; if (file_exists($asset)) { return function () use ($asset) { $info = pathinfo($asset); $type = Media::type($info['extension']); header("Content-type: {$type['content']}"); return file_get_contents($asset); }; } } return $chain->next($self, $params, $chain); }); ?> Wednesday, February 24, 2010
  37. Xhprof Filter <?php use \lithium\action\Dispatcher; Dispatcher::applyFilter('run', function($self, $params, $chain) {

    xhprof_enable(); $data = $chain->next($self, $params, $chain); $xhprof_data = xhprof_disable(); $XHPROF_ROOT = '/usr/local/php/5.3.1/lib/xhprof'; include_once $XHPROF_ROOT . "/xhprof_lib/utils/xhprof_lib.php"; include_once $XHPROF_ROOT . "/xhprof_lib/utils/xhprof_runs.php"; $xhprof_runs = new XHProfRuns_Default(); $run_id = $xhprof_runs->save_run($xhprof_data, "xhprof_lithium"); return $data; }); ?> Wednesday, February 24, 2010
  38. Save Filter <?php namespace app\models; class Paste extends \lithium\data\Model {

    public static function __init(array $options = array()) { parent::__init($options); static::applyFilter('save', function($self, $params, $chain) { $document = $params['record']; if (!$document->id) { $document->created = date('Y-m-d h:i:s'); } if (!empty($params['data'])) { $document->set($params['data']); } $document->parsed = $self::parse($document->content, $document->language); $document->preview = substr($document->content, 0, 100); $document->modified = date('Y-m-d h:i:s'); $params['record'] = $document; return $chain->next($self, $params, $chain); }); } } ?> Wednesday, February 24, 2010
  39. $_classes • Dependency Injection a technique for supplying an external

    dependency (i.e. a reference) to a software component - that is, indicating to a part of a program which other parts it can use... (http://en.wikipedia.org/wiki/Dependency_injection) • modify core functionality without extending a class Wednesday, February 24, 2010
  40. $_classes Example <?php namespace lithium\console; class Library extends \lithium\console\Command {

    ... protected $_classes = array( 'service' => '\lithium\net\http\Service', 'response' => '\lithium\console\Response' ); ... } ?> Wednesday, February 24, 2010
  41. $_classes Example <?php namespace lithium\tests\cases\console; use \lithium\console\Request; class LibraryTest extends

    \lithium\test\Unit { ... public function setUp() { ... $this->classes = array( 'service' => '\lithium\tests\mocks\console\command\MockLibraryService', 'response' => '\lithium\tests\mocks\console\MockResponse' ); ... } ... public function testArchiveNoLibrary() { ... $app = new Library(array( 'request' => new Request(), 'classes' => $this->classes )); $expected = true; $result = $app->archive(); $this->assertEqual($expected, $result); } ... } ?> Wednesday, February 24, 2010
  42. Collections Example <?php use \lithium\util\Collection; $coll = new Collection(array('items' =>

    array(0, 1, 2, 3, 4))); $coll->first(); // 1 (the first non-empty value) $coll->current(); // 0 $coll->next(); // 1 $coll->next(); // 2 $coll->next(); // 3 $coll->prev(); // 2 $coll->rewind(); // 0 $coll->each(function($value) { return $value + 1; }); $coll->to('array'); // array(1, 2, 3, 4, 5) ?> <?php use \lithium\test\Group; $group = new Group(array('items' => array( 'lithium\tests\cases\core\Libraries', 'lithium\tests\cases\core\Object', )) $resul = $group->tests()->run(); ?> Wednesday, February 24, 2010
  43. More Lithium • Integrated Test Suite for fast TDD •

    Command Line Framework • Document Based Data Sources • Object based Record Sets with access to non static model methods • Transparent content type rendering Wednesday, February 24, 2010
  44. Still More Lithium • Automatic output escaping • Http Services

    • g11n for internationalized applications • Authentication • Session/Cookie Handling • Authorization (1.0) Wednesday, February 24, 2010
  45. Even More Lithium • Validator • Logging • Debugger •

    Parser • Inspector • Sockets Wednesday, February 24, 2010
  46. Lithium Integrations • Use 3rd party libraries • Easy to

    add with Libraries class • Especially simple when PSR-0 is followed • Access classes in a standard way Wednesday, February 24, 2010
  47. Using Zend http://rad-dev.org/lithium/wiki/guides/using/zend <?php Libraries::add("Zend", array( "prefix" => "Zend_", 'path'

    => '/htdocs/libraries/Zend/trunk/library/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"; } )); ?> <?php namespace app\controllers; use \Zend_Mail_Storage_Pop3; class EmailController extends \lithium\action\Controller { public function index() { $mail = new Zend_Mail_Storage_Pop3(array( 'host' => 'localhost', 'user' => 'test', 'password' => 'test' )); return compact('mail'); } } ?> Wednesday, February 24, 2010
  48. Plugins • namespaces allow for a true plugin system •

    modify application with filters • add extensions • share your handy work Wednesday, February 24, 2010
  49. lithium_qa • http://rad-dev.org/lithium/wiki/standards • Check syntax of your code •

    Shows rules violations in your code • Automate the process with SCM hooks Wednesday, February 24, 2010
  50. Lithium • http://lithify.me • http://rad-dev.org/lithium/wiki • http://www.ohloh.net/p/lithium • http://twitter.com/UnionOfRAD •

    irc://irc.freenode.net/#li3 • http://search.twitter.com/search?q=%23li3 the most rad php framework Wednesday, February 24, 2010