Slide 1

Slide 1 text

UNSUNG HEROES OF PHP JAKE SMITH http://joind.in/talk/view/2971

Slide 2

Slide 2 text

Jake Smith [t] @jakefolio [w] http://jakefolio.com [e] [email protected]

Slide 3

Slide 3 text

Clean Your Inputs with filter_var();

Slide 4

Slide 4 text

filter_var/filter_input •Available since PHP 5.2.x •Validate or Sanitize variable/input •Input = GET, POST, ENV, COOKIE, SERVER •The input can not be manipulated Source: http://www.php.net/manual/en/filter.filters.php

Slide 5

Slide 5 text

filter_input/filter_has_var Can not add additional fields to filter_input if ($_POST) { $_POST['additional_field'] = "valid string"; $result = filter_input(INPUT_POST, 'additional_field', FILTER_SANITIZE_STRING); // false $result2 = filter_has_var(INPUT_POST, 'additional_field'); // false }

Slide 6

Slide 6 text

Filter - Email •FILTER_VALIDATE_EMAIL •FILTER_SANITIZE_EMAIL •Strip all non-email characters •Email standards based on RFC 822 Source: http://www.faqs.org/rfcs/rfc822.html

Slide 7

Slide 7 text

Filter - email Official RFC822 regular expression (?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)? [ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?: [^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\ ["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+| \Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["() <>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?: (?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000- \031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\". \[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^() <>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["(<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t]) *)?(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)? [ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r \n)?[ \t]))*"(?(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\ [([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\ [\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["() <>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*:(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?: (?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\ \".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r \n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\. (?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)? [ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r \n)?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)* \](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\ \]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\ [([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\ [\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["() <>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?: \r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\ [\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^() <>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t]) *)(?:,\s*(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?: \r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.| (?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\ [\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["() <>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\ [\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)? [ \t])+|\Z|(?=[\["\()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?: (?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000- \031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\ [\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?(?:[^() <>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\. (?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t])) *"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\ \]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\ [([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*))*)?;\s*)

Slide 8

Slide 8 text

Filter - email Source: Validate email examples: returns string if valid and false on failure if (preg_match('/^[_a-z0-9-]+(.[_a-z0-9-]+)*@[a-z0-9-]+(.[a-z0-9-]+)*(.[a-z]{2,4})$/', $email)) { echo "Email Good"; } // test good email address echo filter_var("[email protected]", FILTER_VALIDATE_EMAIL) ? "good\n" : "bad\n"; // Good // test good email address echo filter_var("[email protected]", FILTER_VALIDATE_EMAIL) ? "good\n" : "bad\n"; // Good // not allowed . before @ echo filter_var("[email protected]", FILTER_VALIDATE_EMAIL) ? "good\n" : "bad\n"; // Bad // not allowed .. in domain part echo filter_var("[email protected]", FILTER_VALIDATE_EMAIL) ? "good\n" : "bad\n"; // Bad // not allowed . after @ echo filter_var("[email protected]", FILTER_VALIDATE_EMAIL) ? "good\n" : "bad\n"; // Bad // not allowed double @ echo filter_var("chris@@example.com", FILTER_VALIDATE_EMAIL) ? "good\n" : "bad\n"; // Bad // not allowed @ more than once anywhere echo filter_var("chris@[email protected]", FILTER_VALIDATE_EMAIL) ? "good\n" : "bad\n"; // Bad // must have @ echo filter_var("chris#example.com", FILTER_VALIDATE_EMAIL) ? "good\n" : "bad\n"; // Bad http://www.electrictoolbox.com/php-email-validation-filter-var/

Slide 9

Slide 9 text

Filter - URL •FILTER_VALIDATE_URL •FILTER_SANITIZE_URL •Strip all non-url characters •URL standards based on RFC 2396 • Note that the function will only find ASCII URLs to be valid; internationalized domain names (containing non-ASCII characters) will fail. Source: http://www.faqs.org/rfcs/rfc2396

Slide 10

Slide 10 text

Filter - url URLS to be tested for validation $urls = array( 'http://www.lonestarphp.com', 'http://www.lonestarphp.com', 'http://www.lonestarphp.com/blog', 'http://www.lonestarphp.com/index.html#anchor', 'http://www.lonestarphp.com/index.html?q=123', 'lonestarphp.com', 'www.lonestarphp.com', 'www.lonestarphp.com/blog', 'www.lonestarphp.com/index.html?q=123', '/index.html?q=123', 'https://www.lonestarphp.com/', 'https://localhost', 'https://localhost/', 'https://127.0.0.1/', 'http://.com', 'http://...', 'http://', 'http://i\'me really trying to break this url!!!"£$"%$&*()' );

Slide 11

Slide 11 text

Filter - url URLS validation combinations foreach ($urls AS $i => $url) { $result[$i]['base'] = filter_var($url, FILTER_VALIDATE_URL) ? 'PASS' : 'FAIL'; $result[$i]['path_required'] = filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED) ? 'PASS' : 'FAIL'; $result[$i]['query_required'] = filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED) ? 'PASS' : 'FAIL'; $result[$i]['path_scheme_required'] = filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_PATH_REQUIRED) ? 'PASS' : 'FAIL'; }

Slide 12

Slide 12 text

Filter - url URLS validation results

Slide 13

Slide 13 text

Filter - String •FILTER_SANITIZE_STRING •Strip tags •Flags: • FILTER_FLAG_NO_ENCODE_QUOTES • FILTER_FLAG_STRIP_LOW / FILTER_FLAG_STRIP_HIGH • FILTER_FLAG_ENCODE_LOW / FILTER_FLAG_ENCODE_HIGH • FILTER_FLAG_ENCODE_AMP

Slide 14

Slide 14 text

Filter - string Sanitize string utilizing different flags $string = "\tcafé\n"; // Removes HTML tags (acts like strip_tags()) echo filter_var($string, FILTER_SANITIZE_STRING) . "
"; // This will remove the tab, the line break and HTML tags echo filter_var($string, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW); // This will remove the é and HTML tags. echo filter_var($string, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_HIGH);

Slide 15

Slide 15 text

Filter - string Source: ASCII Table http://www.asciitable.com/

Slide 16

Slide 16 text

Filter - url Source: ASCII Extended Table http://www.asciitable.com/

Slide 17

Slide 17 text

Filter - Boolean •FILTER_VALIDATE_BOOLEAN •returns true for: “yes”, 1, “on”, true •returns false for: “non”, 0, “off”, false

Slide 18

Slide 18 text

Filter - boolean Sanitize string utilizing different flags $data = array( 'terms_of_service' => 'yes', 'logged_in_user' => true, 'forged_field' => 3523621, 'opt_in' => 'no' ); $result = filter_var_array($data, FILTER_VALIDATE_BOOLEAN); var_dump($result); foreach($result AS $key => $val) { if ($val === null) { echo $key . ' Can Not Validate
'; } if ($val === false) { echo $key . ' Failed Validation
'; } } /* OUTPUT array(4) { ["terms_of_service"]=> bool(true) ["logged_in_user"]=> bool(true) ["forged_field"]=> bool(false) ["opt_in"]=> bool(false) } */

Slide 19

Slide 19 text

Filter - boolean Apply filter and flag on each element $result = filter_var_array($data, array( 'terms_of_service' => array( 'filter' => FILTER_VALIDATE_BOOLEAN, 'flags' => FILTER_NULL_ON_FAILURE ), 'logged_in_user' => array( 'filter' => FILTER_VALIDATE_BOOLEAN, 'flags' => FILTER_NULL_ON_FAILURE ), 'forged_field' => array( 'filter' => FILTER_VALIDATE_BOOLEAN, 'flags' => FILTER_NULL_ON_FAILURE ), 'opt_in' => array( 'filter' => FILTER_VALIDATE_BOOLEAN, 'flags' => FILTER_NULL_ON_FAILURE ) )); var_dump($result); /* OUTPUT array(4) { ["terms_of_service"]=> bool(true) ["logged_in_user"]=> bool(true) ["forged_field"]=> NULL ["opt_in"]=> bool(false) } */

Slide 20

Slide 20 text

Filter - boolean Apply filter and flag to all elements with PHP 5.3 closure $result = filter_var_array($data, array_map(function() { return array( 'filter' => FILTER_VALIDATE_BOOLEAN, 'flags' => FILTER_NULL_ON_FAILURE ); }, $data) ); var_dump($result); /* OUTPUT array(4) { ["terms_of_service"]=> bool(true) ["logged_in_user"]=> bool(true) ["forged_field"]=> NULL ["opt_in"]=> bool(false) } */

Slide 21

Slide 21 text

Filter - Integer •FILTER_VALIDATE_INT •FILTER_SANITIZE_INT •remove all characters except digits and +-

Slide 22

Slide 22 text

Filter - integer Validate integer using extra options $year = filter_var('2032', FILTER_VALIDATE_INT, array( 'min_range' => 1927, 'max_range' => 2011) );

Slide 23

Slide 23 text

Filter - Float •FILTER_VALIDATE_FLOAT • FILTER_FLAG_ALLOW_THOUSAND •FILTER_SANITIZE_FLOAT • FILTER_FLAG_ALLOW_FRACTION • FILTER_FLAG_ALLOW_SCIENTIFIC

Slide 24

Slide 24 text

Filter - float Show different types of validation/sanitization // Removes the , even though it's a validate and not a sanitize $totalDonation[] = filter_var('123,523.72', FILTER_VALIDATE_FLOAT, FILTER_FLAG_ALLOW_THOUSAND); // Fails because the ALLOW_THOUSAND flag is not set $totalDonation[] = filter_var('123,523.72', FILTER_VALIDATE_FLOAT); // No sanitization needed $totalDonation[] = filter_var('123,523.72', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_THOUSAND | FILTER_FLAG_ALLOW_FRACTION); // Removes , $totalDonation[] = filter_var('123,523.72', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION); $sciNotation = filter_var('2352e28', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_SCIENTIFIC); foreach($totalDonation AS $donation) { // Failed validation if false returned. if ($donation === false) { echo "FAILED VALIDATION"; } echo $donation . "
"; } echo $sciNotation;

Slide 25

Slide 25 text

Putting it all together!

Slide 26

Slide 26 text

filter_input_array Basic Contact Form HTML

First Name

Last Name

E-mail

Cell Number

Feedback
Please add feedback

Disclaimer
Check box for generic disclaimer

Slide 27

Slide 27 text

filter_input_array Basic Contact Form without filter_input_array if ($_POST) { foreach($_POST AS $id => $val) { $_POST[$id] = strip_tags($val); } if (empty($_POST['first_name'])) { $errors[] = "First Name is a required field."; } if (empty($_POST['last_name'])) { $errors[] = "Last Name is a required field."; } if (!preg_match( '/^[_a-z0-9-]+(.[_a-z0-9-]+)*@[a-z0-9-]+(.[a-z0-9-]+)*(.[a-z]{2,4})$/', $_POST['email'])) { $errors[] = "Email is invalid."; } if (!isset($_POST['disclaimer']) || $_POST['disclaimer'] != 'yes') { $errors[] = "You must accept the disclaimer."; } }

Slide 28

Slide 28 text

Filter - string Basic Contact Form WITH filter_input_array if ($_POST) { $results = filter_input_array(INPUT_POST, array( // Strip Tags 'first_name' => FILTER_SANITIZE_STRING, // Strip Tags 'last_name' => FILTER_SANITIZE_STRING, // Validate Email 'email' => FILTER_VALIDATE_EMAIL, // Strip all non-numeric characters 'cell_phone' => FILTER_SANITIZE_NUMBER_INT, // Strip Tags 'message' => FILTER_SANITIZE_STRING, // Validate Boolean value, return null if can not evaluate to boolean 'disclaimer' => array( 'filter' => FILTER_VALIDATE_BOOLEAN, 'flags' => FILTER_NULL_ON_FAILURE ) )); // Set Errors foreach($results AS $id => $val) { if ($val === NULL || $val === false) { $errors[] = "{$id} is invalid."; } } }

Slide 29

Slide 29 text

Breaking into XML with PHP

Slide 30

Slide 30 text

XML Libraries •SimpleXML •DOMDocument •XMLReader/Writer

Slide 31

Slide 31 text

XML Section Data Feed (Compliments of BreweryDB.com) $data = << 6204 "My" Bock Amber, malty and not too heavy, all around favorite even for the drinkers of the yellow fizzy stuff 1428 2011-06-01T09:39:12+00:00 7219 "Ptarmigan" Pilsner Ptarmigan Pilsner our GABF Silver Medal Winner is A traditional European Style Pilsner with a light hop aroma, smooth malt flavor and a distinctively clean finish. 64 2011-02-25T05:40:25+00:00 7218 "Wheeler" Wheat Wheeler Wheat is a light and refreshing beer to quench your thirst after a hard day of adventure seeking. An American-style wheat beer with just a hint of orange peel and coriander, enjoy it with a slice of fruit if you like, we recommend a slice of orange! 64 2011-02-25T05:36:45+00:00 XML;

Slide 32

Slide 32 text

SimpleXML •Tree Parser •Really awesome for quick and dirty reading •Xpath built-in Source: http://us.php.net/manual/en/class.simplexmlelement.php

Slide 33

Slide 33 text

SimpleXML Source: Read XML string and inject node //$xml = simplexml_load_file(); $xml = simplexml_load_string($data); // $xml = new SimpleXMLElement($data); echo "Enjoy some {$xml->beer[0]->name}
"; $result = $xml->xpath('//beer[brewery=64]'); foreach($result AS $beer) { echo "Found a {$beer->name}
"; } // Add my brew $myBeer = $xml->addChild('beer'); $myBeer->addChild('id', 12252); $myBeer->addChild('name', '512 Pecan Porter'); $myBeer->addChild('description', 'Delicious beer from Austin go try!'); $exportedXML = $xml->asXML(); // $xml->saveXML(); http://us.php.net/manual/en/class.simplexmlelement.php

Slide 34

Slide 34 text

SimpleXML Source: Scrape Craigslist - Searching for “leather” under “furniture” $html = new DOMDocument(); $html->loadHTML(file_get_contents('http://dallas.craigslist.org/search/fua? query=leather&srchType=A&minAsk=&maxAsk=')); $xml = simplexml_import_dom($html); $results = $xml->xpath('//p[@class="row"]'); foreach($results as $listing) { // Strip the " -" from the end of the title $title = substr($listing->a, 0, -2); // Get Image filename from HTML id $imagePath = substr( $listing->span[0]->attributes()->id, strpos($listing->span[0]->attributes()->id, ':')+1 ); echo '

'; echo ($imagePath) ? '' : ''; echo $title; echo '

'; } http://us.php.net/manual/en/class.simplexmlelement.php

Slide 35

Slide 35 text

DOMDocument •Tree Parser •Great at importing HTML/XHTML •Great at modifying/injecting nodes •Xpath built-in Source: http://us.php.net/domdocument

Slide 36

Slide 36 text

DOMDocument Source: Read XML string and inject node $newBeer = << 3252 512 Pecan Porter Delicious nutty beer. 23 2011-06-11T05:36:45+00:00 XML; $xml = new DOMDocument(); $xml->loadXML($exportedXML); // Show name of first beer in xml document (from root, no xpath query) echo $xml->getElementsByTagName('beer')->item(0)->getElementsByTagName('name')->item(0)->nodeValue; $xpath = new DOMXpath($xml); $res = $xpath->query('//beer[1]/name'); // Show name of first beer in xml document (DOMXpath) echo $res->item(0)->nodeValue; $beerXML = new DOMDocument(); $beerXML->loadXML($newBeer); $node = $xml->importNode($beerXML->documentElement, true); $xml->appendChild($node); // $xml->replaceChild(); // $xml->removeChild(); echo $xml->saveXML(); http://us.php.net/domdocument

Slide 37

Slide 37 text

DOMDocument Source: Scrape Craigslist - Searching for “leather” under “furniture” $html = new DOMDocument(); $html->loadHTML(file_get_contents('http://dallas.craigslist.org/search/fua? query=leather&srchType=A&minAsk=&maxAsk=')); $xpath = new DOMXpath($html); $result = $xpath->query('//p[@class="row"]'); foreach($result AS $listing) { $title = substr($listing->getElementsByTagName('a')->item(0)->nodeValue, 0, -2); $imagePath = $listing->getElementsByTagName('span')->item(0)->getAttribute('id'); $imagePath = substr($imagePath, strpos($imagePath, ':')+1); echo '

'; echo ($imagePath) ? '' : ''; echo $title; echo '

'; } http://us.php.net/domdocument

Slide 38

Slide 38 text

XMLReader/Writer •Pull Parser •Full Steam Ahead - only moves forward •Great for large XML documents •Reads/Writes line by line, small memory footprint

Slide 39

Slide 39 text

XMLReader Source: Iterate Feed $reader = new XMLReader(); $reader->open("http://www.brewerydb.com/api/beers/?apikey={$apiKey}"); while($reader->read()) { if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == "beer") { echo "

"; } if ($reader->nodeType == XMLReader::ELEMENT || $reader->nodeType == XMLReader::TEXT) { switch($reader->name) { case "id"; case "name"; case "brewery"; case "description"; case "created"; case "updated"; echo $reader->name . ": "; continue; break; default: } if ($reader->nodeType == XMLReader::TEXT && $reader->value) { echo $reader->value . "
"; } if ($reader->nodeType == XMLReader::END_ELEMENT && $reader->name == "beer") { echo "

"; } } } http://us.php.net/manual/en/class.xmlreader.php

Slide 40

Slide 40 text

XMLWriter Source: Headers and Data header("Content-Type: text/html/force-download"); header("Content-Disposition: attachment; filename=beers.xml"); $beerArray = array( 0 => array( 'id' => 12451, 'name' => 'Shiner 102', 'brewery' => 526, 'description' => 'Lone Star Approved!', 'created' => '2011-06-11T05:36:45+00:00' ), 1 => array( 'id' => 23551, 'name' => '512 Pecan Porter', 'brewery' => 126, 'description' => 'A bit nutty', 'created' => '2011-06-11T05:36:45+00:00' ), 2 => array( 'id' => 35351, 'name' => 'Brooklyn Lager', 'brewery' => 226, 'description' => 'New York City?', 'reviews' => array( 0 => 'Great', 1 => 'Good', 2 => 'Above Average' ), 'created' => '2011-06-11T05:36:45+00:00' ), ); http://us.php.net/manual/en/ref.xmlwriter.php

Slide 41

Slide 41 text

XMLWriter Source: Setup class XMLRecursiveIteratorIterator extends RecursiveIteratorIterator { protected $xml; public function __construct($it, $flag = RecursiveIteratorIterator::SELF_FIRST, XMLWriter $xml) { parent::__construct($it, $flag); $this->xml = $xml; } public function endChildren() { $this->xml->endElement(); } } $xml = new XMLWriter(); $xml->openURI('php://output'); $xml->startDocument('1.0', 'UTF-8'); $xml->setIndent(4); http://us.php.net/manual/en/ref.xmlwriter.php

Slide 42

Slide 42 text

XMLWriter Source: Iteration foreach($beers AS $key => $value) { // If back to the top level create new beer if ($beers->getDepth() == 0) { $xml->startElement('beer'); continue; } // Change current parent to reviews if ($key == "reviews") { $currentParent = "reviews"; } // Check if current value is a review or not $current = (is_int($key) && $currentParent == "reviews") ? "review" : $key; $xml->startElement($current); // Don't end the element if it is the start of a child list if (!$beers->hasChildren()) { $xml->text($value); $xml->endElement(); } } // Close all open tags $xml->endDocument(); http://us.php.net/manual/en/ref.xmlwriter.php

Slide 43

Slide 43 text

XML Recap - SimpleXML •Great for reading XML •Is Iterable (we’ll talk more on this) •Is NOT the end all be all for XML •Has xpath (tree traversing)

Slide 44

Slide 44 text

XML Recap - DOMDocument •Great for manipulating XML •Can properly load (X)HTML files •Has xpath (tree traversing)

Slide 45

Slide 45 text

XML Recap - XMLReader/Writer •Extremely fast •Handles stream context for source •Best used with large XML docs or streams •Forward moving (pull)

Slide 46

Slide 46 text

1...Iterator 2...Iterator 3...Iterator floor();

Slide 47

Slide 47 text

What is an Iterator? Source: http://en.wikipedia.org/wiki/Iterator An iterator is an object that enables a programmer to traverse a container. Various types of iterators are often provided via a container's interface. “ ”

Slide 48

Slide 48 text

Quotes in the Community Source: http://fabien.potencier.org/article/44/php-iterators-and-streams-are-awesome PHP also have a lot of awesome features; at least two of them are in my opinion largely underused: Iterators and Streams. “ ” Fabien Potencier (Lead Developer of Symfony Project)

Slide 49

Slide 49 text

Iterator Interfaces •Traversable •Iterator •RecursiveIterator •Countable •SeekableIterator Source: http://www.php.net/manual/en/spl.iterators.php

Slide 50

Slide 50 text

Interface - Iterator Source: http://us.php.net/manual/en/class.iterator.php Iterator extends Traversable { /* Methods */ abstract public mixed current ( void ) abstract public scalar key ( void ) abstract public void next ( void ) abstract public void rewind ( void ) abstract public boolean valid ( void ) }

Slide 51

Slide 51 text

Interface - RecursiveIterator Source: http://www.php.net/manual/en/spl.iterators.php RecursiveIterator extends Iterator { /* Methods */ public RecursiveIterator getChildren ( void ) public bool hasChildren ( void ) /* Inherited methods */ abstract public mixed Iterator::current ( void ) abstract public scalar Iterator::key ( void ) abstract public void Iterator::next ( void ) abstract public void Iterator::rewind ( void ) abstract public boolean Iterator::valid ( void ) }

Slide 52

Slide 52 text

DIRECTORY ITERATORS

Slide 53

Slide 53 text

DirectoryIterator Source: Output directory content for Zend Framework $it = new DirectoryIterator('lib/Zend'); foreach ($it AS $file) { echo $file->getFilename() . "
"; } OUTPUT: . .. .DS_Store Acl Acl.php Amf Application Application.php Auth Auth.php Barcode Barcode.php Cache Cache.php Captcha Cloud CodeGenerator Config Config.php Console Controller Crypt Crypt.php Currency Currency.php Date http://us.php.net/manual/en/class.directoryiterator.php

Slide 54

Slide 54 text

DirectoryIterator - SPLFileInfo Source: Methods available $it = new DirectoryIterator('lib/Zend'); foreach ($it AS $file) { echo $file->getFilename() . "
"; } OUTPUT: /* Methods available for $file public int getATime ( void ) public string getBasename ([ string $suffix ] ) public int getCTime ( void ) public string getExtension ( void ) public SplFileInfo getFileInfo ([ string $class_name ] ) public string getFilename ( void ) public int getGroup ( void ) public int getInode ( void ) public string getLinkTarget ( void ) public int getMTime ( void ) public int getOwner ( void ) public string getPath ( void ) public SplFileInfo getPathInfo ([ string $class_name ] ) public string getPathname ( void ) public int getPerms ( void ) public string getRealPath ( void ) public int getSize ( void ) public string getType ( void ) public bool isDir ( void ) public bool isExecutable ( void ) public bool isFile ( void ) public bool isLink ( void ) public bool isReadable ( void ) public bool isWritable ( void ) */ http://us.php.net/manual/en/class.splfileinfo.php

Slide 55

Slide 55 text

FileSystemIterator (PHP 5.3.x) Source: Output directory content for Zend Framework $it = new FileSystemIterator('lib/Zend'); foreach ($it AS $path => $file) { echo $path . " - " . $file->getFilename() . "
"; } OUTPUT: lib/Zend/.DS_Store - .DS_Store lib/Zend/Acl - Acl lib/Zend/Acl.php - Acl.php lib/Zend/Amf - Amf lib/Zend/Application - Application lib/Zend/Application.php - Application.php lib/Zend/Auth - Auth lib/Zend/Auth.php - Auth.php lib/Zend/Barcode - Barcode lib/Zend/Barcode.php - Barcode.php lib/Zend/Cache - Cache lib/Zend/Cache.php - Cache.php lib/Zend/Captcha - Captcha lib/Zend/Cloud - Cloud lib/Zend/CodeGenerator - CodeGenerator lib/Zend/Config - Config lib/Zend/Config.php - Config.php lib/Zend/Console - Console http://us.php.net/manual/en/class.filesystemiterator.php

Slide 56

Slide 56 text

GlobIterator (PHP 5.3.x) Source: Output directory content for Zend Framework $it = new GlobIterator('lib/Zend/*'); foreach ($it AS $path => $file) { echo $path . " - " . $file->getFilename() . "
"; } OUTPUT: lib/Zend/Acl - Acl lib/Zend/Acl.php - Acl.php lib/Zend/Amf - Amf lib/Zend/Application - Application lib/Zend/Application.php - Application.php lib/Zend/Auth - Auth lib/Zend/Auth.php - Auth.php lib/Zend/Barcode - Barcode lib/Zend/Barcode.php - Barcode.php lib/Zend/Cache - Cache lib/Zend/Cache.php - Cache.php lib/Zend/Captcha - Captcha lib/Zend/Cloud - Cloud lib/Zend/CodeGenerator - CodeGenerator lib/Zend/Config - Config lib/Zend/Config.php - Config.php lib/Zend/Console - Console http://us.php.net/manual/en/class.globiterator.php

Slide 57

Slide 57 text

RecursiveTreeIterator (PHP 5.3.x) Source: Output ASCII view of Directory Structure $it = new RecursiveDirectoryIterator('lib/Zend'); foreach (new RecursiveTreeIterator($it) AS $file) { echo $file . "\n"; } OUTPUT: |-lib/Zend/Acl | |-lib/Zend/Acl/Assert | | \-lib/Zend/Acl/Assert/Interface.php | |-lib/Zend/Acl/Exception.php | |-lib/Zend/Acl/Resource | | \-lib/Zend/Acl/Resource/Interface.php | |-lib/Zend/Acl/Resource.php | |-lib/Zend/Acl/Role | | |-lib/Zend/Acl/Role/Interface.php | | |-lib/Zend/Acl/Role/Registry | | | \-lib/Zend/Acl/Role/Registry/Exception.php | | \-lib/Zend/Acl/Role/Registry.php | \-lib/Zend/Acl/Role.php |-lib/Zend/Acl.php |-lib/Zend/Amf | |-lib/Zend/Amf/Adobe | | |-lib/Zend/Amf/Adobe/Auth.php | | |-lib/Zend/Amf/Adobe/DbInspector.php | | \-lib/Zend/Amf/Adobe/Introspector.php | |-lib/Zend/Amf/Auth | | \-lib/Zend/Amf/Auth/Abstract.php | |-lib/Zend/Amf/Constants.php | |-lib/Zend/Amf/Exception.php http://us.php.net/manual/en/class.recursivetreeiterator.php

Slide 58

Slide 58 text

FILTER ITERATORS

Slide 59

Slide 59 text

Problem: Source: http://www.php.net/manual/en/spl.iterators.php Need to view all files in a directory, but it keeps returning Version Control folders (.svn and .git).

Slide 60

Slide 60 text

FilterIterator Do not show Version Control folders class NoVCSIterator extends FilterIterator { public function accept() { $file = $this->getInnerIterator()->current(); if ($file->isDir() && ($file->getFilename() == '.git' || $file->getFilename() == '.svn')) { return false; } return true; } }

Slide 61

Slide 61 text

Problem: Source: http://www.php.net/manual/en/spl.iterators.php I need to see all images that are over 5MB that have been uploaded.

Slide 62

Slide 62 text

FilterIterator Only show images greater than 5MB class LargeImageFilter extends FilterIterator { protected $safeImageTypes = array('jpg', 'gif', 'png'); public function __construct(Iterator $it, $imageTypes) { parent::__construct($it); if (count($imageTypes) > 0) { $this->safeImageTypes = $imageTypes; } } public function accept() { $file = $this->getInnerIterator()->current(); if (in_array($file->getExtension(), $this->safeImageTypes) && $file->getSize() > 5242880) return true; } } $dir = new DirectoryIterator(UPLOADS_PATH); foreach(new LargeImageFilter($dir) AS $file) { echo $file->getFileName(); }

Slide 63

Slide 63 text

RegexIterator Source: Move integers from front to the back (example from php.net) /* * RegexIterator::MATCH * RegexIterator::REPLACE * RegexIterator::ALL_MATCHES * RegexIterator::SPLIT */ $a = new ArrayIterator(array('test1', 'test2', 'test3')); $it = new RegexIterator($a, '/^(test)(\d+)/', RegexIterator::REPLACE); $it->replacement = '$2:$1'; foreach($it AS $el) { echo $el; } http://us3.php.net/manual/en/class.regexiterator.php

Slide 64

Slide 64 text

Problem: Source: http://www.php.net/manual/en/spl.iterators.php Currently receiving a feed that returns 50 results, but you need to paginate with 10 results per page.

Slide 65

Slide 65 text

LimitIterator Limit feed to 10 per page $page = (int) $_GET['page'] ?: 1; $perPage = 10; $resultOffset = ($page * $perPage) - $perPage; $it = new ArrayIterator($data); // If the offset is greater than the data an exception is thrown "OutOfBoundsException" try{ foreach(new LimitIterator($it, $resultOffset, $perPage) AS $result) { echo "{$result['name']}
"; } } catch (OutOfBoundsException $e) { echo 'No Records Found'; } catch (Exception $e) { echo $e->getMessage(); }

Slide 66

Slide 66 text

Filter Iterators in the wild ChainIterator • CustomFilterIterator • DateRangeFilterIterator • ExcludeDirectoryFilterIterator • FileTypeFilterIterator • FilenameFilterIterator • IgnoreVcsFilterIterator • LimitDepthFilterIterator • SizeRangeFilterIterator • SortableIterator Source: https://github.com/symfony/symfony/tree/master/src/Symfony/Component/Finder/Iterator Symfony2

Slide 67

Slide 67 text

Other Iterators •AppendIterator •Iterate over multiple iterators •Caching Iterator •More of a look ahead, pointer is always one stop behind Source: http://www.php.net/manual/en/spl.iterators.php

Slide 68

Slide 68 text

Iterator Functions •iterator_to_array •iterator_apply •similar to array_walk •iterator_count •used when iterator doesn’t implement countable Source: http://us.php.net/manual/en/ref.spl.php

Slide 69

Slide 69 text

Questions? Concerns? Complaints?

Slide 70

Slide 70 text

Thanks for listening! http://joind.in/talk/view/2971