Slide 1

Slide 1 text

PHP 5.4: The New Bits Friday, June 8, 12

Slide 2

Slide 2 text

•Engineer at Engine Yard for Orchestra.io PHP Platform as a Service (PaaS) •Author of Zend PHP 5 Certification Study Guide, Sitepoints PHP Anthology: 101 Essential Tips, Tricks & Hacks & PHP Master: Write Cutting Edge Code •A long time contributor to PEAR, phpdoc; new contributor to internals, FRAPI, lithium •Original Contributor to Zend Framework •@dshafik •(Buy My Books!) Davey Shafik Friday, June 8, 12

Slide 3

Slide 3 text

One More Thing Friday, June 8, 12

Slide 4

Slide 4 text

Hard of hearing: PLEASE SPEAK UP! (Everybody Forgets This!) Friday, June 8, 12

Slide 5

Slide 5 text

About These Slides Friday, June 8, 12

Slide 6

Slide 6 text

About These Slides • Two slides per “slide” • Title Slide (for when I’m talking) • Details slide (for later) • Nobody likes it when you can read the slide just as well as the speaker can • I like slides that are useful Friday, June 8, 12

Slide 7

Slide 7 text

The Small Stuff Friday, June 8, 12

Slide 8

Slide 8 text

The Small Stuff • SessionHandlerInterface added, used with session_set_save_handler() • PHP_BINARY constant gives the path to the... PHP binary • Notice now shown on array-to-string conversions • Better Memory Usage and Performance Friday, June 8, 12

Slide 9

Slide 9 text

More on SessionHandlerInterface Friday, June 8, 12

Slide 10

Slide 10 text

interface SessionHandlerInterface { public function open($sessionid); public function close(); public function read($sessionid); public function write($sessiondata); public function destroy($sessionid); public function gc($maxlifetime); } // Corresponds to: session_set_save_handler( $open, $close, $read, $write, $destroy, gc ); // Implemented by new internal class: class SessionHandler { } Friday, June 8, 12

Slide 11

Slide 11 text

Language Changes Friday, June 8, 12

Slide 12

Slide 12 text

Short Echo Tags Friday, June 8, 12

Slide 13

Slide 13 text

Short Echo Tags ="Now I Will Always Work!";?> No longer depends on short_open_tags Friday, June 8, 12

Slide 14

Slide 14 text

Binary Numbers Friday, June 8, 12

Slide 15

Slide 15 text

Binary Numbers $var = 0b01; // Binary (base 2) $var = 1234; // Integer $var = -123; // Signed Integer (+/-) $var = 1.23; // Float $var = 0123; // Octal (base 8) $var = 0x1A; // Hexadecimal (base 16) In Addition To: Friday, June 8, 12

Slide 16

Slide 16 text

New Array Syntax Friday, June 8, 12

Slide 17

Slide 17 text

New Array Syntax // Old $array = array(1, 2, 3); // New $array = [1, 2, 3]; // Old $a = array('a' => 'b', 'c' => 'd'); // New $a = ['a' => 'b', 'c' => 'd']; Friday, June 8, 12

Slide 18

Slide 18 text

Array Dereferencing Friday, June 8, 12

Slide 19

Slide 19 text

Array Dereferencing function returnArray() { return ['a' => 'b', 'c' => 'd']; } $foo = returnArray()['a']; // b Friday, June 8, 12

Slide 20

Slide 20 text

Dynamic Method Calls Friday, June 8, 12

Slide 21

Slide 21 text

Dynamic Method Calls // Variable static methods $var = "staticMethod"; ClassName::{$var}(); // Instantiation Time Access (new ClassName)->instanceMethod(); // UGLY. $var = "instanceMethod"; (new ClassName)->{$var}(); Friday, June 8, 12

Slide 22

Slide 22 text

Improvements to Closures & Callbacks Friday, June 8, 12

Slide 23

Slide 23 text

Closures & Callbacks • New callable type hint (closures, function names, arrays, __invoke()) • $this now accessible inside closures (based on creation location) • Array callbacks for variable function calls • Change $this and/or scope with Closure::bind() and Closure- >bindTo() Friday, June 8, 12

Slide 24

Slide 24 text

Callable Type hint function invokeCallback(callable $var) { $var(); } invokeCallback(function() { }); invokeCallback("functionName"); invokeCallback(['class', 'staticMethod']); invokeCallback([$object, 'method']); class Foo { public function __invoke() { } } invokeCallback(new Foo()); Friday, June 8, 12

Slide 25

Slide 25 text

