Slide 1

Slide 1 text

PHP 5.NEW The Best Bits

Slide 2

Slide 2 text

Proprietary and Confidential •Community Engineer at Engine Yard •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 1 & 2, phpdoc, & PHP internals • Original creator of PHAR/ PHP_Archive • Lead for PHPWomen US •@dshafik Davey Shafik

Slide 3

Slide 3 text

Let’s start a conversation about mental health in tech prompt.engineyard.com

Slide 4

Slide 4 text

About These Slides

Slide 5

Slide 5 text

Proprietary and Confidential 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 About These Slides

Slide 6

Slide 6 text

Proprietary and Confidential Version Indicator: 5.X

Slide 7

Slide 7 text

Proprietary and Confidential Version Indicator: 5.X 5.X + Multiple Versions

Slide 8

Slide 8 text

The Small Stuff

Slide 9

Slide 9 text

PHP 5.3 Release Date: June 30th 2009 (5-15% Faster) 5.3

Slide 10

Slide 10 text

Proprietary and Confidential • Extensions: • ereg deprecated • SPL always enabled • Reflection always enabled • NOWDOC • Goto • stream_context_set_default() • Magic Methods: • __invoke() • __callStatic() • __call() now called on protected/private method access • Performance Increase! PHP 5.3 5.3

Slide 11

Slide 11 text

PHP 5.4 Release Date: March 1st 2012 (10-15% Faster) 5.4

Slide 12

Slide 12 text

Proprietary and Confidential • 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 • UTF-8 by default (instead of iso-8859-1) • Array callbacks — $foo = [$obj, ‘method’]; $foo = [“Class”, “method”]; then: $foo(); • Callable typehint, accepts function names, array callbacks, closures, classes with __invoke() magic method • Better Memory Usage and Performance • (even better than PHP 5.3) PHP 5.4 5.4

Slide 13

Slide 13 text

PHP 5.5 Release Date: June 20th 2013 5.5

Slide 14

Slide 14 text

Proprietary and Confidential • PCRE /e Modifier deprecated • ext/mysql now officially deprecated • boolval() to complement intval(), floatval()/doubleval(), strval(). Same as (bool) $var; • JsonSerializable interface • Fully-qualified Class name constant: ClassName::CLASS • empty() now supports any valid expression • set_(error|exception)_handler() to NULL to return to default behavior PHP 5.5 5.5

Slide 15

Slide 15 text

PHP 5.6 Release Date: August 28th 2014 5.6

Slide 16

Slide 16 text

Proprietary and Confidential • T_POW: ** Exponent operator, raise left operand to the power of right • Constant Scalar Expressions • __debugInfo() magic method — intercept var_dump() • GMP operator overloading (engine level only !) PHP 5.6 5.6

Slide 17

Slide 17 text

Namespaces Better Code Organization 5.3 5.6 +

Slide 18

Slide 18 text

Proprietary and Confidential • Avoid Naming Collisions • Alias Long Names • Must be defined at the top • Relative Namespaces are Supported • Import/Alias with "use" keyword • Can namespace classes, functions, and constants (using const) Namespaces 5.3

Slide 19

Slide 19 text

Proprietary and Confidential Namespaces 5.3

Slide 20

Slide 20 text

PSR-0 A new standard 5.3

Slide 21

Slide 21 text

Proprietary and Confidential http://xkcd.com/927/ 5.3

Slide 22

Slide 22 text

Proprietary and Confidential • Remove leading namespace separator • Replace namespace separator with directory separator • Replace underscores with directory separator • Add .php to the end PSR-0 5.3

Slide 23

Slide 23 text

Proprietary and Confidential PSR-0 5.3

Slide 24

Slide 24 text

Proprietary and Confidential PSR-0 5.3

Slide 25

Slide 25 text

Proprietary and Confidential PSR-0 5.3

Slide 26

Slide 26 text

Proprietary and Confidential PSR-0 5.3

Slide 27

Slide 27 text

Proprietary and Confidential Composer getcomposer.org 5.3

Slide 28

Slide 28 text

