practical php 5.3

48
Practical PHP 5.3 Nate Abele 2.6.2010 IPC Berlin

Upload: nate-abele

Post on 20-May-2015

11.090 views

Category:

Technology


2 download

DESCRIPTION

PHP 5.3 has many new features that allow very different paradigms of software development, that may be unfamiliar to many PHP developers. If you want to learn more about functional or aspect-oriented programming, or how to organize your PHP libraries according to the new de facto PHP namespacing standard, don't miss this talk.

TRANSCRIPT

Page 1: Practical PHP 5.3

Practical PHP 5.3Nate Abele 2.6.2010 IPC Berlin

Page 2: Practical PHP 5.3

Me

• Former lead developer, CakePHP

• Co-founder & current lead developer, Lithium

• Developing on 5.3 for ~2 years

• Twitter: @nateabele

Page 3: Practical PHP 5.3

PHP Renaissance

• Long-awaited features finalized and committed

• Resurgence of energy and interest in evolving the language

• Trunk == iteration on latest stable release

Page 4: Practical PHP 5.3
Page 5: Practical PHP 5.3

Anyway...

Page 6: Practical PHP 5.3

Little Things

• Performance

• Syntax

• Phar

• SPL classes

• ext/fileinfo

• ext/sqlite3

• ext/intl

• mysqlnd

Page 7: Practical PHP 5.3

Big Things

• Late static binding

• Namespaces

• Lambdas / closures

Page 8: Practical PHP 5.3

