Upgrade to Pro — share decks privately, control downloads, hide ads and more …

How Lithium uses PHP 5.3

Avatar for gwoo 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.

Avatar for gwoo

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