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

[DPC] PHP 5.4: The New Bits

[DPC] PHP 5.4: The New Bits

PHP 5.4 is about to be unleashed into the world; bringing some of the most exciting changes to the PHP language to date. Learn about traits, array dereferencing, indirect method calls using array callback syntax and improvements to closures and streams.

Davey Shafik

June 09, 2012
Tweet

More Decks by Davey Shafik

Other Decks in Programming

Transcript

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

    View Slide

  2. •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

    View Slide

  3. One More Thing
    Friday, June 8, 12

    View Slide

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

    View Slide

  5. About These
    Slides
    Friday, June 8, 12

    View Slide

  6. 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

    View Slide

  7. The Small Stuff
    Friday, June 8, 12

    View Slide

  8. 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

    View Slide

  9. More on
    SessionHandlerInterface
    Friday, June 8, 12

    View Slide

  10. 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

    View Slide

  11. Language Changes
    Friday, June 8, 12

    View Slide

  12. Short Echo Tags
    Friday, June 8, 12

    View Slide

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

    View Slide

  14. Binary Numbers
    Friday, June 8, 12

    View Slide

  15. 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

    View Slide

  16. New Array Syntax
    Friday, June 8, 12

    View Slide

  17. 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

    View Slide

  18. Array
    Dereferencing
    Friday, June 8, 12

    View Slide

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

    View Slide

  20. Dynamic Method
    Calls
    Friday, June 8, 12

    View Slide

  21. 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

    View Slide

  22. Improvements to
    Closures &
    Callbacks
    Friday, June 8, 12

    View Slide

  23. 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

    View Slide

  24. 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

    View Slide

  25. $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

    View Slide

  26. 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

    View Slide

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

    View Slide

  28. 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

    View Slide

  29. 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

    View Slide

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

    View Slide

  31. 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

    View Slide

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

    View Slide

  33. 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

    View Slide

  34. 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

    View Slide

  35. 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

    View Slide

  36. 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

    View Slide

  37. 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

    View Slide

  38. 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

    View Slide

  39. 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

    View Slide

  40. 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

    View Slide

  41. Trait Detection
    Friday, June 8, 12

    View Slide

  42. 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

    View Slide

  43. 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

    View Slide

  44. Built-in CLI Server
    Friday, June 8, 12

    View Slide

  45. 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

    View Slide

  46. Running the CLI
    Server
    [email protected] ~ $ /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

    View Slide

  47. 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

    View Slide

  48. Using a Router
    [email protected] ~ $ /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

    View Slide

  49. 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

    View Slide

  50. 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

    View Slide

  51. 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

    View Slide

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

    View Slide