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

[Sunshine PHP] PHP 5.5: The New Bits

Davey Shafik
February 08, 2013

[Sunshine PHP] PHP 5.5: The New Bits

PHP 5.5 is about to be unleashed into the world; bringing some great new features including generators and coroutines, a finally construct, simple password hashing and other small changes.

Davey Shafik

February 08, 2013
Tweet

More Decks by Davey Shafik

Other Decks in Programming

Transcript

  1. PHP 5.5
    The New Bits

    View full-size slide

  2. •Engineer at Engine Yard on the
    Orchestra PHP Platform
    •Author of Zend PHP 5 Certification
    Study Guide, Sitepoints PHP
    Anthology: 101 Essential Tips, Tricks
    & Hacks & PHP Master: Write
    Cutting Edge Code
    •A contributor to Zend Framework,
    phpdoc, FRAPI and PHP internals
    •@dshafik
    Davey Shafik

    View full-size slide

  3. About These Slides

    View full-size slide

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

    View full-size slide

  5. The Small Stuff

    View full-size slide

  6. The Small Stuff
    • PCRE (Perl Compatible Regular Expression) /e (eval) pattern modifier
    deprecated
    • ext/mysql is now officially deprecated
    • mcrypt_ecb(), mcrypt_cbc(), mcrypt_cfb() and mcrypt_ofb()
    deprecated
    • Drop Windows XP and 2003 support
    • Remove php_logo_guid(), php_egg_logo_guid(),
    php_real_logo_guid(), zend_logo_guid()
    • Return previous handler when passing NULL to set_error_handler()
    and set_exception_handler()
    • Added optional second argument for assert() to specify custom
    message
    • Added boolval()
    • Added support for PBKDF2: hash_pbkdf2() 6

    View full-size slide

  7. The Small Stuff (Cont.)
    intlcal_get_keyword_values_for_locale()
    intlcal_get_now()
    intlcal_get_available_locales()
    intlcal_get()
    intlcal_get_time()
    intlcal_set_time()
    intlcal_add()
    intlcal_set_time_zone()
    intlcal_after()
    intlcal_before()
    intlcal_set()
    intlcal_roll()
    intlcal_clear()
    intlcal_field_difference()
    intlcal_get_actual_maximum()
    intlcal_get_actual_minimum()
    intlcal_get_day_of_week_type()
    intlcal_get_first_day_of_week()
    intlcal_get_greatest_minimum()
    intlcal_get_least_maximum()
    intlcal_get_locale()
    intlcal_get_maximum()
    intlcal_get_minimal_days_in_first_week()
    intlcal_get_minimum()
    intlcal_get_time_zone()
    intlcal_get_type()
    intlcal_get_weekend_transition()
    intlcal_in_daylight_time()
    intlcal_is_equivalent_to()
    intlcal_is_lenient()
    intlcal_is_set()
    intlcal_is_weekend()
    intlcal_set_first_day_of_week()
    intlcal_set_lenient()
    intlcal_equals()
    intlcal_get_repeated_wall_time_option()
    intlcal_get_skipped_wall_time_option()
    intlcal_set_repeated_wall_time_option()
    intlcal_set_skipped_wall_time_option()
    intlcal_from_date_time()
    intlcal_to_date_time()
    intlcal_get_error_code()
    intlcal_get_error_message()
    intlgregcal_create_instance()
    intlgregcal_set_gregorian_change()
    intlgregcal_get_gregorian_change()
    intlgregcal_is_leap_year()
    intltz_create_time_zone()
    intltz_create_default()
    intltz_get_id()
    intltz_get_gmt()
    intltz_get_unknown()
    intltz_create_enumeration()
    intltz_count_equivalent_ids()
    intltz_create_time_zone_id_enumeration()
    intltz_get_canonical_id()
    intltz_get_region()
    intltz_get_tz_data_version()
    intltz_get_equivalent_id()
    intltz_use_daylight_time()
    intltz_get_offset()
    intltz_get_raw_offset()
    intltz_has_same_rules()
    intltz_get_display_name()
    intltz_get_dst_savings()
    intltz_from_date_time_zone()
    intltz_to_date_time_zone()
    intltz_get_error_code()
    intltz_get_error_message()
    datefmt_format_object()
    datefmt_get_calendar_object()
    datefmt_get_timezone()
    datefmt_set_timezone()
    datefmt_get_calendar_object()
    intlcal_create_instance()
    Tons of new ext/intl changes (75 new functions!)

    View full-size slide

  8. More on boolval()
    • Identical to: (bool) $var
    • Returns false for empty arrays and strings, and
    zero.
    • Everything else returns true (except false!)
    9
    var_dump(boolval([]));
    bool(false)
    var_dump(boolval(""));
    bool(false)
    var_dump(boolval(new stdClass()));
    bool(true)
    var_dump(boolval(["foo", "bar"]);
    bool(true)

    View full-size slide

  9. NULL with
    set_(error|exception)_handler

    View full-size slide

  10. More on set_(error|exception)_handler
    11
    • Passing NULL sets the handler to default
    var_dump(set_error_handler(function()2{2}));
    22NULL
    2
    var_dump(set_error_handler(null));
    22object(Closure)#1#(0)#{
    22}
    2
    var_dump(set_error_handler(null));
    22NULL

    View full-size slide

  11. assert() Descriptions

    View full-size slide

  12. More on assert()
    • New argument to provide a description of failure
    13
    assert_options(ASSERT_ACTIVE, IS_ASSERT_ACTIVE);
    function foo($bar, $bat) {
    assert(
    $bar < $bat,
    "Second arg is more than first"
    );'
    }
    foo(2, 1);
    Warning: assert(): Second arg is less than first
    failed in on line <#>

    View full-size slide

  13. list() support in foreach

    View full-size slide

  14. list() support in foreach
    15
    • Allows assignment of nested array values (1st level)
    to multiple variables, within the foreach declaration
    $result = [
    [
    'name' => 'Davey Shafik',
    'email' => '[email protected]',
    ],
    [
    'name' => 'Helgi Þormar Þorbjörnsson',
    'email' => '[email protected]',
    ]
    ];
    foreach ($result as list($name, $email)) {
    echo $name, ': ', $email . PHP_EOL;
    }

    View full-size slide

  15. empty() supports any expression

    View full-size slide

  16. empty() supports any expression
    17
    • Prior to 5.5, empty() only allowed variables as input.
    Now it can be called on any expression, e.g. function
    calls
    if (empty(some_function()) {
    // Do something
    }

    View full-size slide

  17. String/Array Dereferencing

    View full-size slide

  18. String/Array Dereferencing
    19
    • PHP 5.4 added support for function dereferencing,
    5.5 adds the same feature to constant strings and
    arrays
    // Added in PHP 5.4:
    someFunction()[$key];
    // Now available in PHP 5.5
    "somestring"[$key];
    // And:
    ["foo", "bar", "baz"][$key];
    // Note: $key can be any valid expression!

    View full-size slide

  19. “finally” keyword

    View full-size slide

  20. “finally” keyword
    21
    • Code within a finally block always is run after
    either of the try, or catch blocks.
    try {
    // Try something
    } catch (\Exception $exception) {
    // Handle exception
    } finally {
    // Whatever happened, do this
    }

    View full-size slide

  21. Fully Qualified Classname
    Constant

    View full-size slide

  22. Fully Qualified Classname Constant
    23
    • Easy access to the fully qualified class name via a
    simple constant. Allows for easy dynamic creation of
    class (think: Reflection, Unit Testing)
    namespace App {
    class Config { }
    $className = "Config";
    new $className; // Fatal error: Class 'Config' not found
    // Instead:
    $className = "App\Config";
    new $className; // Works
    // Added in 5.5:
    $className = Config::class; // = App\Config
    new $className;
    }

    View full-size slide

  23. Simple Password Hashing

    View full-size slide

  24. Simple Password Hashing
    • Makes password hashing super easy
    • Purpose: to make sure everyone uses safe password
    storage
    • Uses the excellent bcrypt (currently)
    • No salting is required
    • The hash itself identifies the algorithm, salt and
    options options when passed to
    password_verify()
    • You may pass an array with salt and cost as third
    argument to password_hash()
    25

    View full-size slide

  25. Simple Password Hashing (cont.)
    26
    $options = [
    'cost' => 20,
    'salt' => 'bcryptuses22characters'
    ];
    $hash = password_hash("testing", PASSWORD_DEFAULT, $options);
    $hash = password_hash("testing", PASSWORD_DEFAULT);
    if (password_verify("testing", $hash)) {
    // valid
    }
    Specify Options:

    View full-size slide

  26. Simple Password Hashing (cont.)
    • Also provides two helper functions:
    • password_needs_rehash() will determine if the hash uses
    the current algorithm, cost and salt, returning true if it doesn’t
    match.
    • password_get_info() returns an array providing information
    about a hash such as algorithm, cost and salt.
    27

    View full-size slide

  27. More on password security

    View full-size slide

  28. More on password security
    • A strong salt makes a dictionary attack much more
    difficult
    • A high cost means it takes a long time (say, 1/10th
    second) to generate a single password, making brute
    force attacks too slow to be effective
    • The cost is what makes SHA-1 and MD5 poor
    options because they are designed to be fast, this is
    the enemy of security.
    • Additionally, MD5 suffers from too many easy
    collisions (e.g. two different strings that create the
    same hash)
    29
    Goal: Make both dictionary and brute force attacks difficult.

    View full-size slide

  29. Generators
    • Introduces new yield keyword - execution is
    handed back to the iterating mechanism (e.g.
    foreach) and then continues from, the yield
    • Functions and methods are automatically return
    generators when yield is found within them
    • Generators are just simple ways to implement
    iterators; without having to duplicate a bunch of
    boilerplate code
    • Technically implemented using the Generator class,
    similar to the magic Closure class.
    31

    View full-size slide

  30. Anatomy of Generator Flow
    32
    function helloGenerator($who) {
    // First iteration starts here
    $greeting = ["Hello", "Hi", "Hola", "Bonjour"][rand(0, 3)];
    yield $greeting; // Control passed back to foreach
    // Next iteration starts here
    yield " "; // Control passed back to foreach
    // Third iteration starts here
    yield ucfirst($who) . "!\n"; // Control passed back to foreach
    }
    $generator = helloGenerator("world"); // No code is executed yet
    foreach ($generator as $value) {
    echo $value;
    }
    Output: $RandomGreeting World!\n

    View full-size slide

  31. Anatomy of Generator Flow (Cont.)
    function MyGenerator() {
    // First iteration starts here
    for ($i = 0; $i < 5; $i++) {
    yield $i; // Control passed back to foreach
    // Second iteration starts here
    // The for iteration completes, and goes to the next loop
    }
    }
    0: 0
    1: 5
    2: 10
    3: 15
    4: 20
    Output

    View full-size slide

  32. Anatomy of Generator Flow (Cont.)
    • A return; (note: a return with a value is a parse error)
    • An exception is thrown (and not caught within the
    generator)
    • There are no more yields
    34
    Generators will return true for valid() until:

    View full-size slide

  33. Sending Data into a Generator

    View full-size slide

  34. Sending data into a Generator
    • You can send any data into a generator
    • It is used as an expression, rather than a statement
    • This also advances the generator
    • You can send and receive at the “same time”
    36
    function logger($fileName) {
    $fileHandle = fopen($fileName, 'a');
    while (true) {
    fwrite($fileHandle, yield . PHP_EOL);
    }
    }
    $logger = logger(__DIR__ . '/log');
    $logger->send('Foo');
    $logger->send('Bar');

    View full-size slide

  35. Confession Time

    View full-size slide

  36. • My first implementation for the next slide didn’t
    work how I expected!
    • Neither did the 2nd, 3rd or 4th...
    • In fact, I thought I found a bug
    • Then I created a test case, and thing started to make
    sense
    • I still don’t think there’s any reasonable use-case for
    this functionality!
    38

    View full-size slide

  37. Test Case
    39
    function2gen()2{
    2222$i2=20;
    2222while2(true)2{
    22222222file_put_contents("./log",2
    222222222222myDate()2.'2'.
    222222222222(yield6$i++)2.2'2'2.
    222222222222PHP_EOL
    22222222,2FILE_APPEND);
    2222}
    }
    2
    function2myDate()2{
    2222return2date("YPmPd2H:i:s");
    }
    2
    $gen2=2gen();
    var_dump($gen=>send("First2Call"));2//#1
    sleep(3);
    var_dump($gen=>send("Second2Call"));2//#2
    Log File
    2013-02-04 03:39:51 First Call
    2013-02-04 03:39:51 Second Call

    View full-size slide

  38. Iteration 1
    40

    View full-size slide

  39. Iteration 1
    40

    View full-size slide

  40. Iteration 1
    40

    View full-size slide

  41. Iteration 1
    40

    View full-size slide

  42. Iteration 1
    40

    View full-size slide

  43. Iteration 1
    40

    View full-size slide

  44. Iteration 1
    40

    View full-size slide

  45. Iteration 1
    40

    View full-size slide

  46. Iteration 1
    40

    View full-size slide

  47. Iteration 1
    40

    View full-size slide

  48. Iteration 1
    40

    View full-size slide

  49. Iteration 1
    40

    View full-size slide

  50. Iteration 1
    40

    View full-size slide

  51. Iteration 2
    41

    View full-size slide

  52. Iteration 2
    41

    View full-size slide

  53. Iteration 2
    41

    View full-size slide

  54. Iteration 2
    41

    View full-size slide

  55. Iteration 2
    41

    View full-size slide

  56. Iteration 2
    41

    View full-size slide

  57. Iteration 2
    41

    View full-size slide

  58. Iteration 2
    41

    View full-size slide

  59. Iteration 2
    41

    View full-size slide

  60. Iteration 2
    41

    View full-size slide

  61. Sending Exceptions into
    Generators

    View full-size slide

  62. Sending Exceptions into Generators
    • Sends an exception into the Generator
    • Throws the exception at the yield
    • The actual yielded value isn’t returned
    43

    View full-size slide

  63. 44
    function gen() {
    echo "Foo\n";
    try {
    while (true) { yield "bat"; }
    } catch (Exception $e) {
    echo "Exception: {$e->getMessage()}\n";
    }
    echo "Bar\n";
    }
    $gen = gen();
    var_dump($gen->current());
    // echos "Foo" and dumps string (3) "bat"
    $gen->throw(new Exception('Test'));
    // echos "Exception: Test" and "Bar"
    var_dump($gen->valid());
    // dumps bool(false)

    View full-size slide

  64. Thank You
    Feedback:
    http://joind.in/8005
    Twitter: @dshafik
    Email: [email protected]
    Slides:
    http://daveyshafik.com/slides

    View full-size slide