Proprietary and Confidential Composer composer.json: { "require": { "monolog/monolog": "1.2.*", "phpunit/phpunit": "3.*", "zend/zendframework": ">=2.0, < 3.0", "zend/zendframework": "~2.0" } } 5.3

Slide 29

Slide 29 text

Proprietary and Confidential Install dependencies (from composer.lock) $ composer install Update dependencies & write composer.lock $ composer update Composer 5.3

Slide 30

Slide 30 text

Proprietary and Confidential

Slide 31

Slide 31 text

Import Namespaced Functions & Constants 5.6

Slide 32

Slide 32 text

Proprietary and Confidential • Prior to PHP 5.6: • Outside of the namespace, function names/constants had to be fully qualified • You could alias the namespace to shorten it (ugh!) • Add two new keyword sequences: • use function \foo\bar\function • use const \foo\bar\BAZ • Use commas to import multiples Import Namespaced Functions & Constants 5.6

Slide 33

Slide 33 text

Proprietary and Confidential Import Namespaced Functions & Constants namespace foo\bar { const HELLO_WORLD = "Hello World"; function strlen($str) { return \strlen($str); } } namespace { use function foo\bar\strlen; use function foo\bar\non_existent; // Doesn't exist! use const foo\bar\HELLO_WORLD; var_dump(strlen(HELLO_WORLD)); // not ambiguous var_dump(non_existent()); // Does not fall-through // to global scope: fatal error } 5.6

Slide 34

Slide 34 text

Proprietary and Confidential Great for DSLs! Import Namespaced Functions & Constants use function html\div, html\p, html\em; $html = div(p('Some', em('Text'))); 5.6

Slide 35

Slide 35 text

Closures 5.3 5.4 +

Slide 36

Slide 36 text

Proprietary and Confidential Closures 5.3

Slide 37

Slide 37 text

Proprietary and Confidential • Explicitly passed in via the use construct Inheriting Scope $who = "World"; $sayHello = function() use ($who) { echo "Hello $who"; }; $sayHello(); 5.3

Slide 38

Slide 38 text

Proprietary and Confidential • $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() $this in closures 5.4

Slide 39

Slide 39 text

Proprietary and Confidential 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 } } 5.4

Slide 40

Slide 40 text

Rebinding $this Or: How to break the object model! 5.4

Slide 41

Slide 41 text

Proprietary and Confidential • 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. Rebinding $this 5.4

Slide 42

Slide 42 text

Proprietary and Confidential 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(); 5.4

Slide 43

Slide 43 text

Proprietary and Confidential Hello Fatal error: Call to private method bar::world() from context 'foo' Output 5.4

Slide 44

Slide 44 text

Proprietary and Confidential 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 5.4

Slide 45

Slide 45 text

Dereferencing 5.4 5.5 +

Slide 46

Slide 46 text

Proprietary and Confidential Array Dereferencing function returnArray() { return ['a' => 'b', 'c' => 'd']; } $foo = returnArray()['a']; // b 5.4 5.5 Literal Dereferencing ["one", "two", "three"][0]; // "one" "foo"[0]; // f

Slide 47

Slide 47 text

Traits AKA Horizontal Re-use 5.4

Slide 48

Slide 48 text

Proprietary and Confidential • Compiler-level copy and paste (almost literally!) • New Keywords: trait, use, as and insteadof • Can use multiple traits – as and insteadof resolve conflicts • Can define methods, abstract methods, and properties • Can be namespaced, identified just like classes/functions/constants Traits 5.4

Slide 49

Slide 49 text

