unsung heroes of php

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

Upload: jsmith92

Post on 12-Nov-2014

4.052 views

Category:

Technology


1 download

DESCRIPTION

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

TRANSCRIPT

Page 1: Unsung Heroes of PHP

UNSUNG HEROES OF PHPJAKE SMITH

http://joind.in/talk/view/2971

Page 3: Unsung Heroes of PHP

Clean Your Inputs with filter_var();

Page 4: Unsung Heroes of PHP

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

Page 5: Unsung Heroes of PHP

filter_input/filter_has_varCan 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}

Page 6: Unsung Heroes of PHP

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

Page 7: Unsung Heroes of PHP

Filter - emailOfficial 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*)

Page 8: Unsung Heroes of PHP

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 addressecho filter_var("[email protected]", FILTER_VALIDATE_EMAIL) ? "good\n" : "bad\n"; // Good

// test good email addressecho 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 partecho 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 anywhereecho 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/

Page 9: Unsung Heroes of PHP

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

Page 10: Unsung Heroes of PHP

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://i\'me really trying to break this url!!!"£$"%$&*()');

Page 11: Unsung Heroes of PHP

Filter - urlURLS 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'; }

Page 12: Unsung Heroes of PHP

Filter - urlURLS validation results

Page 13: Unsung Heroes of PHP

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

Page 14: Unsung Heroes of PHP

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);

Page 15: Unsung Heroes of PHP

Filter - string

Source:

ASCII Table

http://www.asciitable.com/

Page 16: Unsung Heroes of PHP

Filter - url

Source:

ASCII Extended Table

http://www.asciitable.com/

Page 17: Unsung Heroes of PHP

Filter - Boolean

• FILTER_VALIDATE_BOOLEAN

• returns true for: “yes”, 1, “on”, true

• returns false for: “non”, 0, “off”, false

Page 18: Unsung Heroes of PHP

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) }*/

Page 19: Unsung Heroes of PHP

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) }*/

Page 20: Unsung Heroes of PHP

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) }*/

Page 21: Unsung Heroes of PHP

Filter - Integer

• FILTER_VALIDATE_INT

• FILTER_SANITIZE_INT

• remove all characters except digits and +-

Page 22: Unsung Heroes of PHP

Filter - integerValidate integer using extra options

$year = filter_var('2032', FILTER_VALIDATE_INT, array( 'min_range' => 1927, 'max_range' => 2011));

Page 23: Unsung Heroes of PHP

Filter - Float

• FILTER_VALIDATE_FLOAT

• FILTER_FLAG_ALLOW_THOUSAND

• FILTER_SANITIZE_FLOAT

• FILTER_FLAG_ALLOW_FRACTION

• FILTER_FLAG_ALLOW_SCIENTIFIC

Page 24: Unsung Heroes of PHP

Filter - floatShow 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;

Page 25: Unsung Heroes of PHP

Putting it all together!

Page 26: Unsung Heroes of PHP

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>

Page 27: Unsung Heroes of PHP

filter_input_arrayBasic 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."; }}

Page 28: Unsung Heroes of PHP

Filter - stringBasic 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."; } }}

Page 29: Unsung Heroes of PHP

Breaking into XML with PHP

Page 30: Unsung Heroes of PHP

XML Libraries

• SimpleXML

• DOMDocument

• XMLReader/Writer

Page 31: Unsung Heroes of PHP

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 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;

Page 32: Unsung Heroes of PHP

SimpleXML

• Tree Parser

• Really awesome for quick and dirty reading

• Xpath built-in

Source: http://us.php.net/manual/en/class.simplexmlelement.php

Page 33: Unsung Heroes of PHP

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

Page 34: Unsung Heroes of PHP

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

Page 35: Unsung Heroes of PHP

DOMDocument

• Tree Parser

• Great at importing HTML/XHTML

• Great at modifying/injecting nodes

• Xpath built-in

Source: http://us.php.net/domdocument

Page 36: Unsung Heroes of PHP

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

Page 37: Unsung Heroes of PHP

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

Page 38: Unsung Heroes of PHP

XMLReader/Writer

• Pull Parser

• Full Steam Ahead - only moves forward

• Great for large XML documents

• Reads/Writes line by line, small memory footprint

Page 39: Unsung Heroes of PHP

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

Page 40: Unsung Heroes of PHP

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

Page 41: Unsung Heroes of PHP

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

Page 42: Unsung Heroes of PHP

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

Page 43: Unsung Heroes of PHP

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)

Page 44: Unsung Heroes of PHP

XML Recap - DOMDocument

• Great for manipulating XML

• Can properly load (X)HTML files

• Has xpath (tree traversing)

Page 45: Unsung Heroes of PHP

XML Recap - XMLReader/Writer

• Extremely fast

• Handles stream context for source

• Best used with large XML docs or streams

• Forward moving (pull)

Page 46: Unsung Heroes of PHP

1...Iterator2...Iterator3...Iterator

floor();

Page 47: Unsung Heroes of PHP

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.

Page 48: Unsung Heroes of PHP

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)

Page 49: Unsung Heroes of PHP

Iterator Interfaces

• Traversable

• Iterator

• RecursiveIterator

• Countable

• SeekableIterator

Source: http://www.php.net/manual/en/spl.iterators.php

Page 52: Unsung Heroes of PHP

DIRECTORY ITERATORS

Page 53: Unsung Heroes of PHP

DirectoryIterator

Source:

Output 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.phpDate

http://us.php.net/manual/en/class.directoryiterator.php

Page 54: Unsung Heroes of PHP

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

Page 55: Unsung Heroes of PHP

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_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 - Console

http://us.php.net/manual/en/class.filesystemiterator.php

Page 56: Unsung Heroes of PHP

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 - 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 - Console

http://us.php.net/manual/en/class.globiterator.php

Page 57: Unsung Heroes of PHP

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

Page 58: Unsung Heroes of PHP

FILTER ITERATORS

Page 59: Unsung Heroes of PHP

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).

Page 60: Unsung Heroes of PHP

FilterIteratorDo 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; }}

Page 61: Unsung Heroes of PHP

Problem:

Source: http://www.php.net/manual/en/spl.iterators.php

I need to see all images that are over 5MB that have been uploaded.

Page 62: Unsung Heroes of PHP

FilterIteratorOnly 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();}

Page 63: Unsung Heroes of PHP

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

Page 64: Unsung Heroes of PHP

Problem:

Source: http://www.php.net/manual/en/spl.iterators.php

Currently receiving a feed that returns 50 results, but you need to paginate

with 10 results per page.

Page 65: Unsung Heroes of PHP

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();}

Page 66: Unsung Heroes of PHP

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

Page 67: Unsung Heroes of PHP

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

Page 68: Unsung Heroes of PHP

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

Page 69: Unsung Heroes of PHP

Questions? Concerns? Complaints?

Page 70: Unsung Heroes of PHP

Thanks for listening!

http://joind.in/talk/view/2971