Save 37% off PRO during our Black Friday Sale! »

[Sunshine PHP] PHP 5.5: The New Bits

Fee39f0c0ffb29d9ac21607ed188be6b?s=47 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.

Fee39f0c0ffb29d9ac21607ed188be6b?s=128

Davey Shafik

February 08, 2013
Tweet

Transcript

  1. PHP 5.5 The New Bits

  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
  3. About These Slides

  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
  5. The Small Stuff

  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
  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!)
  8. boolval()

  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)
  10. NULL with set_(error|exception)_handler

  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
  12. assert() Descriptions

  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 <file> on line <#>
  14. list() support in foreach

  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' => 'davey@engineayrd.com', ], [ 'name' => 'Helgi Þormar Þorbjörnsson', 'email' => 'helgi@engineyard.com', ] ]; foreach ($result as list($name, $email)) { echo $name, ': ', $email . PHP_EOL; }
  16. empty() supports any expression

  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 }
  18. String/Array Dereferencing

  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!
  20. “finally” keyword

  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 }
  22. Fully Qualified Classname Constant

  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; }
  24. Simple Password Hashing

  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
  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:
  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
  28. More on password security

  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.
  30. Generators

  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
  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
  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
  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:
  35. Sending Data into a Generator

  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');
  37. Confession Time

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

  41. Iteration 1 40

  42. Iteration 1 40

  43. Iteration 1 40

  44. Iteration 1 40

  45. Iteration 1 40

  46. Iteration 1 40

  47. Iteration 1 40

  48. Iteration 1 40

  49. Iteration 1 40

  50. Iteration 1 40

  51. Iteration 1 40

  52. Iteration 1 40

  53. Iteration 2 41

  54. Iteration 2 41

  55. Iteration 2 41

  56. Iteration 2 41

  57. Iteration 2 41

  58. Iteration 2 41

  59. Iteration 2 41

  60. Iteration 2 41

  61. Iteration 2 41

  62. Iteration 2 41

  63. Sending Exceptions into Generators

  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
  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)
  66. Thank You Feedback: http://joind.in/8005 Twitter: @dshafik Email: davey@engineyard.com Slides: http://daveyshafik.com/slides