PHP 5.3 and Lithium: the most rad php framework

Post on 01-Nov-2014

21.130 views 1 download

Tags:

description

Presentation given to the Orange County PHP meetup on Feb 24 2010. The presentation covers the new features in php 5.3 and goes on to show how they are used in Lithium, the most rad php framework.

Transcript of PHP 5.3 and Lithium: the most rad php framework

Wednesday, February 24, 2010

PHP 5.3

Wednesday, February 24, 2010

Why?• Speed & Memory

• Namespaces

• Anonymous Functions

• Late Static Binding

• Syntax enhancements

• SPL

• Phar

• ext/intl

• ext/fileinfo

• ext/sqlite3

• mysqlnd

Wednesday, February 24, 2010

Speed & Memory

http://sebastian-bergmann.de/archives/745-Benchmark-of-PHP-Branches-3.0-through-5.3-CVS.html

Drupal 20% fasterQdig 2% fastertypo3 30% fasterwordpress 15% fasterxoops 10% fasterhttp://news.php.net/php.internals/36484

gc_enable() : New Garbage Collector

Wednesday, February 24, 2010

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

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

<?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-proposalAutoloading

Wednesday, February 24, 2010

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

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

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

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

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

Why Static?

• Promotes proper application design

• Stateless

• Easier to access

Wednesday, February 24, 2010

Late Static Binding<?phpclass 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

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

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

Phar

• PHP archives

• includable (include 'phar:///path/to/myphar.phar/file.php')

• stream accessible

• distributable

Wednesday, February 24, 2010

ext/intl

• Collator

• Locale

• IntlDateFormatter

• NumberFormatter

Wednesday, February 24, 2010

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

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

mysqlnd

• mysql native driver

• faster

• easier to compile

• transparent client, same old mysql/mysqli

Wednesday, February 24, 2010

Lithiumthe most rad php framework

Wednesday, February 24, 2010

In Lithium• Namespaces

• Anonymous Functions

• Late Static Binding

• Syntax Enhancements

• SPL

• Phar

• Sqlite3

Wednesday, February 24, 2010

Lithium Namespaces• action

• analysis

• console

• core

• g11n

• net

• security

• storage

• template

• test

• tests

• util

Wednesday, February 24, 2010

Namespace Example

<?php

namespace app\extensions\helper;

class Form extends \lithium\template\helper\Form {

public function config(array $config = array()) { .... }}

Wednesday, February 24, 2010

Anonymous Functions Example

<?php

Validator::add('role', function ($value, $format, $options) { return (in_array($value, array('admin', 'editor', 'user')));});

?>

Wednesday, February 24, 2010

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

__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

__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

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

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

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

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

Sqlite3

<?php

Connections::add('default', array( 'type' => 'database', 'adapter' => 'Sqlite3', 'database' => LITHIUM_APP_PATH . '/resources/db/sqlite.db'));

?>

Wednesday, February 24, 2010

By Lithium

• Simple, Uniform API

• Unified Constructor

• Adaptable

• Filters (Aspect Oriented Programming)

• $_classes (Dependency Injection)

• Collections

Wednesday, February 24, 2010

Simple Uniform API

• logical namespaces and classes

• simple method names

• <= 3 params per method

• $config

• $options

Wednesday, February 24, 2010

Unified Constructor

• $config

• always an array

• check for $_autoConfig

• _init() and __init()

Wednesday, February 24, 2010

Adaptable• \security\Auth

• \storage\Session

• \storage\Cache

• \g11n\Catalog

• \data\Connections

• \analysis\Logger

Wednesday, February 24, 2010

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

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

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

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

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

$_classes

• Dependency Injectiona 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

$_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

$_classes Example<?phpnamespace 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

Collections

• lithium\util\Collection

• lithium\data\Collection

• lithium\data\collection\RecordSet

• lithium\data\collection\Document

• lithium\test\Group

Wednesday, February 24, 2010

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

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

Still More Lithium

• Automatic output escaping

• Http Services

• g11n for internationalized applications

• Authentication

• Session/Cookie Handling

• Authorization (1.0)

Wednesday, February 24, 2010

Even More Lithium

• Validator

• Logging

• Debugger

• Parser

• Inspector

• Sockets

Wednesday, February 24, 2010

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

Using Zendhttp://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

Plugins

• namespaces allow for a true plugin system

• modify application with filters

• add extensions

• share your handy work

Wednesday, February 24, 2010

Some Plugins

• li3_docs

• li3_oauth

• li3_bot

• li3_doctrine

• li3_lab

Wednesday, February 24, 2010

Wednesday, February 24, 2010

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

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