$this in closures class foo { public function getClosure() { return function() { return $this; } } } class bar { public function __construct() { $foo = new foo(); $func = $foo->getClosure(); $obj = $func(); // PHP 5.3: $obj == null // PHP 5.4: $obj == foo, not bar } } Friday, June 8, 12

Slide 26

Slide 26 text

Array Callbacks class ClassName { public static function staticMethod() { var_dump(__METHOD__); } public function instanceMethod() { var_dump(__METHOD__); } } $callback = ['ClassName', 'staticMethod']; $callback(); // ClassName::staticMethod $callback = [new ClassName(), 'instanceMethod']; $callback(); // ClassName::instanceMethod Friday, June 8, 12

Slide 27

Slide 27 text

Rebinding $this Or: How to break the object model! Friday, June 8, 12

Slide 28

Slide 28 text

Rebinding $this • Doesn’t change the original closure — creates a duplicate • $this can be any object • $this and scope are separate — $this can be a different class to the access scope. Friday, June 8, 12

Slide 29

Slide 29 text

Rebinding $this class foo { public function getClosure() { return function() { echo $this->hello; $this->world(); }; } } class bar { public $hello = "Hello "; private function world() { echo "World"; } } $foo = new Foo(); $closure = $foo->getClosure(); $bar = new Bar(); $newClosure = $closure->bindTo($bar); $newClosure(); Friday, June 8, 12

Slide 30

Slide 30 text

Output Hello Fatal error: Call to private method bar::world() from context 'foo' Friday, June 8, 12

Slide 31

Slide 31 text

Rebinding $this class foo { public function getClosure() { return function() { echo $this->hello; $this->world(); }; } } class bar { public $hello = "Hello "; private function world() { echo "World"; } } $foo = new Foo(); $closure = $foo->getClosure(); $bar = new Bar(); $newClosure = $closure->bindTo($bar); $newClosure = $closure->bindTo($bar, $bar); $newClosure(); // Hello World Friday, June 8, 12

Slide 32

Slide 32 text

Traits AKA Horizontal Re-use Friday, June 8, 12

Slide 33

Slide 33 text

Traits • Compiler-level copy and paste (literally!) • New Keywords: trait, use, as and insteadof • Can use multiple traits • as and insteadof resolve conflicts • Can define methods, abstract methods, and properties Friday, June 8, 12

Slide 34

Slide 34 text

Traits trait sayHello { public function hello() { echo "Hello "; } } trait sayWorld { public function world() { echo "World"; } } class sayHelloWorld { use sayHello, sayWorld; } $say = new sayHelloWorld(); $say->hello(); // Hello $say->world(); // World Friday, June 8, 12

Slide 35

Slide 35 text

Inheritance/Scope trait getHello { public function hello() { return "Hello"; } } trait getWorld { public function world() { return "World"; } } trait sayHelloWorld { use getHello, getWorld; public function helloWorld() { echo $this->hello(), " ", $this->world(); } } class Greeting { use sayHelloWorld; } (new Greeting)->helloWorld(); // Hello World Friday, June 8, 12

Slide 36

Slide 36 text

Precedence class say { public function sayHello() { echo 'Hello '; } } trait sayWorld { public function sayHello() { parent::sayHello(); // parent is unknown echo 'World'; } } class HelloWorld extends say { use sayWorld; // parent == say } class HiMum extends HelloWorld { public function sayHello() { parent::sayHello(); // parent == HelloWorld == sayWorld echo ", Hi mum!", PHP_EOL; } } (new HelloWorld)->sayHello(); echo PHP_EOL; // Hello World (new HiMum)->sayHello(); // Hello World, Hi mum! Friday, June 8, 12

Slide 37

Slide 37 text

Method Visibility trait sayHello { public function hello() { echo "Hello "; } } trait sayWorld { private function world() { echo "World"; } } class sayHelloWorld { use sayHello, sayWorld { world as public; } } $say = new sayHelloWorld(); $say->hello(); // Hello $say->world(); // World Friday, June 8, 12

Slide 38

Slide 38 text

Method Aliases trait sayHello { public function hello() { echo "Hello "; } } trait sayWorld { private function world() { echo "World"; } } class sayHelloWorld { use sayHello, sayWorld { hello as greeting; world as public planet; } } $say = new sayHelloWorld(); $say->greeting(); // Hello $say->planet(); // World Friday, June 8, 12

Slide 39

Slide 39 text

Conflicts trait hello_en { public function greet() { echo "Hello "; } } trait mother_en_US { public function mother() { echo "Mom"; } } trait mother_en_UK { public function mother() { echo "Mum"; } } class HiMother { use hello_en, mother_en_US, mother_en_UK; public function sayHi($locale = 'UK') { $this->greet(); ($locale != 'US') ? $this->mother() : $this->mom(); } } (new HiMother)->sayHi('UK'); (new HiMother)->sayHi('US'); Fatal error: Trait method mother has not been applied, because there are collisions with other trait methods on HiMother on line 28 Friday, June 8, 12

Slide 40

Slide 40 text

Conflict Resolution trait hello_en { public function greet() { echo "Hello "; } } trait mother_en_US { public function mother() { echo "Mom"; } } trait mother_en_UK { public function mother() { echo "Mum"; } } class HiMother { use hello_en, mother_en_US, mother_en_UK { mother_en_UK::mother insteadof mother_en_US; mother_en_US::mother as mom; } public function sayHi($locale = 'UK') { $this->greet(); ($locale != 'US') ? $this->mother() : $this->mom(); } } (new HiMother)->sayHi('UK'); // Hello Mum (new HiMother)->sayHi('US'); // Hello Mom Friday, June 8, 12

Slide 41

Slide 41 text

Trait Detection Friday, June 8, 12

Slide 42

Slide 42 text

Trait Detection • instanceof doesn’t work because it’s literally engine-level copy and paste • class_uses() returns an array • Both keys and values are the trait names • We can use array dereferencing (another PHP 5.4 feature) to check! Friday, June 8, 12

Slide 43

Slide 43 text

Trait Detection trait HelloWorld { public function hi() { echo "Hello World", PHP_EOL; } } class greeting { use HelloWorld; } $greeting = new greeting(); // This doesn’t work if ($greeting instanceof HelloWorld) { echo "instanceof: ", $greeting->hi(); } // This does - using array dereferencing! if (isset(class_uses($greeting)['HelloWorld'])) { echo "class_uses: ", $greeting->hi(); } Friday, June 8, 12

Slide 44

Slide 44 text

Built-in CLI Server Friday, June 8, 12

Slide 45

Slide 45 text

Built in CLI Server • Use -S : (capital S) flag to initiate • Document Root: Current working directory • Default file: index.php • Serves static assets (e.g. images, js, css) • Allows URL routing with simple PHP script Friday, June 8, 12

Slide 46

Slide 46 text

Running the CLI Server davey@maat ~ $ /usr/local/php5/bin/php -S localhost:8080 PHP 5.4.0RC6 Development Server started at Sun Jan 29 22:15:32 2012 Listening on localhost:8080 Document root is /Users/davey Press Ctrl-C to quit. [Sun Jan 29 22:15:36 2012] 127.0.0.1:49956 [200]: / [Sun Jan 29 22:15:37 2012] 127.0.0.1:49957 [404]: / favicon.ico - No such file or directory Friday, June 8, 12

Slide 47

Slide 47 text

Output: /index.php array (size=21) 'DOCUMENT_ROOT' => string '/Users/davey' (length=12) 'REMOTE_ADDR' => string '127.0.0.1' (length=9) 'REMOTE_PORT' => string '49956' (length=5) 'SERVER_SOFTWARE' => string 'PHP 5.4.0RC6 Development Server' (length=31) 'SERVER_PROTOCOL' => string 'HTTP/1.1' (length=8) 'SERVER_NAME' => string 'localhost' (length=9) 'SERVER_PORT' => string '8080' (length=4) 'REQUEST_URI' => string '/' (length=1) 'REQUEST_METHOD' => string 'GET' (length=3) 'SCRIPT_NAME' => string '/index.php' (length=10) 'SCRIPT_FILENAME' => string '/Users/davey/index.php' (length=22) 'PHP_SELF' => string '/index.php' (length=10) 'HTTP_HOST' => string 'localhost:8080' (length=14) 'HTTP_CONNECTION' => string 'keep-alive' (length=10) 'HTTP_USER_AGENT' => string 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.77 Safari/ 535.7' (length=116) 'HTTP_ACCEPT' => string 'text/html,application/xhtml+xml,application/ xml;q=0.9,*/*;q=0.8' (length=63) 'HTTP_ACCEPT_ENCODING' => string 'gzip,deflate,sdch' (length=17) 'HTTP_ACCEPT_LANGUAGE' => string 'en-US,en;q=0.8' (length=14) 'HTTP_ACCEPT_CHARSET' => string 'ISO-8859-1,utf-8;q=0.7,*;q=0.3' (length=30) 'REQUEST_TIME_FLOAT' => float 1327893336.7823 'REQUEST_TIME' => int 1327893336 Friday, June 8, 12

Slide 48

Slide 48 text

Using a Router davey@maat ~ $ /usr/local/php5/bin/php -S localhost:8080 router.php PHP 5.4.0RC6 Development Server started at Sun Jan 29 22:15:32 2012 Listening on localhost:8080 Document root is /Users/davey Press Ctrl-C to quit. [Sun Jan 29 22:15:36 2012] 127.0.0.1:49956 [200]: / [Sun Jan 29 22:15:41 2012] 127.0.0.1:49956 [200]: /index.php Note: custom routed URLs do not show here (might be a bug!) Friday, June 8, 12

Slide 49

Slide 49 text

Using a Router if (realpath(__DIR__ . "/. {$_SERVER['REQUEST_URI']}")) { // file exists, serve it — will execute PHP return false; } else { // route the request (could be ZF, li3, etc) MyRouter::route($_SERVER['REQUEST_URI']); } class MyRouter { static public function route($path) { echo "Requested Resource: $path"; } // Check if we’re using the cli-server if (PHP_SAPI == 'cli-server') { ... } Example Router Friday, June 8, 12

Slide 50

Slide 50 text

Output: /index.php array (size=21) 'DOCUMENT_ROOT' => string '/Users/davey' (length=12) 'REMOTE_ADDR' => string '127.0.0.1' (length=9) 'REMOTE_PORT' => string '49956' (length=5) 'SERVER_SOFTWARE' => string 'PHP 5.4.0RC6 Development Server' (length=31) 'SERVER_PROTOCOL' => string 'HTTP/1.1' (length=8) 'SERVER_NAME' => string 'localhost' (length=9) 'SERVER_PORT' => string '8080' (length=4) 'REQUEST_URI' => string '/' (length=1) 'REQUEST_METHOD' => string 'GET' (length=3) 'SCRIPT_NAME' => string '/index.php' (length=10) 'SCRIPT_FILENAME' => string '/Users/davey/index.php' (length=22) 'PHP_SELF' => string '/index.php' (length=10) 'HTTP_HOST' => string 'localhost:8080' (length=14) 'HTTP_CONNECTION' => string 'keep-alive' (length=10) 'HTTP_USER_AGENT' => string 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.77 Safari/535.7' (length=116) 'HTTP_ACCEPT' => string 'text/html,application/xhtml+xml,application/ xml;q=0.9,*/*;q=0.8' (length=63) 'HTTP_ACCEPT_ENCODING' => string 'gzip,deflate,sdch' (length=17) 'HTTP_ACCEPT_LANGUAGE' => string 'en-US,en;q=0.8' (length=14) 'HTTP_ACCEPT_CHARSET' => string 'ISO-8859-1,utf-8;q=0.7,*;q=0.3' (length=30) 'REQUEST_TIME_FLOAT' => float 1327893336.7823 'REQUEST_TIME' => int 1327893336 Friday, June 8, 12

Slide 51

Slide 51 text

Output: /foo/bar Requested Resource: /foo/bar array (size=23) 'DOCUMENT_ROOT' => string '/Users/davey/Dropbox/Talks/2012/PHP 5.4 - The New Bits/ cli-server' (length=65) 'REMOTE_ADDR' => string '::1' (length=3) 'REMOTE_PORT' => string '52584' (length=5) 'SERVER_SOFTWARE' => string 'PHP 5.4.0RC6 Development Server' (length=31) 'SERVER_PROTOCOL' => string 'HTTP/1.1' (length=8) 'SERVER_NAME' => string 'localhost' (length=9) 'SERVER_PORT' => string '8080' (length=4) 'REQUEST_URI' => string '/foo/bar' (length=8) 'REQUEST_METHOD' => string 'GET' (length=3) 'SCRIPT_NAME' => string '/index.php' (length=10) 'SCRIPT_FILENAME' => string '/Users/davey/Dropbox/Talks/2012/PHP 5.4 - The New Bits/cli-server/index.php' (length=75) 'PATH_INFO' => string '/foo/bar' (length=8) 'PHP_SELF' => string '/index.php/foo/bar' (length=18) 'HTTP_HOST' => string 'localhost:8080' (length=14) 'HTTP_CONNECTION' => string 'keep-alive' (length=10) 'HTTP_CACHE_CONTROL' => string 'max-age=0' (length=9) 'HTTP_USER_AGENT' => string 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.77 Safari/535.7' (length=116) 'HTTP_ACCEPT' => string 'text/html,application/xhtml+xml,application/xml;q=0.9,*/ *;q=0.8' (length=63) 'HTTP_ACCEPT_ENCODING' => string 'gzip,deflate,sdch' (length=17) 'HTTP_ACCEPT_LANGUAGE' => string 'en-US,en;q=0.8' (length=14) 'HTTP_ACCEPT_CHARSET' => string 'ISO-8859-1,utf-8;q=0.7,*;q=0.3' (length=30) 'REQUEST_TIME_FLOAT' => float 1327903577.3323 'REQUEST_TIME' => int 1327903577 Friday, June 8, 12

Slide 52

Slide 52 text

Thank You! • Feedback: • http://joind.in/talk/view/6252 • @dshafik • dshafi[email protected] • Slides: • http://daveyshafik.com/slides Friday, June 8, 12