Unsung Heroes of PHP
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

Unsung Heroes of PHP

on

  • 4,035 views

A talk to describe under utilized tools that exist in PHP. Filter_var, iterators, xml libraries

A talk to describe under utilized tools that exist in PHP. Filter_var, iterators, xml libraries

Statistics

Views

Total Views
4,035
Views on SlideShare
4,034
Embed Views
1

Actions

Likes
5
Downloads
43
Comments
0

1 Embed 1

https://twitter.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Unsung Heroes of PHP Presentation Transcript

  • 1. UNSUNG HEROES OF PHP JAKE SMITHhttp://joind.in/talk/view/2971
  • 2. Jake Smith[t] @jakefolio[w] http://jakefolio.com[e] me@jakefolio.com
  • 3. Clean Your Inputs with filter_var();
  • 4. 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 manipulatedSource: http://www.php.net/manual/en/filter.filters.php
  • 5. filter_input/filter_has_varCan not add additional fields to filter_inputif ($_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}
  • 6. Filter - Email • FILTER_VALIDATE_EMAIL • FILTER_SANITIZE_EMAIL • Strip all non-email characters • Email standards based on RFC 822Source: http://www.faqs.org/rfcs/rfc822.html
  • 7. Filter - emailOfficial RFC822 regular expression(?:(?:rn)?[ t])*(?:(?:(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|"(?:[^"r]|.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|"(?:[^"r]|.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*))*@(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*))*|(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|"(?:[^"r]|.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*)*<(?:(?:rn)?[ t])*(?:@(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*))*(?:,@(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["(<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*))*)*:(?:(?:rn)?[ t])*)?(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|"(?:[^"r]|.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|"(?:[^"r]|.|(?:(?:rn)?[ t]))*"(?(?:rn)?[ t])*))*@(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*))*>(?:(?:rn)?[ t])*)|(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|"(?:[^"r]|.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*)*:(?:(?:rn)?[ t])*(?:(?:(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|"(?:[^"r]|.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|"(?:[^"r]|.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*))*@(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*))*|(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|"(?:[^"r]|.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*)*<(?:(?:rn)?[ t])*(?:@(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*))*(?:,@(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*))*)*:(?:(?:rn)?[ t])*)?(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|"(?:[^"r]|.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|"(?:[^"r]|.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*))*@(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*))*>(?:(?:rn)?[ t])*)(?:,s*(?:(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|"(?:[^"r]|.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|"(?:[^"r]|.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*))*@(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*))*|(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|"(?:[^"r]|.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*)*<(?:(?:rn)?[ t])*(?:@(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*))*(?:,@(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*))*)*:(?:(?:rn)?[ t])*)?(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|"(?:[^"r]|.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|"(?:[^"r]|.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*))*@(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:".[] 000-031]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:".[]]))|[([^[]r]|.)*](?:(?:rn)?[ t])*))*>(?:(?:rn)?[ t])*))*)?;s*)
  • 8. Filter - emailValidate email examples: returns string if valid and false on failureif (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 addressecho filter_var("chris@example.com", FILTER_VALIDATE_EMAIL) ? "goodn" : "badn"; // Good// test good email addressecho filter_var("chris@a.b.c.example.com", FILTER_VALIDATE_EMAIL) ? "goodn" : "badn"; // Good// not allowed . before @echo filter_var("chris.@example.com", FILTER_VALIDATE_EMAIL) ? "goodn" : "badn"; // Bad// not allowed .. in domain partecho filter_var("chris@example..com", FILTER_VALIDATE_EMAIL) ? "goodn" : "badn"; // Bad// not allowed . after @echo filter_var("chris@.example.com", FILTER_VALIDATE_EMAIL) ? "goodn" : "badn"; // Bad// not allowed double @echo filter_var("chris@@example.com", FILTER_VALIDATE_EMAIL) ? "goodn" : "badn"; // Bad// not allowed @ more than once anywhereecho filter_var("chris@exa@mple.com", FILTER_VALIDATE_EMAIL) ? "goodn" : "badn"; // Bad// must have @echo filter_var("chris#example.com", FILTER_VALIDATE_EMAIL) ? "goodn" : "badn"; // BadSource: http://www.electrictoolbox.com/php-email-validation-filter-var/
  • 9. 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
  • 10. Filter - urlURLS 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://ime really trying to break this url!!!"£$"%$&*());
  • 11. Filter - urlURLS validation combinationsforeach ($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;}
  • 12. Filter - urlURLS validation results
  • 13. 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
  • 14. Filter - stringSanitize string utilizing different flags$string = "<strong>tcafén</strong>";// Removes HTML tags (acts like strip_tags())echo filter_var($string, FILTER_SANITIZE_STRING) . "<br>";// This will remove the tab, the line break and HTML tagsecho 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);
  • 15. Filter - stringASCII TableSource: http://www.asciitable.com/
  • 16. Filter - urlASCII Extended TableSource: http://www.asciitable.com/
  • 17. Filter - Boolean• FILTER_VALIDATE_BOOLEAN • returns true for: “yes”, 1, “on”, true • returns false for: “non”, 0, “off”, false
  • 18. Filter - booleanSanitize 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 <br>; } if ($val === false) { echo $key . Failed Validation <br>; }}/* OUTPUTarray(4) { ["terms_of_service"]=> bool(true) ["logged_in_user"]=> bool(true) ["forged_field"]=> bool(false) ["opt_in"]=> bool(false) }*/
  • 19. Filter - booleanApply 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);/* OUTPUTarray(4) { ["terms_of_service"]=> bool(true) ["logged_in_user"]=> bool(true) ["forged_field"]=> NULL ["opt_in"]=> bool(false) }*/
  • 20. Filter - booleanApply 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);/* OUTPUTarray(4) { ["terms_of_service"]=> bool(true) ["logged_in_user"]=> bool(true) ["forged_field"]=> NULL ["opt_in"]=> bool(false) }*/
  • 21. Filter - Integer• FILTER_VALIDATE_INT• FILTER_SANITIZE_INT • remove all characters except digits and +-
  • 22. Filter - integerValidate integer using extra options$year = filter_var(2032, FILTER_VALIDATE_INT, array( min_range => 1927, max_range => 2011));
  • 23. Filter - Float• FILTER_VALIDATE_FLOAT • FILTER_FLAG_ALLOW_THOUSAND• FILTER_SANITIZE_FLOAT • FILTER_FLAG_ALLOW_FRACTION • FILTER_FLAG_ALLOW_SCIENTIFIC
  • 24. Filter - floatShow different types of validation/sanitization// Removes the , even though its 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 . "<br>";}echo $sciNotation;
  • 25. Putting it all together!
  • 26. filter_input_arrayBasic Contact Form HTML<form action="" method="post"> <p> <label>First Name</label><br> <input type="text" name="first_name"> </p> <p> <label>Last Name</label><br> <input type="text" name="last_name"> </p> <p> <label>E-mail</label><br> <input type="email" name="email"> </p> <p> <label>Cell Number</label><br> <input type="text" name="cell_phone"> </p> <p> <label>Feedback</label><br> <textarea name="message">Please add feedback</textarea> </p> <p> <label>Disclaimer</label><br> <input type="checkbox" name="disclaimer" value="yes"> Check box for generic disclaimer </p> <p><input type="submit" value="Submit Form"></p></form>
  • 27. filter_input_arrayBasic Contact Form without filter_input_arrayif ($_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."; }}
  • 28. Filter - stringBasic Contact Form WITH filter_input_arrayif ($_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."; } }}
  • 29. Breaking intoXML with PHP
  • 30. XML Libraries• SimpleXML• DOMDocument• XMLReader/Writer
  • 31. XML SectionData Feed (Compliments of BreweryDB.com)$data = <<<XML <beers> <beer> <id>6204</id> <name>"My" Bock</name> <description> Amber, malty and not too heavy, all around favorite even for the drinkers of the yellow fizzy stuff </description> <brewery>1428</brewery> <created>2011-06-01T09:39:12+00:00</created> <updated/> </beer> <beer> <id>7219</id> <name>"Ptarmigan" Pilsner</name> <description> Ptarmigan Pilsner our GABF Silver Medal Winner is A traditional European Style Pilsner with a light hop aroma, smooth malt flavorand a distinctively clean finish. </description> <brewery>64</brewery> <created>2011-02-25T05:40:25+00:00</created> <updated/> </beer> <beer> <id>7218</id> <name>"Wheeler" Wheat</name> <description> Wheeler Wheat is a light and refreshing beer to quench your thirst after a hard day of adventure seeking. An American-style wheatbeer 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! </description> <brewery>64</brewery> <created>2011-02-25T05:36:45+00:00</created> <updated/> </beer> </beers>XML;
  • 32. SimpleXML • Tree Parser • Really awesome for quick and dirty reading • Xpath built-inSource: http://us.php.net/manual/en/class.simplexmlelement.php
  • 33. SimpleXMLRead 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} <br>";$result = $xml->xpath(//beer[brewery=64]);foreach($result AS $beer) { echo "Found a {$beer->name} <br>";}// 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();Source: http://us.php.net/manual/en/class.simplexmlelement.php
  • 34. SimpleXMLScrape 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 <p>; echo ($imagePath) ? <img src="http://images.craigslist.org/ . $imagePath . "> : ; echo $title; echo </p>;}Source: http://us.php.net/manual/en/class.simplexmlelement.php
  • 35. DOMDocument • Tree Parser • Great at importing HTML/XHTML • Great at modifying/injecting nodes • Xpath built-inSource: http://us.php.net/domdocument
  • 36. DOMDocumentRead XML string and inject node$newBeer = <<<XML <beer> <id>3252</id> <name>512 Pecan Porter</name> <description> Delicious nutty beer. </description> <brewery>23</brewery> <created>2011-06-11T05:36:45+00:00</created> <updated/> </beer>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();Source: http://us.php.net/domdocument
  • 37. DOMDocumentScrape 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 <p>; echo ($imagePath) ? <img src="http://images.craigslist.org/ . $imagePath . "> : ; echo $title; echo </p>;}Source: http://us.php.net/domdocument
  • 38. XMLReader/Writer• Pull Parser• Full Steam Ahead - only moves forward• Great for large XML documents• Reads/Writes line by line, small memory footprint
  • 39. XMLReaderIterate 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 "<p>"; } 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 . "<br>"; } if ($reader->nodeType == XMLReader::END_ELEMENT && $reader->name == "beer") { echo "</p>"; } }}Source: http://us.php.net/manual/en/class.xmlreader.php
  • 40. XMLWriterHeaders and Dataheader("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 ),);Source: http://us.php.net/manual/en/ref.xmlwriter.php
  • 41. XMLWriterSetupclass 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);Source: http://us.php.net/manual/en/ref.xmlwriter.php
  • 42. XMLWriterIterationforeach($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); // Dont 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();Source: http://us.php.net/manual/en/ref.xmlwriter.php
  • 43. 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)
  • 44. XML Recap - DOMDocument• Great for manipulating XML• Can properly load (X)HTML files• Has xpath (tree traversing)
  • 45. XML Recap - XMLReader/Writer• Extremely fast• Handles stream context for source• Best used with large XML docs or streams• Forward moving (pull)
  • 46. 1...Iterator2...Iterator3...Iterator floor();
  • 47. What is an Iterator? “ An iterator is an object that enables a programmer to traverse a container. Various types of iterators are often provided via a containers interface. ”Source: http://en.wikipedia.org/wiki/Iterator
  • 48. Quotes in the Community “ 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) ”Source: http://fabien.potencier.org/article/44/php-iterators-and-streams-are-awesome
  • 49. Iterator Interfaces • Traversable • Iterator • RecursiveIterator • Countable • SeekableIteratorSource: http://www.php.net/manual/en/spl.iterators.php
  • 50. Interface - Iterator 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 ) }Source: http://us.php.net/manual/en/class.iterator.php
  • 51. Interface - RecursiveIterator 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 ) }Source: http://www.php.net/manual/en/spl.iterators.php
  • 52. DIRECTORY ITERATORS
  • 53. DirectoryIteratorOutput directory content for Zend Framework$it = new DirectoryIterator(lib/Zend);foreach ($it AS $file) { echo $file->getFilename() . "<br>";}OUTPUT:....DS_StoreAclAcl.phpAmfApplicationApplication.phpAuthAuth.phpBarcodeBarcode.phpCacheCache.phpCaptchaCloudCodeGeneratorConfigConfig.phpConsoleControllerCryptCrypt.phpCurrencyCurrency.phpDateSource: http://us.php.net/manual/en/class.directoryiterator.php
  • 54. DirectoryIterator - SPLFileInfoMethods available$it = new DirectoryIterator(lib/Zend);foreach ($it AS $file) { echo $file->getFilename() . "<br>";}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 ) */Source: http://us.php.net/manual/en/class.splfileinfo.php
  • 55. FileSystemIterator (PHP 5.3.x)Output directory content for Zend Framework$it = new FileSystemIterator(lib/Zend);foreach ($it AS $path => $file) { echo $path . " - " . $file->getFilename() . "<br>";}OUTPUT:lib/Zend/.DS_Store - .DS_Storelib/Zend/Acl - Acllib/Zend/Acl.php - Acl.phplib/Zend/Amf - Amflib/Zend/Application - Applicationlib/Zend/Application.php - Application.phplib/Zend/Auth - Authlib/Zend/Auth.php - Auth.phplib/Zend/Barcode - Barcodelib/Zend/Barcode.php - Barcode.phplib/Zend/Cache - Cachelib/Zend/Cache.php - Cache.phplib/Zend/Captcha - Captchalib/Zend/Cloud - Cloudlib/Zend/CodeGenerator - CodeGeneratorlib/Zend/Config - Configlib/Zend/Config.php - Config.phplib/Zend/Console - ConsoleSource: http://us.php.net/manual/en/class.filesystemiterator.php
  • 56. GlobIterator (PHP 5.3.x)Output directory content for Zend Framework$it = new GlobIterator(lib/Zend/*);foreach ($it AS $path => $file) { echo $path . " - " . $file->getFilename() . "<br>";}OUTPUT:lib/Zend/Acl - Acllib/Zend/Acl.php - Acl.phplib/Zend/Amf - Amflib/Zend/Application - Applicationlib/Zend/Application.php - Application.phplib/Zend/Auth - Authlib/Zend/Auth.php - Auth.phplib/Zend/Barcode - Barcodelib/Zend/Barcode.php - Barcode.phplib/Zend/Cache - Cachelib/Zend/Cache.php - Cache.phplib/Zend/Captcha - Captchalib/Zend/Cloud - Cloudlib/Zend/CodeGenerator - CodeGeneratorlib/Zend/Config - Configlib/Zend/Config.php - Config.phplib/Zend/Console - ConsoleSource: http://us.php.net/manual/en/class.globiterator.php
  • 57. RecursiveTreeIterator (PHP 5.3.x)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.phpSource: http://us.php.net/manual/en/class.recursivetreeiterator.php
  • 58. FILTER ITERATORS
  • 59. Problem: Need to view all files in a directory, but it keeps returning Version Control folders (.svn and .git).Source: http://www.php.net/manual/en/spl.iterators.php
  • 60. FilterIteratorDo not show Version Control foldersclass NoVCSIterator extends FilterIterator{ public function accept() { $file = $this->getInnerIterator()->current(); if ($file->isDir() && ($file->getFilename() == .git || $file->getFilename() == .svn)) { return false; } return true; }}
  • 61. Problem: I need to see all images that are over 5MB that have been uploaded.Source: http://www.php.net/manual/en/spl.iterators.php
  • 62. FilterIteratorOnly show images greater than 5MBclass 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();}
  • 63. RegexIteratorMove 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;}Source: http://us3.php.net/manual/en/class.regexiterator.php
  • 64. Problem: Currently receiving a feed that returns 50 results, but you need to paginate with 10 results per page.Source: http://www.php.net/manual/en/spl.iterators.php
  • 65. LimitIteratorLimit 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]} <br>"; }} catch (OutOfBoundsException $e) { echo No Records Found;} catch (Exception $e) { echo $e->getMessage();}
  • 66. Filter Iterators in the wild Symfony2 ChainIterator • CustomFilterIterator • DateRangeFilterIterator • ExcludeDirectoryFilterIterator • FileTypeFilterIterator • FilenameFilterIterator • IgnoreVcsFilterIterator • LimitDepthFilterIterator • SizeRangeFilterIterator • SortableIteratorSource: https://github.com/symfony/symfony/tree/master/src/Symfony/Component/Finder/Iterator
  • 67. Other Iterators • AppendIterator • Iterate over multiple iterators • Caching Iterator • More of a look ahead, pointer is always one stop behindSource: http://www.php.net/manual/en/spl.iterators.php
  • 68. Iterator Functions • iterator_to_array • iterator_apply • similar to array_walk • iterator_count • used when iterator doesn’t implement countableSource: http://us.php.net/manual/en/ref.spl.php
  • 69. Questions? Concerns? Complaints?
  • 70. Thanks for listening! http://joind.in/talk/view/2971