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 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 Slide

  3. About These Slides

    View 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 Slide

  5. The Small Stuff

    View 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 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 Slide

  8. boolval()

    View Slide

  9. 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 Slide

  10. NULL with
    set_(error|exception)_handler

    View Slide

  11. 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 Slide

  12. assert() Descriptions

    View Slide

  13. 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 Slide

  14. list() support in foreach

    View Slide

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

  16. empty() supports any expression

    View Slide

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

  18. String/Array Dereferencing

    View Slide

  19. 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 Slide

  20. “finally” keyword

    View Slide

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

  22. Fully Qualified Classname
    Constant

    View Slide

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

  24. Simple Password Hashing

    View Slide

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

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

  27. 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 Slide

  28. More on password security

    View Slide

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

  30. Generators

    View Slide

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

  32. 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 Slide

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

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

  35. Sending Data into a Generator

    View Slide

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

  37. Confession Time

    View Slide

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

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

  40. Iteration 1
    40

    View Slide

  41. Iteration 1
    40

    View Slide

  42. Iteration 1
    40

    View Slide

  43. Iteration 1
    40

    View Slide

  44. Iteration 1
    40

    View Slide

  45. Iteration 1
    40

    View Slide

  46. Iteration 1
    40

    View Slide

  47. Iteration 1
    40

    View Slide

  48. Iteration 1
    40

    View Slide

  49. Iteration 1
    40

    View Slide

  50. Iteration 1
    40

    View Slide

  51. Iteration 1
    40

    View Slide

  52. Iteration 1
    40

    View Slide

  53. Iteration 2
    41

    View Slide

  54. Iteration 2
    41

    View Slide

  55. Iteration 2
    41

    View Slide

  56. Iteration 2
    41

    View Slide

  57. Iteration 2
    41

    View Slide

  58. Iteration 2
    41

    View Slide

  59. Iteration 2
    41

    View Slide

  60. Iteration 2
    41

    View Slide

  61. Iteration 2
    41

    View Slide

  62. Iteration 2
    41

    View Slide

  63. Sending Exceptions into
    Generators

    View Slide

  64. 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 Slide

  65. 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 Slide

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

    View Slide