Slide 1

Slide 1 text

© 2014 John Bafford php[world] 2014 — 11/14/2014 “Stupid PHP Tricks” John Bafford! http://bafford.com — @jbafford — [email protected] ! The Brick Factory! http://thebrickfactory.com — @thebrickfactory — [email protected] 1

Slide 2

Slide 2 text

© 2014 John Bafford php[world] 2014 — 11/13/2014 Who Am I? • John Bafford
 Vice President, Programming Services
 The Brick Factory • PHP developer since 1999 • Programmer since 1990 2

Slide 3

Slide 3 text

© 2014 John Bafford php[world] 2014 — 11/13/2014 The Brick Factory • Full Service Web Development Shop • Farragut North, DC • We do lots of Drupal sites 3

Slide 4

Slide 4 text

© 2014 John Bafford php[world] 2014 — 11/13/2014 Output Buffers 4

Slide 5

Slide 5 text

© 2014 John Bafford php[world] 2014 — 11/13/2014 Pop Quiz function a(){ echo 'Hello'; echo 'World'; } function b(){ echo 'Hello', 'World'; } function c(){ echo 'Hello' . 'World'; } 5

Slide 6

Slide 6 text

function a(){ echo 'Hello'; echo 'World'; } ! line # * op fetch ext return operands! ---------------------------------------------------------------------------------! 3 0 > ECHO 'Hello'! 1 ECHO 'World'! 2 > RETURN null! ! ! ! function b(){ echo 'Hello', 'World'; } ! line # * op fetch ext return operands! ---------------------------------------------------------------------------------! 4 0 > ECHO 'Hello'! 1 ECHO 'World'! 2 > RETURN null! ! ! ! function c(){ echo 'Hello' . 'World'; } ! line # * op fetch ext return operands! ---------------------------------------------------------------------------------! 5 0 > CONCAT ~0 'Hello', 'World'! 1 ECHO ~0! 2 > RETURN null!

Slide 7

Slide 7 text

function a(){ echo 'Hello'; echo 'World'; } ! line # * op fetch ext return operands! ---------------------------------------------------------------------------------! 3 0 > ECHO 'Hello'! 1 ECHO 'World'! 2 > RETURN null! ! ! ! function b(){ echo 'Hello', 'World'; } ! line # * op fetch ext return operands! ---------------------------------------------------------------------------------! 4 0 > ECHO 'Hello'! 1 ECHO 'World'! 2 > RETURN null! ! ! ! function c(){ echo 'Hello' . 'World'; } ! line # * op fetch ext return operands! ---------------------------------------------------------------------------------! 5 0 > CONCAT ~0 'Hello', 'World'! 1 ECHO ~0! 2 > RETURN null!

Slide 8

Slide 8 text

