Successfully reported this slideshow.
Your SlideShare is downloading. ×

Unsung Heroes of PHP

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Loading in …3
×

Check these out next

1 of 70 Ad

More Related Content

Slideshows for you (20)

Viewers also liked (19)

Advertisement

Similar to Unsung Heroes of PHP (20)

Advertisement

Recently uploaded (20)

Unsung Heroes of PHP

  1. 1. UNSUNG HEROES OF PHP JAKE SMITH http://joind.in/talk/view/2971
  2. 2. Jake Smith [t] @jakefolio [w] http://jakefolio.com [e] me@jakefolio.com
  3. 3. Clean Your Inputs with filter_var();
  4. 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 manipulated Source: http://www.php.net/manual/en/filter.filters.php
  5. 5. 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 }
  6. 6. 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
  7. 7. Filter - email Official 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]|.|(?:(?:r n)?[ 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])*))*@(?:(?:r n)?[ 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]))*"(?:(?:r n)?[ 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. 8. Filter - email 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("chris@example.com", FILTER_VALIDATE_EMAIL) ? "goodn" : "badn"; // Good // test good email address echo 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 part echo 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 anywhere echo 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"; // Bad Source: http://www.electrictoolbox.com/php-email-validation-filter-var/
  9. 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. 10. 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!!!"£$"%$&*()' );
  11. 11. 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'; }
  12. 12. Filter - url URLS validation results
  13. 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. 14. Filter - string Sanitize 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 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);
  15. 15. Filter - string ASCII Table Source: http://www.asciitable.com/
  16. 16. Filter - url ASCII Extended Table Source: http://www.asciitable.com/
  17. 17. Filter - Boolean • FILTER_VALIDATE_BOOLEAN • returns true for: “yes”, 1, “on”, true • returns false for: “non”, 0, “off”, false
  18. 18. 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 <br>'; } if ($val === false) { echo $key . ' Failed Validation <br>'; } } /* OUTPUT array(4) { ["terms_of_service"]=> bool(true) ["logged_in_user"]=> bool(true) ["forged_field"]=> bool(false) ["opt_in"]=> bool(false) } */
  19. 19. 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) } */
  20. 20. 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) } */
  21. 21. Filter - Integer • FILTER_VALIDATE_INT • FILTER_SANITIZE_INT • remove all characters except digits and +-
  22. 22. Filter - integer Validate integer using extra options $year = filter_var('2032', FILTER_VALIDATE_INT, array( 'min_range' => 1927, 'max_range' => 2011) );
  23. 23. Filter - Float • FILTER_VALIDATE_FLOAT • FILTER_FLAG_ALLOW_THOUSAND • FILTER_SANITIZE_FLOAT • FILTER_FLAG_ALLOW_FRACTION • FILTER_FLAG_ALLOW_SCIENTIFIC
  24. 24. 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 . "<br>"; } echo $sciNotation;
  25. 25. Putting it all together!
  26. 26. filter_input_array Basic 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. 27. 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."; } }
  28. 28. 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."; } } }
  29. 29. Breaking into XML with PHP
  30. 30. XML Libraries • SimpleXML • DOMDocument • XMLReader/Writer
  31. 31. XML Section Data 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 flavor and 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 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! </description> <brewery>64</brewery> <created>2011-02-25T05:36:45+00:00</created> <updated/> </beer> </beers> XML;
  32. 32. SimpleXML • Tree Parser • Really awesome for quick and dirty reading • Xpath built-in Source: http://us.php.net/manual/en/class.simplexmlelement.php
  33. 33. SimpleXML 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} <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. 34. SimpleXML 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 '<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. 35. DOMDocument • Tree Parser • Great at importing HTML/XHTML • Great at modifying/injecting nodes • Xpath built-in Source: http://us.php.net/domdocument
  36. 36. DOMDocument Read 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. 37. DOMDocument 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 '<p>'; echo ($imagePath) ? '<img src="http://images.craigslist.org/' . $imagePath . '">' : ''; echo $title; echo '</p>'; } Source: http://us.php.net/domdocument
  38. 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. 39. XMLReader 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 "<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. 40. XMLWriter 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' ), ); Source: http://us.php.net/manual/en/ref.xmlwriter.php
  41. 41. XMLWriter 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); Source: http://us.php.net/manual/en/ref.xmlwriter.php
  42. 42. XMLWriter 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(); Source: http://us.php.net/manual/en/ref.xmlwriter.php
  43. 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. 44. XML Recap - DOMDocument • Great for manipulating XML • Can properly load (X)HTML files • Has xpath (tree traversing)
  45. 45. XML Recap - XMLReader/Writer • Extremely fast • Handles stream context for source • Best used with large XML docs or streams • Forward moving (pull)
  46. 46. 1...Iterator 2...Iterator 3...Iterator floor();
  47. 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 container's interface. ” Source: http://en.wikipedia.org/wiki/Iterator
  48. 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. 49. Iterator Interfaces • Traversable • Iterator • RecursiveIterator • Countable • SeekableIterator Source: http://www.php.net/manual/en/spl.iterators.php
  50. 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. 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. 52. DIRECTORY ITERATORS
  53. 53. DirectoryIterator Output directory content for Zend Framework $it = new DirectoryIterator('lib/Zend'); foreach ($it AS $file) { echo $file->getFilename() . "<br>"; } 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 Source: http://us.php.net/manual/en/class.directoryiterator.php
  54. 54. DirectoryIterator - SPLFileInfo Methods 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. 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_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 Source: http://us.php.net/manual/en/class.filesystemiterator.php
  56. 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 - 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 Source: http://us.php.net/manual/en/class.globiterator.php
  57. 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.php Source: http://us.php.net/manual/en/class.recursivetreeiterator.php
  58. 58. FILTER ITERATORS
  59. 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. 60. 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; } }
  61. 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. 62. 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(); }
  63. 63. RegexIterator 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; } Source: http://us3.php.net/manual/en/class.regexiterator.php
  64. 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. 65. 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']} <br>"; } } catch (OutOfBoundsException $e) { echo 'No Records Found'; } catch (Exception $e) { echo $e->getMessage(); }
  66. 66. Filter Iterators in the wild Symfony2 ChainIterator • CustomFilterIterator • DateRangeFilterIterator • ExcludeDirectoryFilterIterator • FileTypeFilterIterator • FilenameFilterIterator • IgnoreVcsFilterIterator • LimitDepthFilterIterator • SizeRangeFilterIterator • SortableIterator Source: https://github.com/symfony/symfony/tree/master/src/Symfony/Component/Finder/Iterator
  67. 67. 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
  68. 68. 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
  69. 69. Questions? Concerns? Complaints?
  70. 70. Thanks for listening! http://joind.in/talk/view/2971

×