Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Unsung Heroes of PHP

jakefolio
September 26, 2011

Unsung Heroes of PHP

PHP is filled with many amazing functions/classes that we use daily (PDO, array_*, etc.). There are also many classes/functions that have been created to make our lives much easier, many of which are not popularized in tutorials/articles. Whether you're a developer of 6 months or 6 years there are many things that got missed. I will be discussing usefulness of filter_var and the plethora of benefits when using SPL.

jakefolio

September 26, 2011
Tweet

More Decks by jakefolio

Other Decks in Programming

Transcript

  1. 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
  2. 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 }
  3. 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
  4. 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*)
  5. 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/
  6. 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
  7. 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!!!"£$"%$&*()' );
  8. 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'; }
  9. 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
  10. 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);
  11. Filter - Boolean •FILTER_VALIDATE_BOOLEAN •returns true for: “yes”, 1, “on”,

    true •returns false for: “non”, 0, “off”, false
  12. 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) } */
  13. 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) } */
  14. 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) } */
  15. Filter - integer Validate integer using extra options $year =

    filter_var('2032', FILTER_VALIDATE_INT, array( 'min_range' => 1927, 'max_range' => 2011) );
  16. 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;
  17. 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>
  18. 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."; } }
  19. 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."; } } }
  20. 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;
  21. SimpleXML •Tree Parser •Really awesome for quick and dirty reading

    •Xpath built-in Source: http://us.php.net/manual/en/class.simplexmlelement.php
  22. 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} <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(); http://us.php.net/manual/en/class.simplexmlelement.php
  23. 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 '<p>'; echo ($imagePath) ? '<img src="http://images.craigslist.org/' . $imagePath . '">' : ''; echo $title; echo '</p>'; } http://us.php.net/manual/en/class.simplexmlelement.php
  24. DOMDocument •Tree Parser •Great at importing HTML/XHTML •Great at modifying/injecting

    nodes •Xpath built-in Source: http://us.php.net/domdocument
  25. DOMDocument Source: 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(); http://us.php.net/domdocument
  26. 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 '<p>'; echo ($imagePath) ? '<img src="http://images.craigslist.org/' . $imagePath . '">' : ''; echo $title; echo '</p>'; } http://us.php.net/domdocument
  27. XMLReader/Writer •Pull Parser •Full Steam Ahead - only moves forward

    •Great for large XML documents •Reads/Writes line by line, small memory footprint
  28. 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 "<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>"; } } } http://us.php.net/manual/en/class.xmlreader.php
  29. 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
  30. 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
  31. 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
  32. 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)
  33. XML Recap - DOMDocument •Great for manipulating XML •Can properly

    load (X)HTML files •Has xpath (tree traversing)
  34. XML Recap - XMLReader/Writer •Extremely fast •Handles stream context for

    source •Best used with large XML docs or streams •Forward moving (pull)
  35. 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. “ ”
  36. 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)
  37. 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 ) }
  38. 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 ) }
  39. DirectoryIterator Source: 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 http://us.php.net/manual/en/class.directoryiterator.php
  40. DirectoryIterator - SPLFileInfo Source: 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 ) */ http://us.php.net/manual/en/class.splfileinfo.php
  41. 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() . "<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 http://us.php.net/manual/en/class.filesystemiterator.php
  42. 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() . "<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 http://us.php.net/manual/en/class.globiterator.php
  43. 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
  44. 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).
  45. 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; } }
  46. 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(); }
  47. 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
  48. 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(); }
  49. 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
  50. 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
  51. 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