function a(){ echo 'Hello'; echo 'World'; } function b(){ echo 'Hello', 'World'; } function c(){ echo 'Hello' . 'World'; } function obwrap($fn) { ob_start(function($s) { return $s . $s; }, 1); $fn(); ob_end_clean(); } $ob = false; for($x = 1; $x < $argc; $x++) { $fn = $argv[$x]; if($fn == ‘--ob') { $ob = true; continue; } echo "$fn:\n"; if($ob) obwrap($fn); else $fn(); echo "\n\n"; } php st-ob.php a b c! a:! HelloWorld! ! b:! HelloWorld! ! c:! HelloWorld!

Slide 9

Slide 9 text

function a(){ echo 'Hello'; echo 'World'; } function b(){ echo 'Hello', 'World'; } function c(){ echo 'Hello' . 'World'; } function obwrap($fn) { ob_start(function($s) { return $s . $s; }, 1); $fn(); ob_end_clean(); } $ob = false; for($x = 1; $x < $argc; $x++) { $fn = $argv[$x]; if($fn == ‘--ob') { $ob = true; continue; } echo "$fn:\n"; if($ob) obwrap($fn); else $fn(); echo "\n\n"; } php st-ob.php a b c! a:! HelloWorld! ! b:! HelloWorld! ! c:! HelloWorld! php st-ob.php --ob a b c! a:! HelloHelloWorldWorld! ! b:! HelloHelloWorldWorld! ! c:! HelloWorldHelloWorld!

Slide 10

Slide 10 text

php st-ob.php --ob a b c! a:! HelloHelloWorldWorld! ! b:! HelloHelloWorldWorld! ! c:! HelloWorldHelloWorld!

Slide 11

Slide 11 text

chunk_size If the optional parameter chunk_size is passed, the buffer will be flushed after any output call which causes the buffer's length to equal or exceed chunk_size. The default value 0 means that the output function will only be called when the output buffer is closed. ! Prior to PHP 5.4.0, the value 1 was a special case value that set the chunk size to 4096 bytes. bool ob_start ( [ callable $output_callback = NULL [, int $chunk_size = 0 [, int $flags = PHP_OUTPUT_HANDLER_STDFLAGS ]]] )

Slide 12

Slide 12 text

function a(){ echo 'Hello'; echo 'World'; } function b(){ echo 'Hello', 'World'; } function c(){ echo 'Hello' . 'World'; } function obwrap($fn) { ob_start(function($s) { return $s . $s; }, 1); $fn(); ob_end_clean(); } $ob = false; for($x = 1; $x < $argc; $x++) { $fn = $argv[$x]; if($fn == ‘--ob') { $ob = true; continue; } echo "$fn:\n"; if($ob) obwrap($fn); else $fn(); echo "\n\n"; } php st-ob.php a b c! a:! HelloWorld! ! b:! HelloWorld! ! c:! HelloWorld! php st-ob.php --ob a b c! a:! HelloHelloWorldWorld! ! b:! HelloHelloWorldWorld! ! c:! HelloWorldHelloWorld!

Slide 13

Slide 13 text

© 2014 John Bafford php[world] 2014 — 11/13/2014 http_build_query 13

Slide 14

Slide 14 text

Generates a URL-encoded query string from the associative (or indexed) array provided. string http_build_query ( mixed $query_data [, string $numeric_prefix [, string $arg_separator [, int $enc_type = PHP_QUERY_RFC1738 ]]] )

Slide 15

Slide 15 text

© 2014 John Bafford php[world] 2014 — 11/13/2014 Please Don’t Write This $url = "https://your.favorite.api/favoritizer/ json?api_key=%s&api_secret= %s¶m_one=value¶m_two=%s&%message=%s"; $encoded = urlencode($some_message) $url = sprintf($url, $api_key, $api_secret, 'value', $param_two, $encoded); 15

Slide 16

Slide 16 text

© 2014 John Bafford php[world] 2014 — 11/13/2014 Write This Instead $url = "https://your.favorite.api/favoritizer/ json?" . http_build_query([ 'api_key' => $api_key, 'api_secret' => $api_secret, 'param_one' => 'value', 'param_two' => $param_two, 'message' => $some_message, ]); 16

Slide 17

Slide 17 text

© 2014 John Bafford php[world] 2014 — 11/13/2014 [] 17

Slide 18

Slide 18 text

$array = []; $array[] = 'foo'; $array[] = 'bar'; print_r($array); /* Array ( [0] => foo [1] => bar ) */

Slide 19

Slide 19 text

$array = []; $array[] = 'foo'; $array[] = 'bar'; print_r($array); /* Array ( [0] => foo [1] => bar ) */ ! ! $x = $array[]; /* Fatal error: Cannot use [] for reading in …/phpworld/StupidPHPTricks/array.php on line 124 */

Slide 20

Slide 20 text

$array = []; $array[] = 'foo'; $array[] = 'bar'; print_r($array); /* Array ( [0] => foo [1] => bar ) */ ! ! $foo = 'foo'; $bar = &$foo; var_dump($foo, $bar); /* string(3) "foo" string(3) "foo" */ ! ! ! $bar = 'bar'; var_dump($foo, $bar); /* string(3) "bar" string(3) "bar" */

Slide 21

Slide 21 text

$array = []; $array[] = 'foo'; $array[] = 'bar'; print_r($array); /* Array ( [0] => foo [1] => bar ) */ $array[] = &$foo; $foo = 'baz'; print_r($array); /* Array ( [0] => foo [1] => bar [2] => baz ) */

Slide 22

Slide 22 text

$array = []; $array[] = 'foo'; $array[] = 'bar'; ! ! $baz = ['foo', 'bar']; $array[] = &$baz; $baz[] = 'baz'; print_r($array); /* Array ( [0] => foo [1] => bar [2] => Array ( [0] => foo [1] => bar [2] => baz ) ) */

Slide 23

Slide 23 text

function setGreek(&$output) { $output = ['α', 'β', 'ɣ', 'δ']; } ! $x = null; setGreek($x); print_r($x); ! /* Array ( [0] => α [1] => β [2] => ɣ [3] => δ ) */

Slide 24

Slide 24 text

function setGreek(&$output) { $output = ['α', 'β', 'ɣ', 'δ']; } ! ! setGreek($x); print_r($x); ! /* Array ( [0] => α [1] => β [2] => ɣ [3] => δ ) */

Slide 25

Slide 25 text

function setGreek(&$output) { $output = ['α', 'β', 'ɣ', 'δ']; } ! $values = [ ['1', '2', '3'], ['a', 'b', 'c'], ]; ! setGreek($values[]); print_r($values); /* Array ( [0] => Array ( [0] => 1 [1] => 2 [2] => 3 ) [1] => Array ( [0] => a [1] => b [2] => c ) [2] => Array ( [0] => α [1] => β [2] => ɣ [3] => δ ) ) */

Slide 26

Slide 26 text

$a = [1, 2, 3]; $b = &$a[]; $c = &$a[]; $a[] = 'a'; $b = 'b'; $c = 'c'; print_r($a); /* Array ( [0] => 1 [1] => 2 [2] => 3 [3] => b [4] => c [5] => a ) */

Slide 27

Slide 27 text

© 2014 John Bafford php[world] 2014 — 11/13/2014 Practical Application of &$arr[] 27

Slide 28

Slide 28 text

$xml = simplexml_load_string(file_get_contents('xml.xml')); $array = json_decode(json_encode((array) $xml), true); $array = array($xml->getName() => $array);

Slide 29

Slide 29 text

function _parse($xml) { $_level = array(); $_cdata = ''; $_data = array(); while($xml->read()) { switch($xml->nodeType) { case XMLReader::ELEMENT: $_cdata = ''; $name = $xml->name; $curLevel = count($_level); if($curLevel == 0) //the root $_level[] = &$_data[$name][]; else $_level[] = &$_level[$curLevel - 1][$name][]; //Fall-through and close the tag if it is empty if(!$xml->isEmptyElement) break; case XMLReader::END_ELEMENT: if($_cdata != '') { $curLevel = count($_level) - 1; $_level[$curLevel] = $_cdata; $_cdata = ''; } array_pop($_level); break; case XMLReader::TEXT: case XMLReader::CDATA: $_cdata .= $xml->value; break; } } return $_data; }

Slide 30

Slide 30 text

one two three four Array(! [foo] => Array(! [0] => Array(! [bar] => Array(! [0] => one! [1] => two! )! ! [baz] => Array(! [0] => three! [1] => Array(! [quux] => Array(! [0] => four! )! )! )! )! )! )

Slide 31

Slide 31 text

© 2014 John Bafford php[world] 2014 — 11/13/2014 array_combine 31

Slide 32

Slide 32 text

Creates an array by using the values from the keys array as keys and the values from the values array as the corresponding values. array array_combine ( array $keys , array $values )

Slide 33

Slide 33 text

© 2014 John Bafford php[world] 2014 — 11/13/2014 array_combine $fd = fopen('somefile.csv', 'r'); $cols = null; while(false !== ($row = fgetcsv($fd))) { if(!$cols) $cols = $row; else if(count($row) == count($cols)) { $row = array_combine($cols, $row); print_r($row); } } 33 A,B,C! 1,2,3! 4,5,6 Array! (! [A] => 1! [B] => 2! [C] => 3! )! Array! (! [A] => 4! [B] => 5! [C] => 6! )!

Slide 34

Slide 34 text

© 2014 John Bafford php[world] 2014 — 11/13/2014 (unset) 34

Slide 35

Slide 35 text

© 2014 John Bafford php[world] 2014 — 11/13/2014 Unset cast • Returns null • That’s it. 35

Slide 36

Slide 36 text

$foo = 'foo'; $bar = (unset)$foo; $foo === 'foo'; $bar === null;

Slide 37

Slide 37 text

© 2014 John Bafford php[world] 2014 — 11/13/2014 WHY?? 37

Slide 38

Slide 38 text

$bar = ( $foo ? FuncA() : (unset)FuncB() );

Slide 39

Slide 39 text

$bar = ( $foo ? FuncA() : (unset)FuncB() ); if($foo) { $bar = FuncA(); } else { FuncB(); $bar = null; }

Slide 40

Slide 40 text

© 2014 John Bafford php[world] 2014 — 11/13/2014 Controlling Runaway Functions 40

Slide 41

Slide 41 text

© 2014 John Bafford php[world] 2014 — 11/13/2014 Controlling Runaway Functions • PHP has limited multithreading support • There’s the pthreads pecl module, but it’s unlikely you have --enable-maintainer-zts enabled 41

Slide 42

Slide 42 text

A tick is an event that occurs for every N low-level tickable statements executed by the parser within the declare block. The value for N is specified using ticks=N within the declare block's directive section. declare(ticks = 1);

Slide 43

Slide 43 text

© 2014 John Bafford php[world] 2014 — 11/13/2014 Method 1 SIGALRM 43

Slide 44

Slide 44 text

class LimitExecutionAlarm { function __construct($time, $fn) { $this->limit = $time; $this->fn = $fn; } function run() { pcntl_signal(SIGALRM, function() { echo “HALT!\n"; exit; }); pcntl_alarm($this->limit); $fn = $this->fn; $fn(); echo "Stopped.\n"; } } function slowFunc() { for($x = 0;; $x++) { echo "Iteration $x\n"; sleep(1); } } $slow = new LimitExecutionAlarm(
 10, ‘slowFunc' ); $slow->run();

Slide 45

Slide 45 text

© 2014 John Bafford php[world] 2014 — 11/13/2014 Method 2 Modify the Original Function 45

Slide 46

Slide 46 text

class LimitExecutionThrottleable { function __construct($time, $fn) { $this->limit = $time; $this->fn = $fn; } function run() { $halt = false; pcntl_signal(SIGALRM, function() use(&$halt) { $halt = true; }); pcntl_alarm($this->limit); $fn = $this->fn; $fn($halt); echo "Stopped.\n"; } } function slowFuncThrottleable(&$halt = false) { for($x = 0;; $x++) { echo "Iteration $x\n"; sleep(1); if($halt) { echo "halt requested\n"; break; } } } $slow = new LimitExecutionThrottleable( 10, ‘slowFuncThrottleable' ); $slow->run();

Slide 47

Slide 47 text

© 2014 John Bafford php[world] 2014 — 11/13/2014 Method 3 fork 47

Slide 48

Slide 48 text

class LimitExecutionFork { function run() { $pid = pcntl_fork(); if($pid == -1) { //error } else if($pid) { //parent echo "Forked $pid\n"; $done = false; pcntl_signal(SIGALRM, function() use($pid) { if(!$done) { posix_kill($pid, SIGTERM); echo "Killed $pid.\n”; } }); pcntl_alarm($this->limit); $status = false; $child = pcntl_wait($status); $done = true; } else { //child $fn = $this->fn; $fn(); exit; } } } function slowFunc() { for($x = 0;; $x++) { echo "Iteration $x\n"; sleep(1); } } $slow = new LimitExecutionFork( 10, ‘slowFunc' ); $slow->run();

Slide 49

Slide 49 text

© 2014 John Bafford php[world] 2014 — 11/14/2014 https://joind.in/talk/view/11915 ! John Bafford! http://bafford.com — @jbafford — [email protected] ! The Brick Factory! http://thebrickfactory.com — @thebrickfactory — [email protected] Questions? 49

Slide 50

Slide 50 text

© 2014 John Bafford php[world] 2014 — 11/14/2014 https://joind.in/talk/view/11915 ! John Bafford! http://bafford.com — @jbafford — [email protected] ! The Brick Factory! http://thebrickfactory.com — @thebrickfactory — [email protected] Thank You! 50