Late-static binding (LSB)class Base { public static function foo() { $subclass = get_called_class(); // ...do some logic with $subclass... }}

class Child extends Base { public static function bar() { return static::foo() + 1; }}

class Grandchild extends Child { public static function foo() { $result = parent::foo(); // ...do some logic with $result... return $result; }}

Page 9: Practical PHP 5.3

Late-static binding (LSB)

• static:: ~= $this->

• get_called_class() - the subclass that invoked the method

• parent:: - same idea you’re used to

• Always use static:: or parent::, self:: etc. breaks the chain

Page 10: Practical PHP 5.3

Late-static binding (LSB)

• Attributes still a little “broken”class A { public static $message;}class B extends A {}class C extends A {}

B::$message = 'WTF?';echo C::$message; // echoes 'WTF?'

Page 11: Practical PHP 5.3

Late-static binding (LSB)

• Attributes still a little “broken”class A { public static $message;}class B extends A {}class C extends A { public static $message = 'Overridden';}

B::$message = 'WTF?';echo C::$message; // echoes 'Overridden'

Page 12: Practical PHP 5.3

Late-static binding (LSB)

• Attributes still a little “broken”class A { public static $message;}class B extends A { public static $message = 'Overridden';}class C extends A {}

A::$message = 'WTF?';echo C::$message; // echoes 'WTF?'

Page 13: Practical PHP 5.3

Why?

• Properly architect stateless portions of apps

• Utility classes

• Immutable state

Page 14: Practical PHP 5.3

“Dynamic” statics

• $foo->$bar() vs. Foo::bar()

• $foo = 'Foo'; $bar = 'bar'; $foo::$bar();

• __callStatic()

Page 15: Practical PHP 5.3

“Dynamic” statics

class Dispatcher {

public function run($url) { $parameters = Router::match($url); // ... }}

Page 16: Practical PHP 5.3

“Dynamic” statics

class Dispatcher {

public $router = 'Router';

public function run($url) { $router = $this->router; $parameters = $router::match($url); // ... }}

Page 17: Practical PHP 5.3

Namespaces

• Finally!

• What’s up with the \ ?

• Actually “packages”

Page 18: Practical PHP 5.3

Namespacesnamespace foo\bar;

class MyClass { // ...}

$class = new foo\bar\MyClass();

// -- or --

use foo\bar\MyClass;$class = new MyClass();

Page 19: Practical PHP 5.3

Namespaceuse foo\bar;$class = new bar\MyClass();

namespace me;$list = new SplDoublyLinkedList();

namespace me;$list = new \SplDoublyLinkedList();

namespace me;$class = 'foo\bar\MyClass';$object = new $class();

Page 21: Practical PHP 5.3

PSR-0

• Maps top-level vendor package name to filesystem location

• Maps file names 1:1 with class name

Page 22: Practical PHP 5.3

PSR-0• lithium\core\Libraries =>

/path/to/classes/lithium/core/Libraries.php

• lithium\Libraries =>/path/to/classes/lithium/Libraries.php

• Lithium\Core\Libraries =>/path/to/classes/Lithium/Core/Libraries.php

• Lithium_Core_Libraries =>/path/to/classes/Lithium/Core/Libraries.php

Page 23: Practical PHP 5.3

Original (PEAR) Draft

• Requires sub-packages

• Namespaces must be lower-cased and underscored

Page 24: Practical PHP 5.3

Original (PEAR) Draft

• Lithium\Core: ?

• lithium\core: Obviously a namespace

• Sub-packages promote reuse outside vendor libraries

Page 25: Practical PHP 5.3

SplClassLoader

• Concrete implementation of PSR-0

• PHP version:http://gist.github.com/221634

• C version:http://github.com/metagoto/splclassloader

Page 26: Practical PHP 5.3

Intermission

Page 27: Practical PHP 5.3

Ternary Shortcut

// Old:public function foo($parameter = null) { $parameter = $parameter ? $parameter : $this->_calculateDefault(); // ...}

// New:public function foo($parameter = null) { $parameter = $parameter ?: $this->_calculateDefault(); // ...}

Page 28: Practical PHP 5.3

Phar

• include 'phar:///path/to/file.phar/file.php';

• Redistributable apps

• Plugins

• Application templates

Page 29: Practical PHP 5.3

Phar

$archive = new Phar("/path/new_file.phar");

$archive->buildFromDirectory( '/path/to/my/app', '/\.(php|htaccess|jpg|png|gif|css|js|ico|json|ini)$/');

$archive->compress(Phar::GZ);

Page 30: Practical PHP 5.3

Lambdas & Closures

• Lambda: a function assigned to a variable

• Closure: a lambda, but bound to variables in the current scope

• This is an extremely big deal

Page 31: Practical PHP 5.3

Lambdas & Closures$names = array( 'Nate Abele', 'David Coallier', 'Cap\'n Crunch');$split = array_map( function($name) { list($first, $last) = explode(' ', $name); return compact('first', 'last'); }, $names);

// Result:array( array('first' => 'Nate', 'last' => 'Abele'), array('first' => 'David', 'last' => 'Coallier'), array('first' => 'Cap\'n', 'last' => 'Crunch'))

Page 32: Practical PHP 5.3

Lambdas & Closures

$names = array('Nate Abele', 'David Coallier', /* ... */);$filter = array('Nate', 'David');

$mapper = function($name) use ($filter) { list($first, $last) = explode(' ', $name); if (!in_array($first, $filter)) { return null; } return compact('first', 'last');};$filtered = array_map($mapper, $names);

Page 33: Practical PHP 5.3

Lambdas & Closures

$findActive = function($object) use (&$findActive) { if ($object->isActive) { return $object; } if ($object->children) { foreach ($object->children as $child) { return $findActive($child); } }};

Page 34: Practical PHP 5.3

Lambdas & Closures

class SomeWebService {

public function call($data) { $request = new HttpRequest(); // Configure $request... $result = $request->send(); // Do some processing... // Update $request for next operation... $final = $request->send(); // Post-process $final to extract some value return $someExtractedValue; }}

Page 35: Practical PHP 5.3

Lambdas & Closuresclass SomeWebService {

public function call($data, $pre = null, $post = null) { $request = new HttpRequest(); // ... if ($pre) { $request = $pre($request); } $result = $request->send();

if ($post) { $result = $post($result); } // ... $final = $request->send(); // ... }}

Page 36: Practical PHP 5.3

Lambdas & Closuresclass Database {

public $callThisOnEveryRead;

public function read($query) { if ($callback = $this->callThisOnEveryRead) { $callback($query); } // ... }}

Page 37: Practical PHP 5.3

Lambdas & Closuresclass Database {

public $callThisOnEveryRead;

public function read($query) { if ($callback = $this->callThisOnEveryRead) { $result = $callback($query) if ($result !== null) { return $result; } } // ... }}

Page 38: Practical PHP 5.3

No $this

Page 39: Practical PHP 5.3

Referential Transparency

• Only needs parameters to calculate a return value (i.e. no $_*, $this or date(), etc.)

• Doesn’t produce any side-effects

• No modifications outside current scope

• No references

• No echo, headers(), etc.

Page 40: Practical PHP 5.3

lithium\util\collection\Filters

Page 41: Practical PHP 5.3

Method Filters

class Database {

public function read($query) { // ... run the query ... return $result; }}

Page 42: Practical PHP 5.3

Method Filters

class Database {

public function read($query) { $method = function() { // ... run the query ... return $result; }; }}

Page 43: Practical PHP 5.3

Method Filters

class Database {

public function read($query) { $method = function($query) { // ... run the query ... return $result; }; return $method($query); }}

Page 44: Practical PHP 5.3

Method Filters

class Database extends \lithium\core\Object {

public function read($query) { $method = function($self, $params) { // ... run the query ... return $result; }; return $this->_filter( __METHOD__, compact('query'), $method ); }}

Page 45: Practical PHP 5.3

Method Filters$database = new Database($connectionDetails);

$database->applyFilter('read', function($self, $params, $chain) { $key = md5(serialize($params['query']));

if ($result = Cache::read($key)) { return $result; }

$result = $chain->next($self, $params, $chain); Cache::write($key, $result); return $result;});

Page 46: Practical PHP 5.3

lithium\util\collection\Filters

read()

inner

outer

Page 47: Practical PHP 5.3

AOP in a Nutshell

• Obliviousness

• Eliminates boilerplate code per class relationship

• Centralized configuration of concerns