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. •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
  2. 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
  3. 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
  4. 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!)
  5. 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)
  6. 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
  7. 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 <file> on line <#>
  8. 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; }
  9. 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 }
  10. 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!
  11. “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 }
  12. 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; }
  13. 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
  14. 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:
  15. 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
  16. 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.
  17. 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
  18. 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
  19. 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
  20. 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:
  21. 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');
  22. • 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
  23. 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
  24. Sending Exceptions into Generators • Sends an exception into the

    Generator • Throws the exception at the yield • The actual yielded value isn’t returned 43
  25. 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)