Unsung Heroes of PHP
- 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. 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. 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. 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. 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. Filter - URL
• FILTER_VALIDATE_URL
• FILTER_SANITIZE_URL
• Strip all non-url characters
• URL standards based on RFC 2396
• Note that the function will only find ASCII URLs to be valid;
internationalized domain names (containing non-ASCII characters)
will fail.
Source: http://www.faqs.org/rfcs/rfc2396
- 10. Filter - 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. 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';
}
- 13. Filter - String
• FILTER_SANITIZE_STRING
• Strip tags
• Flags:
• FILTER_FLAG_NO_ENCODE_QUOTES
• FILTER_FLAG_STRIP_LOW / FILTER_FLAG_STRIP_HIGH
• FILTER_FLAG_ENCODE_LOW / FILTER_FLAG_ENCODE_HIGH
• FILTER_FLAG_ENCODE_AMP
- 14. Filter - 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);
- 17. Filter - Boolean
• FILTER_VALIDATE_BOOLEAN
• returns true for: “yes”, 1, “on”, true
• returns false for: “non”, 0, “off”, false
- 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. 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. 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. Filter - Integer
• FILTER_VALIDATE_INT
• FILTER_SANITIZE_INT
• remove all characters except digits
and +-
- 22. Filter - integer
Validate integer using extra options
$year = filter_var('2032', FILTER_VALIDATE_INT, array(
'min_range' => 1927,
'max_range' => 2011)
);
- 23. Filter - Float
• FILTER_VALIDATE_FLOAT
• FILTER_FLAG_ALLOW_THOUSAND
• FILTER_SANITIZE_FLOAT
• FILTER_FLAG_ALLOW_FRACTION
• FILTER_FLAG_ALLOW_SCIENTIFIC
- 24. Filter - 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;
- 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. 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. 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.";
}
}
}
- 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. SimpleXML
• Tree Parser
• Really awesome for quick and dirty
reading
• Xpath built-in
Source: http://us.php.net/manual/en/class.simplexmlelement.php
- 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. 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. DOMDocument
• Tree Parser
• Great at importing HTML/XHTML
• Great at modifying/injecting nodes
• Xpath built-in
Source: http://us.php.net/domdocument
- 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. 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
- 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. 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. 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. 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. XML Recap - SimpleXML
• Great for reading XML
• Is Iterable (we’ll talk more on this)
• Is NOT the end all be all for XML
• Has xpath (tree traversing)
- 44. XML Recap - DOMDocument
• Great for manipulating XML
• Can properly load (X)HTML files
• Has xpath (tree traversing)
- 45. XML Recap - XMLReader/Writer
• Extremely fast
• Handles stream context for source
• Best used with large XML docs or
streams
• Forward moving (pull)
- 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. Quotes in the Community
“ PHP also have a lot of awesome features; at
least two of them are in my opinion largely
underused: Iterators and Streams.
Fabien Potencier (Lead Developer of Symfony Project)
”
Source: http://fabien.potencier.org/article/44/php-iterators-and-streams-are-awesome
- 49. Iterator Interfaces
• Traversable
• Iterator
• RecursiveIterator
• Countable
• SeekableIterator
Source: http://www.php.net/manual/en/spl.iterators.php
- 50. Interface - Iterator
Iterator extends Traversable {
/* Methods */
abstract public mixed current ( void )
abstract public scalar key ( void )
abstract public void next ( void )
abstract public void rewind ( void )
abstract public boolean valid ( void )
}
Source: http://us.php.net/manual/en/class.iterator.php
- 51. Interface - RecursiveIterator
RecursiveIterator extends Iterator {
/* Methods */
public RecursiveIterator getChildren ( void )
public bool hasChildren ( void )
/* Inherited methods */
abstract public mixed Iterator::current ( void )
abstract public scalar Iterator::key ( void )
abstract public void Iterator::next ( void )
abstract public void Iterator::rewind ( void )
abstract public boolean Iterator::valid ( void )
}
Source: http://www.php.net/manual/en/spl.iterators.php
- 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. 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. 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. 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. 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
- 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. 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. 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. 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. 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. 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. 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. 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. 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. 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