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
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!!!"£$"%$&*()'
);
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);
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;
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
38. XMLReader/Writer
• Pull Parser
• Full Steam Ahead - only moves forward
• Great for large XML documents
• Reads/Writes line by line, small
memory footprint
39. 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
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
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
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();
}
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