Proprietary and Confidential namespace Ds\Util; trait SecureDebugInfo { public function __debugInfo() { $info = (array) $this; foreach ($info as $key => $value) { // Hide elements starting with '_' if ($key[0] == '_') { unset($info[$key]); } } } } Defining a Trait 5.4

Slide 50

Slide 50 text

Proprietary and Confidential • Uses the “use” keyword • Use multiple traits like namespaces, separate use calls, or comma- separated. Using a Trait namespace Ds; class MyClass { use Util\SecureDebugInfo; } 5.4

Slide 51

Slide 51 text

Proprietary and Confidential trait One { public function one() { } } trait Two { public function two() { } } trait Three { use One, Two; // Trait three now comprises of 
 // all three traits. public function Three() { } } Inheriting In Traits 5.4

Slide 52

Slide 52 text

Proprietary and Confidential class Numbers { use One; // Adds One->one() public function two() { } public function three() { } } class MoreNumbers extends Numbers { use Two; // Two->two() overrides Numbers->two() public function one() { } // Overrides Numbers->one() } (Trait One->one) class EvenMoreNumbers extends MoreNumbers { use Three; // Three->one() overrides MoreNumbers->one() // Three->two() overrides MoreNumbers->two() 
 // (Trait Two->two) // Three->three() overrides inherited 
 Numbers->three() public function three() { } // Overrides Three->three() } Inheritance & Traits 5.4

Slide 53

Slide 53 text

Proprietary and Confidential namespace Ds\Util; trait SecureDebugInfo { public function __debugInfo() { return $this->getData(); } abstract public function getData(); } Trait Requirements 5.4

Slide 54

Slide 54 text

Proprietary and Confidential Fatal error: Trait method has not been applied, because there are collisions with other trait methods on class MyClass { use Ds\Util\SecureDebugInfo, 
 My\Framework\DebugHelper { Ds\Util\SecureDebugInfo::__debugInfo insteadof My\Framework\DebugHelper; } } Conflict Resolution 5.4

Slide 55

Slide 55 text

Proprietary and Confidential class MyClass { use Ds\Util\SecureDebugInfo, My\Framework\DebugHelper { Ds\Util\SecureDebugInfo::__debugInfo insteadof My\Framework\DebugHelper; My\Framework\DebugHelper::__debugInfo as debugHelperInfo; } } Aliases 5.4

Slide 56

Slide 56 text

Proprietary and Confidential class MyClass { use MyTrait { MyTrait::myMethod as protected; MyTrait::myOtherMethod as private AliasName; } } Changing Visibility 5.4

Slide 57

Slide 57 text

Proprietary and Confidential class Numbers { use One, Two; } var_dump(class_uses('Numbers')); Output: array(2) { ["One"]=> string(3) "One" ["Two"]=> string(3) "Two" } Using Array Dereferencing: if (class_uses('MyClass')['SomeTrait']) { // MyClass uses the SomeTrait } Detecting Traits 5.4

Slide 58

Slide 58 text

Proprietary and Confidential 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 Traits

Slide 59

Slide 59 text

Proprietary and Confidential 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 Inheritance/Scope

Slide 60

Slide 60 text

Proprietary and Confidential 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! Precedence

Slide 61

Slide 61 text

Proprietary and Confidential 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 Method Visibility

Slide 62

Slide 62 text

Proprietary and Confidential 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 Method Aliases

Slide 63

Slide 63 text

Proprietary and Confidential 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 Conflicts

Slide 64

Slide 64 text

Proprietary and Confidential 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 Conflict Resolution

Slide 65

Slide 65 text

Short Echo Tags 5.4

Slide 66

Slide 66 text

Proprietary and Confidential No longer depends on short_open_tags Short Echo Tags ="Now I Will Always Work!";?> 5.4

Slide 67

Slide 67 text

Binary Numbers 5.4

Slide 68

Slide 68 text

Proprietary and Confidential Binary Numbers $var = 0b01; // Binary (base 2) In Addition To: $var = 1234; // Integer $var = -123; // Signed Integer (+/-) $var = 1.23; // Float $var = 0123; // Octal (base 8) $var = 0x1A; // Hexadecimal (base 16) 5.4

Slide 69

Slide 69 text

Short Array Syntax 5.4

Slide 70

Slide 70 text

Proprietary and Confidential Short 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']; 5.4

Slide 71

Slide 71 text

Dynamic Method Calls 5.4

Slide 72

Slide 72 text

Proprietary and Confidential Dynamic Method Calls // Variable static methods $var = "staticMethod"; ClassName::{$var}(); // Instantiation Time Access (new ClassName)->instanceMethod();
 
 // UGLY. $var = "instanceMethod"; (new ClassName)->{$var}(); 5.4

Slide 73

Slide 73 text

list() support in foreach 5.5

Slide 74

Slide 74 text

Proprietary and Confidential • Allows assignment of nested array values (1st level) to multiple variables, within the foreach declaration list() support in foreach $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; } 5.5

Slide 75

Slide 75 text

Constant Scalar Expressions 5.6

Slide 76

Slide 76 text

Proprietary and Confidential • Use expressions when defining: • global constants with const keyword • class constants with the const keyword • class properties • static variables • function arguments Constant Scalar Expressions 5.6

Slide 77

Slide 77 text

Proprietary and Confidential • 123 - Integers • 123.456 - Floats • “foo” - Strings • __LINE__ - Line magic constant • __FILE__ - File magic constant • __DIR__ - Directory magic constant • __TRAIT__ - Trait magic constant • __METHOD__ - Method magic constant • __FUNCTION__ - Function magic constant • __NAMESPACE__ - Namespace magic constant • <<

Slide 78

Slide 78 text

Proprietary and Confidential Global constants with const keyword const FOO = 1 + 1; const BAR = 1 << 1; const GREETING = "HELLO"; const BAZ = GREETING." WORLD!" 5.6

Slide 79

Slide 79 text

Proprietary and Confidential Class constants with the const keyword class Foo { const FOO = 1 + 1; const BAR = 1 << 1; const GREETING = "HELLO"; const BAZ = self::GREETING." WORLD!" } 5.6

Slide 80

Slide 80 text

Proprietary and Confidential Class Properties class Foo { const BAZ = 10; } class Bar { public $foo = 1 + 1; public $bar = [ 1 + 1, 1 << 2, Foo::BAZ => "foo "."bar" ]; public $baseDir = __DIR__ . "/base"; } 5.6

Slide 81

Slide 81 text

Proprietary and Confidential Static Variables const BAR = 0x10; function foo() { static $a = 1 + 1; static $b = [1 << 2]; static $c = 0x01 | BAR; } 5.6

Slide 82

Slide 82 text

Proprietary and Confidential Function Arguments const BAR = 1; function f($a = 1 + 1, $b = 2 << 3, $c = BAR?10:100) { } 5.6

Slide 83

Slide 83 text

__debugInfo() 5.6

Slide 84

Slide 84 text

Proprietary and Confidential Magic method to control the output of var_dump() __debugInfo() class File { // "Resource(stream)" isn't all that useful private $fp; // But all the stream meta data is public function __debugInfo() { return $this->fp ? stream_get_meta_data($fp) : []; } public function open($filename, $mode = 'r'){ $this->fp = fopen($filename, $mode); } } 5.6

Slide 85

Slide 85 text

Proprietary and Confidential __debugInfo() (Cont.) $f = new File; var_dump($f); // object(File)#1 { } $f->open('http://php.net'); var_dump($f); /* object(File)#1 { ["wrapper_type"]=> string(4) "http" ["stream_type"]=> string(10) "tcp_socket" etc... */ 5.6

Slide 86

Slide 86 text

“finally” keyword 5.5

Slide 87

Slide 87 text

Proprietary and Confidential • Code within a finally block is always run after either of the try, or catch blocks. • Remember: Catch is optional “finally” keyword try { // Try something } catch (\Exception $exception) { // Handle exception } finally { // Whatever happened, do this } 5.5

Slide 88

Slide 88 text

Fully Qualified Classname Constant 5.5

Slide 89

Slide 89 text

Proprietary and Confidential • Easy access to the fully qualified class name via a simple constant. Allows for easy dynamic creation of class (think: Reflection, Unit Testing) Fully Qualified Classname Constant 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; } 5.5

Slide 90

Slide 90 text

Simple Password Hashing 5.5

Slide 91

Slide 91 text

Proprietary and Confidential • Makes password hashing super easy • Purpose: to make sure everyone uses safe password storage • Uses the excellent bcrypt (currently) • Salting is automatic, but can be supplied • 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() Simple Password Hashing 5.5

Slide 92

Slide 92 text

Proprietary and Confidential Simple Password Hashing (cont.) $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: 5.5

Slide 93

Slide 93 text

Proprietary and Confidential • 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. Simple Password Hashing (cont.) 5.5

Slide 94

Slide 94 text

More on password security 5.5

Slide 95

Slide 95 text

Proprietary and Confidential • 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) More on password security Goal: Make both dictionary and brute force attacks difficult. 5.5

Slide 96

Slide 96 text

Proprietary and Confidential Hashing Rates Algorithm Hashes/ second MD5 SHA-1 SHA-512 bcrypt MD5 180 Billion/ second 65% Faster 99.9997% Faster 99.9999996% Faster SHA-1 63 Billion/ second 185% Slower 99.9994% Faster 99.999887% Faster SHA-512 364,000/ second 49.5M% Slower 17.3M% Slower 80.49% Faster bcrypt 71,000/ second 253.5M% Slower 88.7M% Slower 412% Slower Data Source: http://passwords12.at.ifi.uio.no/Jeremi_Gosney_Password_Cracking_HPC_Passwords12.pdf 5.5

Slide 97

Slide 97 text

Generators 5.5

Slide 98

Slide 98 text

Proprietary and Confidential • 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. Generators 5.5

Slide 99

Slide 99 text

Proprietary and Confidential Anatomy of Generator Flow 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 5.5

Slide 100

Slide 100 text

Proprietary and Confidential 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 5.5

Slide 101

Slide 101 text

Proprietary and Confidential Anatomy of Generator Flow (Cont.) function gen() { echo "One"; yield "Two"; echo "Three"; yield "Four"; echo "Five"; } $generator = gen(); $generator->rewind(); if ($generator->valid()) { echo $generator->current(); } $generator->next(); 5.5

Slide 102

Slide 102 text

Proprietary and Confidential Anatomy of Generator Flow (Cont.) function gen() { echo "One"; yield "Two"; echo "Three"; yield "Four"; echo "Five"; } $generator = gen(); $generator->rewind(); if ($generator->valid()) { echo $generator->current(); } $generator->next(); 5.5

Slide 103

Slide 103 text

Proprietary and Confidential Anatomy of Generator Flow (Cont.) function gen() { echo "One"; yield "Two"; echo "Three"; yield "Four"; echo "Five"; } $generator = gen(); $generator->rewind(); if ($generator->valid()) { echo $generator->current(); } $generator->next(); 5.5

Slide 104

Slide 104 text

Proprietary and Confidential Anatomy of Generator Flow (Cont.) function gen() { echo "One"; yield "Two"; echo "Three"; yield "Four"; echo "Five"; } $generator = gen(); $generator->rewind(); if ($generator->valid()) { echo $generator->current(); } $generator->next(); 5.5

Slide 105

Slide 105 text

Proprietary and Confidential Anatomy of Generator Flow (Cont.) function gen() { echo "One"; yield "Two"; echo "Three"; yield "Four"; echo "Five"; } $generator = gen(); $generator->rewind(); if ($generator->valid()) { echo $generator->current(); } $generator->next(); 5.5

Slide 106

Slide 106 text

Proprietary and Confidential Anatomy of Generator Flow (Cont.) function gen() { echo "One"; yield "Two"; echo "Three"; yield "Four"; echo "Five"; } $generator = gen(); $generator->rewind(); if ($generator->valid()) { echo $generator->current(); } $generator->next(); 5.5

Slide 107

Slide 107 text

Proprietary and Confidential Anatomy of Generator Flow (Cont.) function gen() { echo "One"; yield "Two"; echo "Three"; yield "Four"; echo "Five"; } $generator = gen(); $generator->rewind(); if ($generator->valid()) { echo $generator->current(); } $generator->next(); 5.5

Slide 108

Slide 108 text

Proprietary and Confidential Anatomy of Generator Flow (Cont.) function gen() { echo "One"; yield "Two"; echo "Three"; yield "Four"; echo "Five"; } $generator = gen(); $generator->rewind(); if ($generator->valid()) { echo $generator->current(); } $generator->next(); 5.5

Slide 109

Slide 109 text

Proprietary and Confidential Anatomy of Generator Flow (Cont.) function gen() { echo "One"; yield "Two"; echo "Three"; yield "Four"; echo "Five"; } $generator = gen(); $generator->rewind(); if ($generator->valid()) { echo $generator->current(); } $generator->next(); 5.5

Slide 110

Slide 110 text

Proprietary and Confidential Anatomy of Generator Flow (Cont.) function gen() { echo "One"; yield "Two"; echo "Three"; yield "Four"; echo "Five"; } $generator = gen(); $generator->rewind(); if ($generator->valid()) { echo $generator->current(); } $generator->next(); 5.5

Slide 111

Slide 111 text

Proprietary and Confidential Anatomy of Generator Flow (Cont.) function gen() { echo "One"; yield "Two"; echo "Three"; yield "Four"; echo "Five"; } $generator = gen(); $generator->rewind(); if ($generator->valid()) { echo $generator->current(); } $generator->next(); 5.5

Slide 112

Slide 112 text

Proprietary and Confidential • 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 Anatomy of Generator Flow (Cont.) Generators will return true for valid() until: 5.5

Slide 113

Slide 113 text

Sending Data into a Generator 5.5

Slide 114

Slide 114 text

Proprietary and Confidential • 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” Sending data into a Generator function logger($fileName) { $fileHandle = fopen($fileName, 'a'); while (true) { fwrite($fileHandle, yield . PHP_EOL); } } $logger = logger(__DIR__ . '/log'); $logger->send('Foo'); $logger->send('Bar'); 5.5

Slide 115

Slide 115 text

Confession Time 5.5

Slide 116

Slide 116 text

Proprietary and Confidential • 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 things started to make sense • I still don’t think there’s any reasonable use-case for this functionality! Confession Time 5.5

Slide 117

Slide 117 text

Proprietary and Confidential Test Case function gen() { $i = 0; while (true) { file_put_contents("./log", myDate() .' '. (yield $i++) . ' ' . PHP_EOL , FILE_APPEND); } } function myDate() { return date("Y-m-d H:i:s"); } $gen = gen(); var_dump($gen->send("First Call")); // 1 sleep(3); var_dump($gen->send("Second Call")); // 2 Log File 2013-02-04 03:39:51 First Call 2013-02-04 03:39:51 Second Call 5.5

Slide 118

Slide 118 text

Proprietary and Confidential Iteration 1 5.5

Slide 119

Slide 119 text

Proprietary and Confidential Iteration 1 5.5

Slide 120

Slide 120 text

Proprietary and Confidential Iteration 1 5.5

Slide 121

Slide 121 text

Proprietary and Confidential Iteration 1 5.5

Slide 122

Slide 122 text

Proprietary and Confidential Iteration 1 5.5

Slide 123

Slide 123 text

Proprietary and Confidential Iteration 1 5.5

Slide 124

Slide 124 text

Proprietary and Confidential Iteration 1 5.5

Slide 125

Slide 125 text

Proprietary and Confidential Iteration 1 5.5

Slide 126

Slide 126 text

Proprietary and Confidential Iteration 1 5.5

Slide 127

Slide 127 text

Proprietary and Confidential Iteration 1 5.5

Slide 128

Slide 128 text

Proprietary and Confidential Iteration 1 5.5

Slide 129

Slide 129 text

Proprietary and Confidential Iteration 1 5.5

Slide 130

Slide 130 text

Proprietary and Confidential Iteration 1 5.5

Slide 131

Slide 131 text

Proprietary and Confidential Iteration 2 5.5

Slide 132

Slide 132 text

Proprietary and Confidential Iteration 2 5.5

Slide 133

Slide 133 text

Proprietary and Confidential Iteration 2 5.5

Slide 134

Slide 134 text

Proprietary and Confidential Iteration 2 5.5

Slide 135

Slide 135 text

Proprietary and Confidential Iteration 2 5.5

Slide 136

Slide 136 text

Proprietary and Confidential Iteration 2 5.5

Slide 137

Slide 137 text

Proprietary and Confidential Iteration 2 5.5

Slide 138

Slide 138 text

Proprietary and Confidential Iteration 2 5.5

Slide 139

Slide 139 text

Proprietary and Confidential Iteration 2 5.5

Slide 140

Slide 140 text

Proprietary and Confidential Iteration 2 5.5

Slide 141

Slide 141 text

Sending Exceptions into Generators 5.5

Slide 142

Slide 142 text

Proprietary and Confidential • Sends an exception into the Generator • Throws the exception at the yield • The actual yielded value isn’t returned Sending Exceptions into Generators 5.5

Slide 143

Slide 143 text

Proprietary and Confidential Sending Exceptions into Generators 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)
 5.5

Slide 144

Slide 144 text

Variadic Functions 5.6

Slide 145

Slide 145 text

Proprietary and Confidential Variadic Syntax … $variable 5.6

Slide 146

Slide 146 text

Proprietary and Confidential • Variadic means to accept a variable number of arguments • Previously you needed to use func_num_args()/func_get_args() • Which includes defined arguments also! • New syntax: "… $variable" (triple dot) • Array with just the variable arguments • Self-documenting code • Supports by-reference • Allows type hints • Must be the last argument! Variadic Functions 5.6

Slide 147

Slide 147 text

Proprietary and Confidential Variadic Functions function fn($reqParam, $optParam = null, ...$params) { var_dump($reqParam, $optParam, $params); } fn(1); // 1, null, [] fn(1, 2); // 1, 2, [] fn(1, 2, 3); // 1, 2, [3] fn(1, 2, 3, 4); // 1, 2, [3, 4] fn(1, 2, 3, 4, 5); // 1, 2, [3, 4, 5] 5.6

Slide 148

Slide 148 text

Proprietary and Confidential Variadic Functions — References 5.6 class MySQL implements DB { public function prepare($query, &...$params) { $stmt = $this->pdo->prepare($query); foreach ($params as $i => &$param) { $stmt->bindParam($i + 1, $param); } return $stmt; } // ... } $stmt = $db->prepare(
 'INSERT INTO users (name, email, age) 
 VALUES (?, ?, ?)', $name, $email, $age);
 foreach ($usersToInsert as list($name, $email, $age)) { $stmt->execute(); }

Slide 149

Slide 149 text

Proprietary and Confidential Variadic Functions — Type hints function hooks($name, Callable ... $callbacks) { foreach ($callbacks as $callback) { $callback(); } } 5.6

Slide 150

Slide 150 text

Argument Unpack (AKA: SPLAT) 5.6

Slide 151

Slide 151 text

Proprietary and Confidential Splat Syntax … $variable 5.6

Slide 152

Slide 152 text

Proprietary and Confidential Splat Syntax fn(… $variable); 5.6

Slide 153

Slide 153 text

Proprietary and Confidential • The opposite of variadics, unpack an array (or similar) as arguments • No more call_user_func_array() (which is “slow”) • Valid for any argument list (including new foo(… $var)) • Must be at the end of the argument list • Use it multiple times! Splat 5.6

Slide 154

Slide 154 text

Proprietary and Confidential Splat function test(...$args) { var_dump($args); } test(1, 2, 3); // [1, 2, 3] test(...[1, 2, 3]); // [1, 2, 3] test(...new ArrayIterator([1, 2, 3])); // [1, 2, 3] 5.6

Slide 155

Slide 155 text

Proprietary and Confidential Splat $args1 = [1, 2, 3]; $args2 = [4, 5, 6]; test(...$args1, ...$args2); // [1, 2, 3, 4, 5, 6] test(1, 2, 3, ...$args2); // [1, 2, 3, 4, 5, 6]
 test(...$args1, 4, 5, 6); // [1, 2, 3, 4, 5, 6] 5.6

Slide 156

Slide 156 text

Proprietary and Confidential Feedback & Questions: 
 Twitter: @dshafik Email: [email protected] Slides: http://daveyshafik.com/slides