SlideShare a Scribd company logo
A Functional Guide to
Cat Herding with PHP
Generators
The Filter/Map/Reduce Pattern for PHP
Generators
A Functional Guide to Cat Herding with PHP Generators
• Blog Post
http://markbakeruk.net/2016/01/19/a-functional-guide-to-cat-herding-with-
php-generators/
• Code Examples
https://github.com/MarkBaker/GeneratorFunctionExamples
A Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP Generators
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.topografix.com/GPX/1/1"
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
<trk>
<name>Roman 2015-11-23</name>
<trkseg>
<trkpt lat="53.54398800" lon="-2.7403680000">
<ele>146.100</ele><time>2015-11-23T11:05:07Z</time>
</trkpt>
<trkpt lat="53.54401600" lon="-2.7402620000">
<ele>141.300</ele><time>2015-11-23T11:05:15Z</time>
</trkpt>
...
<trkpt lat="53.54384500" lon="-2.7426130000">
<ele>110.500</ele><time>2015-11-23T14:58:57Z</time>
</trkpt>
</trkseg>
</trk>
</gpx>
A Functional Guide to Cat Herding with PHP Generators
namespace GpxReader;
class GpxHandler {
protected $gpxReader;
public function __construct($gpxFilename) {
$this->gpxReader = new XMLReader();
$this->gpxReader->open($gpxFilename);
}
public function getElements($elementType) {
while ($this->gpxReader->read()) {
if ($this->gpxReader->nodeType == XMLREADER::ELEMENT &&
$this->gpxReader->name == $elementType) {
$doc = new DOMDocument('1.0', 'UTF-8');
$xml = simplexml_import_dom($doc->importNode($this->gpxReader->expand(), true));
$gpxAttributes = $this->readAttributes($this->gpxReader);
$gpxElement = $this->readChildren($xml);
$gpxElement->position = $gpxAttributes;
yield $gpxElement->timestamp => $gpxElement;
}
}
}
}
A Functional Guide to Cat Herding with PHP Generators
// Create our initial Generator to read the gpx file
$gpxReader = new GpxReaderGpxHandler($gpxFilename);
// Iterate over the trackpoint set from the gpx file,
// displaying each point detail in turn
foreach ($gpxReader->getElements('trkpt') as $time => $element) {
printf(
'%s' . PHP_EOL . ' latitude: %7.4f longitude: %7.4f elevation: %d' . PHP_EOL,
$time->format('Y-m-d H:i:s'),
$element->position->latitude,
$element->position->longitude,
$element->elevation
);
}
A Functional Guide to Cat Herding with PHP Generators
2015-11-23 11:05:07
latitude: 53.5440 longitude: -2.7404 elevation: 146
2015-11-23 11:05:15
latitude: 53.5440 longitude: -2.7403 elevation: 141
2015-11-23 11:05:25
latitude: 53.5440 longitude: -2.7402 elevation: 140
...
2015-11-23 14:58:47
latitude: 53.5439 longitude: -2.7426 elevation: 103
2015-11-23 14:58:57
latitude: 53.5438 longitude: -2.7426 elevation: 110
A Functional Guide to Cat Herding with PHP Generators
Cat Herding with PHP Generators – Filter
• A filter selects only a subset of values from the Traversable.
• The rules for filtering are defined in a callback function.
• If no callback is provided, then only non-empty values are returned.
Cat Herding with PHP Generators – Filter
array_filter()
Filters elements of an array using a callback function.
array array_filter ( array $array [, callable $callback] )
Iterates over each value in the array passing them to the callback function. If the
callback function returns true, the current value from array is returned into the
result array, otherwise it is discarded. Array keys are preserved.
Cat Herding with PHP Generators – Filter
function notEmpty($value) {
return !empty($value);
}
/**
* Version of filter to use with versions of PHP prior to 5.6.0,
* without the `$flag` option
*
**/
function filter(Traversable $filter, Callable $callback = null) {
if ($callback === null) {
$callback = 'notEmpty';
}
foreach ($filter as $key => $value) {
if ($callback($value)) {
yield $key => $value;
}
}
}
Cat Herding with PHP Generators – Filter
array_filter()
Filters elements of an array using a callback function.
array array_filter ( array $array [, callable $callback] )
array array_filter ( array $array [, callable $callback [, int $flag = 0 ]] )
Iterates over each value in the array passing them to the callback function. If the
callback function returns true, the current value from array is returned into the
result array, otherwise it is discarded. Array keys are preserved.
[PHP < 5.6.0]
[PHP >= 5.6.0]
Cat Herding with PHP Generators – Filter
/**
* The `$flag` option (and the constants ARRAY_FILTER_USE_KEY and ARRAY_FILTER_USE_BOTH)
* were introduced in PHP 5.6.0
*
**/
function filter(Traversable $filter, Callable $callback = null, $flag = 0) {
if ($callback === null) {
$callback = 'notEmpty';
}
foreach ($filter as $key => $value) {
switch($flag) {
case ARRAY_FILTER_USE_KEY:
...
case ARRAY_FILTER_USE_BOTH:
...
default:
...
}
}
}
Cat Herding with PHP Generators – Filter
• Time Range
Where was Roman between 11:30 and 12:00?
• Geo-Fencing (“Bounding Box”)
• Inside
Did Osiris go anywhere near the main road?
• Outside
Has Lexie left the house at all?
Cat Herding with PHP Generators – Filter
// Create our initial Generator to read the gpx file
$gpxReader = new GpxReaderGpxHandler($gpxFilename);
// Define the date/time filter parameters
$startTime = new DateTime('2015-03-02 13:20:00Z');
$endTime = new DateTime('2015-03-02 13:30:00Z');
// Create the filter callback with the date/time parameters we've just defined
$timeFilter = function($timestamp) use ($startTime, $endTime) {
return $timestamp >= $startTime && $timestamp <= $endTime;
};
Cat Herding with PHP Generators – Filter
// Iterate over the trackpoint set from the gpx file,
// displaying each point detail in turn
foreach (filter($gpxReader->getElements('trkpt'), $timeFilter, ARRAY_FILTER_USE_KEY)
as $time => $element) {
printf(
'%s' . PHP_EOL . ' latitude: %7.4f longitude: %7.4f elevation: %d' . PHP_EOL,
$time->format('Y-m-d H:i:s'),
$element->position->latitude,
$element->position->longitude,
$element->elevation
);
}
Cat Herding with PHP Generators – Filter
Cat Herding with PHP Generators – Filter
namespace GpxReaderHelpers;
class BoundingBox {
/**
* Identify whether a trackpoint falls inside the defined bounding box
*
* @param GpxReaderGpxElement The trackpoint
* @return boolean If the trackpoint falls outside (false)
* or inside (true) the bounding box
**/
public function inside(GpxReaderGpxElement $point) {
return (($point->position->longitude >= $this->left) &&
($point->position->longitude <= $this->right) &&
($point->position->latitude >= $this->bottom) &&
($point->position->latitude <= $this->top));
}
}
Cat Herding with PHP Generators – Filter
// Create our initial Generator to read the gpx file
$gpxReader = new GpxReaderGpxHandler($gpxFilename);
// Create a bounding box defining the coordinates we want to test each point against
// This bounding box is for inside the house/garden
$boundaries = new GpxReaderHelpersBoundingBox();
$boundaries->setLatitudes(53.54382, 53.54340);
$boundaries->setLongitudes(-2.74059, -2.74005);
// We want to set the filter to include only points inside the bounding box
$boundingBoxFilter = [$boundaries, 'inside'];
Cat Herding with PHP Generators – Filter
// Iterate over the trackpoint set from the gpx file,
// displaying each point detail in turn
foreach (filter($gpxReader->getElements('trkpt'), $boundingBoxFilter) as
$time => $element) {
printf(
'%s' . PHP_EOL . ' latitude: %7.4f longitude: %7.4f elevation: %d' . PHP_EOL,
$time->format('Y-m-d H:i:s'),
$element->position->latitude,
$element->position->longitude,
$element->elevation
);
}
Cat Herding with PHP Generators – Filter
// Iterate over the trackpoint set from the gpx file,
// displaying each point detail in turn
// applying both a time filter (12:00:00-12:20:00 on 2015-11-23)
// and a bounding box filter for inside the house/garden
foreach (filter(
filter(
$gpxReader->getElements('trkpt'), $timeFilter, ARRAY_FILTER_USE_KEY
),
$boundingBoxFilter
) as $time => $element) {
printf(
...
);
}
Cat Herding with PHP Generators
Osiris
Located
Achievement
Unlocked
Cat Herding with PHP Generators – Map
• A map is like a foreach loop that transforms each value in the
Traversable.
• Each input value is transformed into a new output value.
• The rules for the transformation are defined in a callback function.
Cat Herding with PHP Generators – Map
array_map()
Applies the callback to the elements of the given arrays.
array array_map ( callable $callback , array $array1 [, array $... ] )
array_map() returns an array containing all the elements of array1 after applying
the callback function to each one. The number of parameters that the callback
function accepts should match the number of arrays passed to the array_map().
Cat Herding with PHP Generators – Map
function map(Callable $callback, Traversable $iterator) {
foreach ($iterator as $key => $value) {
yield $key => $callback($value);
}
}
Cat Herding with PHP Generators – Map
namespace GpxReaderHelpers;
class DistanceCalculator {
public function setDistance(GpxReaderGpxElement $point) {
$point->distance = $this->calculateDistance($point);
return $point;
}
}
Cat Herding with PHP Generators – Map
// Create our initial Generator to read the gpx file
$gpxReader = new GpxReaderGpxHandler($gpxFilename);
// Set the mapper to calculate the distance between a trackpoint
// and the previous trackpoint
$distanceCalculator = new GpxReaderHelpersDistanceCalculator();
Cat Herding with PHP Generators – Map
// Iterate over the trackpoint set from the gpx file, mapping the distances as we go,
// displaying each point detail in turn
foreach (map([$distanceCalculator, 'setDistance'], $gpxReader->getElements('trkpt'))
as $time => $element) {
printf(
'%s' . PHP_EOL . ' latitude: %7.4f longitude: %7.4f elevation: %d' . PHP_EOL .
' distance from previous point: %5.2f m' . PHP_EOL,
$time->format('Y-m-d H:i:s'),
$element->position->latitude,
$element->position->longitude,
$element->elevation,
$element->distance
);
}
Cat Herding with PHP Generators – Map
function mmap(Callable $callback, Traversable ...$iterators) {
$mi = new MultipleIterator(MultipleIterator::MIT_NEED_ANY);
foreach($iterators as $iterator) {
$mi->attachIterator($iterator);
}
foreach($mi as $values) {
yield $callback(...$values);
}
}
http://nl3.php.net/manual/en/function.array-slice.php
...
Splat Operator
PHP >= 5.6.0
Argument Packing/Unpacking
Cat Herding with PHP Generators
Lexie
Located
Achievement
Unlocked
Cat Herding with PHP Generators – Reduce
• A reduce aggregates all the values in the Traversable to a single value.
• A callback function determines the process for the aggregation.
Cat Herding with PHP Generators – Reduce
array_reduce()
Iteratively reduces the array to a single value using a callback function.
mixed array_reduce ( array $array , callable $callback [, mixed $initial = NULL ] )
array_reduce() applies the callback function iteratively to the elements of the array,
so as to reduce the array to a single value.
Cat Herding with PHP Generators – Reduce
function reduce(Traversable $iterator, Callable $callback, $initial = null) {
$result = $initial;
foreach($iterator as $value) {
$result = $callback($result, $value);
}
return $result;
}
Cat Herding with PHP Generators – Reduce
• Bounding Box
What Coordinates should I use for the bounding box when displaying the track
on a map?
• Distance
How far has Roman walked while he’s been out?
What is the furthest distance that Osiris has travelled from home?
Cat Herding with PHP Generators – Reduce
// Iterate over our trackpoint set from the gpx file (mapping the distance as we go)
// and reducing the results to calculate the total distance travelled
$totalDistance = reduce(
map([$distanceCalculator, 'setDistance'], $gpxReader->getElements('trkpt')),
function($runningTotal, $value) {
$runningTotal += $value->distance;
return $runningTotal;
},
0.0
);
// Display the results of our reduce
printf(
'Total distance travelled is %5.2f km' . PHP_EOL,
$totalDistance / 1000
);
Cat Herding with PHP Generators – Reduce
Total distance travelled is 4.33 km
Cat Herding with PHP Generators – Reduce
namespace GpxReaderHelpers;
class BoundingBox {
function calculate($discard, GpxReaderGpxElement $point) {
$this->top = max($point->position->latitude, $this->top);
$this->bottom = min($point->position->latitude, $this->bottom);
$this->left = min($point->position->longitude, $this->left);
$this->right = max($point->position->longitude, $this->right);
return $this;
}
}
Cat Herding with PHP Generators – Reduce
// Create our initial Generator to read the gpx file
$gpxReader = new GpxReaderGpxHandler($gpxFilename);
// Set our bounding box callback
$boundaries = new GpxReaderHelpersBoundingBox();
// Reduce our trackpoint set from the gpx file against the bounding box callback
$boundingBox = reduce( $gpxReader->getElements('trkpt'), [$boundaries, 'calculate'] );
// Display the results of our reduce
printf(
'Top: %7.4f Bottom: %7.4f' . PHP_EOL . 'Left: %7.4f Right: %7.4f' . PHP_EOL,
$boundingBox->top,
$boundingBox->bottom,
$boundingBox->left,
$boundingBox->right
);
Cat Herding with PHP Generators – Reduce
Top: 53.5445 Bottom: 53.5426
Left: -2.7433 Right: -2.7393
Cat Herding with PHP Generators
Roman
Located
Achievement
Unlocked
Cat Herding with PHP Generators
iterator_apply()
Call a function for every element in an iterator.
int iterator_apply ( Traversable $iterator , callable $function [, array $args ] )
Cat Herding with PHP Generators
iterator_count()
Count the elements in an iterator.
int iterator_count ( Traversable $iterator )
Cat Herding with PHP Generators
iterator_to_array()
Copy all values from the iterator into an array.
array iterator_to_array ( Traversable $iterator [, bool $use_keys = true ] )
Cat Herding with PHP Generators
// Create an instance of the fluent Generator Helper and set our filters,
// mapper offset and limits
// and the display callback to "do" (or execute)
// In this case, the "do" is a display callback,
// but it could also be a "reduce" callback
withGenerator($trackPoints)
->filteredBy($boundingBoxFilter)
->filteredBy($timeFilter, ARRAY_FILTER_USE_KEY)
->map([$distanceCalculator, 'setDistance'])
->offset(1)
->limit(1)
->do($display);
A Functional Guide to Cat Herding with PHP Generators
https://github.com/lstrojny/functional-php
A Functional Guide to Cat Herding with PHP Generators
No cats were forced to walk anywhere that they didn't want to go
during the writing of this presentation.
A Functional Guide to Cat Herding with PHP Generators
?
Questions
Who am I?
Mark Baker
Design and Development Manager
InnovEd (Innovative Solutions for Education) Ltd
Coordinator and Developer of:
Open Source PHPOffice library
PHPExcel, PHPWord, PHPPresentation (formerly PHPPowerPoint), PHPProject, PHPVisio
Minor contributor to PHP core
@Mark_Baker
https://github.com/MarkBaker
http://uk.linkedin.com/pub/mark-baker/b/572/171
http://markbakeruk.net

More Related Content

PDF
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
PPTX
A Functional Guide to Cat Herding with PHP Generators
PDF
Being functional in PHP (DPC 2016)
PDF
What's new in PHP 8.0?
PDF
Nikita Popov "What’s new in PHP 8.0?"
PDF
PHP Enums - PHPCon Japan 2021
PDF
PHP Performance Trivia
PDF
Typed Properties and more: What's coming in PHP 7.4?
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
A Functional Guide to Cat Herding with PHP Generators
Being functional in PHP (DPC 2016)
What's new in PHP 8.0?
Nikita Popov "What’s new in PHP 8.0?"
PHP Enums - PHPCon Japan 2021
PHP Performance Trivia
Typed Properties and more: What's coming in PHP 7.4?

What's hot (20)

PDF
Diving into HHVM Extensions (php[tek] 2016)
PPTX
Looping the Loop with SPL Iterators
PDF
SPL: The Missing Link in Development
PDF
Advanced symfony Techniques
PDF
PHP 8.1 - What's new and changed
PPTX
New in php 7
PDF
Forget about loops
PPTX
Creating own language made easy
PDF
関西PHP勉強会 php5.4つまみぐい
PDF
PHP 5.3 Overview
PDF
Doctrine MongoDB ODM (PDXPHP)
PPT
php 2 Function creating, calling, PHP built-in function
PPTX
Generated Power: PHP 5.5 Generators
PDF
"How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur...
PPTX
Zero to SOLID
PDF
Durian: a PHP 5.5 microframework with generator-style middleware
PDF
Opaque Pointers Are Coming
PDF
PHP Conference Asia 2016
PDF
Perl6 grammars
PDF
Introducing Assetic (NYPHP)
Diving into HHVM Extensions (php[tek] 2016)
Looping the Loop with SPL Iterators
SPL: The Missing Link in Development
Advanced symfony Techniques
PHP 8.1 - What's new and changed
New in php 7
Forget about loops
Creating own language made easy
関西PHP勉強会 php5.4つまみぐい
PHP 5.3 Overview
Doctrine MongoDB ODM (PDXPHP)
php 2 Function creating, calling, PHP built-in function
Generated Power: PHP 5.5 Generators
"How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur...
Zero to SOLID
Durian: a PHP 5.5 microframework with generator-style middleware
Opaque Pointers Are Coming
PHP Conference Asia 2016
Perl6 grammars
Introducing Assetic (NYPHP)
Ad

Viewers also liked (20)

PDF
Getting instantly up and running with Docker and Symfony
PPTX
Giving birth to an ElePHPant
PDF
php[world] 2015 Training - Laravel from the Ground Up
PDF
Zend Framework Foundations
PPTX
Engineer - Mastering the Art of Software
PDF
Amp your site an intro to accelerated mobile pages
PDF
Adding 1.21 Gigawatts to Applications with RabbitMQ (Bulgaria PHP 2016 - Tuto...
PDF
Hack the Future
PDF
Create, test, secure, repeat
PDF
Console Apps: php artisan forthe:win
PDF
Presentation Bulgaria PHP
PDF
Dip Your Toes in the Sea of Security
PDF
Git Empowered
PDF
Code Coverage for Total Security in Application Migrations
PPTX
Php extensions
PDF
SunshinePHP 2017 - Making the most out of MySQL
PDF
Conscious Coupling
PDF
Intermediate OOP in PHP
PDF
200K+ reasons security is a must
PDF
PHP World DC 2015 - What Can Go Wrong with Agile Development and How to Fix It
Getting instantly up and running with Docker and Symfony
Giving birth to an ElePHPant
php[world] 2015 Training - Laravel from the Ground Up
Zend Framework Foundations
Engineer - Mastering the Art of Software
Amp your site an intro to accelerated mobile pages
Adding 1.21 Gigawatts to Applications with RabbitMQ (Bulgaria PHP 2016 - Tuto...
Hack the Future
Create, test, secure, repeat
Console Apps: php artisan forthe:win
Presentation Bulgaria PHP
Dip Your Toes in the Sea of Security
Git Empowered
Code Coverage for Total Security in Application Migrations
Php extensions
SunshinePHP 2017 - Making the most out of MySQL
Conscious Coupling
Intermediate OOP in PHP
200K+ reasons security is a must
PHP World DC 2015 - What Can Go Wrong with Agile Development and How to Fix It
Ad

More from Mark Baker (20)

PPTX
Looping the Loop with SPL Iterators
PPTX
Looping the Loop with SPL Iterators
PPTX
Deploying Straight to Production
PPTX
Deploying Straight to Production
PPTX
Deploying Straight to Production
PPTX
A Brief History of Elephpants
PPTX
Aspects of love slideshare
PPTX
Does the SPL still have any relevance in the Brave New World of PHP7?
PPTX
A Brief History of ElePHPants
PPTX
Coding Horrors
PPTX
Anonymous classes2
PPTX
Testing the Untestable
PPTX
Anonymous Classes: Behind the Mask
PPTX
Does the SPL still have any relevance in the Brave New World of PHP7?
PPTX
Coding Horrors
PPTX
Does the SPL still have any relevance in the Brave New World of PHP7?
PPTX
SPL - The Undiscovered Library - PHPBarcelona 2015
PPTX
Zephir - A Wind of Change for writing PHP extensions
PPTX
Flying under the radar
PPTX
Php data structures – beyond spl (online version)
Looping the Loop with SPL Iterators
Looping the Loop with SPL Iterators
Deploying Straight to Production
Deploying Straight to Production
Deploying Straight to Production
A Brief History of Elephpants
Aspects of love slideshare
Does the SPL still have any relevance in the Brave New World of PHP7?
A Brief History of ElePHPants
Coding Horrors
Anonymous classes2
Testing the Untestable
Anonymous Classes: Behind the Mask
Does the SPL still have any relevance in the Brave New World of PHP7?
Coding Horrors
Does the SPL still have any relevance in the Brave New World of PHP7?
SPL - The Undiscovered Library - PHPBarcelona 2015
Zephir - A Wind of Change for writing PHP extensions
Flying under the radar
Php data structures – beyond spl (online version)

Recently uploaded (20)

PDF
Galatica Smart Energy Infrastructure Startup Pitch Deck
PPTX
Business Ppt On Nestle.pptx huunnnhhgfvu
PPTX
advance b rammar.pptxfdgdfgdfsgdfgsdgfdfgdfgsdfgdfgdfg
PPTX
Data_Analytics_and_PowerBI_Presentation.pptx
PDF
22.Patil - Early prediction of Alzheimer’s disease using convolutional neural...
PPTX
mbdjdhjjodule 5-1 rhfhhfjtjjhafbrhfnfbbfnb
PDF
Clinical guidelines as a resource for EBP(1).pdf
PPTX
Acceptance and paychological effects of mandatory extra coach I classes.pptx
PDF
Mega Projects Data Mega Projects Data
PPTX
Introduction to Basics of Ethical Hacking and Penetration Testing -Unit No. 1...
PPTX
Introduction to machine learning and Linear Models
PPTX
STUDY DESIGN details- Lt Col Maksud (21).pptx
PPTX
DISORDERS OF THE LIVER, GALLBLADDER AND PANCREASE (1).pptx
PPTX
MODULE 8 - DISASTER risk PREPAREDNESS.pptx
PDF
“Getting Started with Data Analytics Using R – Concepts, Tools & Case Studies”
PPTX
Computer network topology notes for revision
PPTX
climate analysis of Dhaka ,Banglades.pptx
PDF
Business Analytics and business intelligence.pdf
PPTX
ALIMENTARY AND BILIARY CONDITIONS 3-1.pptx
Galatica Smart Energy Infrastructure Startup Pitch Deck
Business Ppt On Nestle.pptx huunnnhhgfvu
advance b rammar.pptxfdgdfgdfsgdfgsdgfdfgdfgsdfgdfgdfg
Data_Analytics_and_PowerBI_Presentation.pptx
22.Patil - Early prediction of Alzheimer’s disease using convolutional neural...
mbdjdhjjodule 5-1 rhfhhfjtjjhafbrhfnfbbfnb
Clinical guidelines as a resource for EBP(1).pdf
Acceptance and paychological effects of mandatory extra coach I classes.pptx
Mega Projects Data Mega Projects Data
Introduction to Basics of Ethical Hacking and Penetration Testing -Unit No. 1...
Introduction to machine learning and Linear Models
STUDY DESIGN details- Lt Col Maksud (21).pptx
DISORDERS OF THE LIVER, GALLBLADDER AND PANCREASE (1).pptx
MODULE 8 - DISASTER risk PREPAREDNESS.pptx
“Getting Started with Data Analytics Using R – Concepts, Tools & Case Studies”
Computer network topology notes for revision
climate analysis of Dhaka ,Banglades.pptx
Business Analytics and business intelligence.pdf
ALIMENTARY AND BILIARY CONDITIONS 3-1.pptx

A Functional Guide to Cat Herding with PHP Generators

  • 1. A Functional Guide to Cat Herding with PHP Generators The Filter/Map/Reduce Pattern for PHP Generators
  • 2. A Functional Guide to Cat Herding with PHP Generators • Blog Post http://markbakeruk.net/2016/01/19/a-functional-guide-to-cat-herding-with- php-generators/ • Code Examples https://github.com/MarkBaker/GeneratorFunctionExamples
  • 3. A Functional Guide to Cat Herding with PHP Generators
  • 4. A Functional Guide to Cat Herding with PHP Generators
  • 5. A Functional Guide to Cat Herding with PHP Generators <?xml version="1.0" encoding="UTF-8" standalone="no" ?> <gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.topografix.com/GPX/1/1" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"> <trk> <name>Roman 2015-11-23</name> <trkseg> <trkpt lat="53.54398800" lon="-2.7403680000"> <ele>146.100</ele><time>2015-11-23T11:05:07Z</time> </trkpt> <trkpt lat="53.54401600" lon="-2.7402620000"> <ele>141.300</ele><time>2015-11-23T11:05:15Z</time> </trkpt> ... <trkpt lat="53.54384500" lon="-2.7426130000"> <ele>110.500</ele><time>2015-11-23T14:58:57Z</time> </trkpt> </trkseg> </trk> </gpx>
  • 6. A Functional Guide to Cat Herding with PHP Generators namespace GpxReader; class GpxHandler { protected $gpxReader; public function __construct($gpxFilename) { $this->gpxReader = new XMLReader(); $this->gpxReader->open($gpxFilename); } public function getElements($elementType) { while ($this->gpxReader->read()) { if ($this->gpxReader->nodeType == XMLREADER::ELEMENT && $this->gpxReader->name == $elementType) { $doc = new DOMDocument('1.0', 'UTF-8'); $xml = simplexml_import_dom($doc->importNode($this->gpxReader->expand(), true)); $gpxAttributes = $this->readAttributes($this->gpxReader); $gpxElement = $this->readChildren($xml); $gpxElement->position = $gpxAttributes; yield $gpxElement->timestamp => $gpxElement; } } } }
  • 7. A Functional Guide to Cat Herding with PHP Generators // Create our initial Generator to read the gpx file $gpxReader = new GpxReaderGpxHandler($gpxFilename); // Iterate over the trackpoint set from the gpx file, // displaying each point detail in turn foreach ($gpxReader->getElements('trkpt') as $time => $element) { printf( '%s' . PHP_EOL . ' latitude: %7.4f longitude: %7.4f elevation: %d' . PHP_EOL, $time->format('Y-m-d H:i:s'), $element->position->latitude, $element->position->longitude, $element->elevation ); }
  • 8. A Functional Guide to Cat Herding with PHP Generators 2015-11-23 11:05:07 latitude: 53.5440 longitude: -2.7404 elevation: 146 2015-11-23 11:05:15 latitude: 53.5440 longitude: -2.7403 elevation: 141 2015-11-23 11:05:25 latitude: 53.5440 longitude: -2.7402 elevation: 140 ... 2015-11-23 14:58:47 latitude: 53.5439 longitude: -2.7426 elevation: 103 2015-11-23 14:58:57 latitude: 53.5438 longitude: -2.7426 elevation: 110
  • 9. A Functional Guide to Cat Herding with PHP Generators
  • 10. Cat Herding with PHP Generators – Filter • A filter selects only a subset of values from the Traversable. • The rules for filtering are defined in a callback function. • If no callback is provided, then only non-empty values are returned.
  • 11. Cat Herding with PHP Generators – Filter array_filter() Filters elements of an array using a callback function. array array_filter ( array $array [, callable $callback] ) Iterates over each value in the array passing them to the callback function. If the callback function returns true, the current value from array is returned into the result array, otherwise it is discarded. Array keys are preserved.
  • 12. Cat Herding with PHP Generators – Filter function notEmpty($value) { return !empty($value); } /** * Version of filter to use with versions of PHP prior to 5.6.0, * without the `$flag` option * **/ function filter(Traversable $filter, Callable $callback = null) { if ($callback === null) { $callback = 'notEmpty'; } foreach ($filter as $key => $value) { if ($callback($value)) { yield $key => $value; } } }
  • 13. Cat Herding with PHP Generators – Filter array_filter() Filters elements of an array using a callback function. array array_filter ( array $array [, callable $callback] ) array array_filter ( array $array [, callable $callback [, int $flag = 0 ]] ) Iterates over each value in the array passing them to the callback function. If the callback function returns true, the current value from array is returned into the result array, otherwise it is discarded. Array keys are preserved. [PHP < 5.6.0] [PHP >= 5.6.0]
  • 14. Cat Herding with PHP Generators – Filter /** * The `$flag` option (and the constants ARRAY_FILTER_USE_KEY and ARRAY_FILTER_USE_BOTH) * were introduced in PHP 5.6.0 * **/ function filter(Traversable $filter, Callable $callback = null, $flag = 0) { if ($callback === null) { $callback = 'notEmpty'; } foreach ($filter as $key => $value) { switch($flag) { case ARRAY_FILTER_USE_KEY: ... case ARRAY_FILTER_USE_BOTH: ... default: ... } } }
  • 15. Cat Herding with PHP Generators – Filter • Time Range Where was Roman between 11:30 and 12:00? • Geo-Fencing (“Bounding Box”) • Inside Did Osiris go anywhere near the main road? • Outside Has Lexie left the house at all?
  • 16. Cat Herding with PHP Generators – Filter // Create our initial Generator to read the gpx file $gpxReader = new GpxReaderGpxHandler($gpxFilename); // Define the date/time filter parameters $startTime = new DateTime('2015-03-02 13:20:00Z'); $endTime = new DateTime('2015-03-02 13:30:00Z'); // Create the filter callback with the date/time parameters we've just defined $timeFilter = function($timestamp) use ($startTime, $endTime) { return $timestamp >= $startTime && $timestamp <= $endTime; };
  • 17. Cat Herding with PHP Generators – Filter // Iterate over the trackpoint set from the gpx file, // displaying each point detail in turn foreach (filter($gpxReader->getElements('trkpt'), $timeFilter, ARRAY_FILTER_USE_KEY) as $time => $element) { printf( '%s' . PHP_EOL . ' latitude: %7.4f longitude: %7.4f elevation: %d' . PHP_EOL, $time->format('Y-m-d H:i:s'), $element->position->latitude, $element->position->longitude, $element->elevation ); }
  • 18. Cat Herding with PHP Generators – Filter
  • 19. Cat Herding with PHP Generators – Filter namespace GpxReaderHelpers; class BoundingBox { /** * Identify whether a trackpoint falls inside the defined bounding box * * @param GpxReaderGpxElement The trackpoint * @return boolean If the trackpoint falls outside (false) * or inside (true) the bounding box **/ public function inside(GpxReaderGpxElement $point) { return (($point->position->longitude >= $this->left) && ($point->position->longitude <= $this->right) && ($point->position->latitude >= $this->bottom) && ($point->position->latitude <= $this->top)); } }
  • 20. Cat Herding with PHP Generators – Filter // Create our initial Generator to read the gpx file $gpxReader = new GpxReaderGpxHandler($gpxFilename); // Create a bounding box defining the coordinates we want to test each point against // This bounding box is for inside the house/garden $boundaries = new GpxReaderHelpersBoundingBox(); $boundaries->setLatitudes(53.54382, 53.54340); $boundaries->setLongitudes(-2.74059, -2.74005); // We want to set the filter to include only points inside the bounding box $boundingBoxFilter = [$boundaries, 'inside'];
  • 21. Cat Herding with PHP Generators – Filter // Iterate over the trackpoint set from the gpx file, // displaying each point detail in turn foreach (filter($gpxReader->getElements('trkpt'), $boundingBoxFilter) as $time => $element) { printf( '%s' . PHP_EOL . ' latitude: %7.4f longitude: %7.4f elevation: %d' . PHP_EOL, $time->format('Y-m-d H:i:s'), $element->position->latitude, $element->position->longitude, $element->elevation ); }
  • 22. Cat Herding with PHP Generators – Filter // Iterate over the trackpoint set from the gpx file, // displaying each point detail in turn // applying both a time filter (12:00:00-12:20:00 on 2015-11-23) // and a bounding box filter for inside the house/garden foreach (filter( filter( $gpxReader->getElements('trkpt'), $timeFilter, ARRAY_FILTER_USE_KEY ), $boundingBoxFilter ) as $time => $element) { printf( ... ); }
  • 23. Cat Herding with PHP Generators Osiris Located Achievement Unlocked
  • 24. Cat Herding with PHP Generators – Map • A map is like a foreach loop that transforms each value in the Traversable. • Each input value is transformed into a new output value. • The rules for the transformation are defined in a callback function.
  • 25. Cat Herding with PHP Generators – Map array_map() Applies the callback to the elements of the given arrays. array array_map ( callable $callback , array $array1 [, array $... ] ) array_map() returns an array containing all the elements of array1 after applying the callback function to each one. The number of parameters that the callback function accepts should match the number of arrays passed to the array_map().
  • 26. Cat Herding with PHP Generators – Map function map(Callable $callback, Traversable $iterator) { foreach ($iterator as $key => $value) { yield $key => $callback($value); } }
  • 27. Cat Herding with PHP Generators – Map namespace GpxReaderHelpers; class DistanceCalculator { public function setDistance(GpxReaderGpxElement $point) { $point->distance = $this->calculateDistance($point); return $point; } }
  • 28. Cat Herding with PHP Generators – Map // Create our initial Generator to read the gpx file $gpxReader = new GpxReaderGpxHandler($gpxFilename); // Set the mapper to calculate the distance between a trackpoint // and the previous trackpoint $distanceCalculator = new GpxReaderHelpersDistanceCalculator();
  • 29. Cat Herding with PHP Generators – Map // Iterate over the trackpoint set from the gpx file, mapping the distances as we go, // displaying each point detail in turn foreach (map([$distanceCalculator, 'setDistance'], $gpxReader->getElements('trkpt')) as $time => $element) { printf( '%s' . PHP_EOL . ' latitude: %7.4f longitude: %7.4f elevation: %d' . PHP_EOL . ' distance from previous point: %5.2f m' . PHP_EOL, $time->format('Y-m-d H:i:s'), $element->position->latitude, $element->position->longitude, $element->elevation, $element->distance ); }
  • 30. Cat Herding with PHP Generators – Map function mmap(Callable $callback, Traversable ...$iterators) { $mi = new MultipleIterator(MultipleIterator::MIT_NEED_ANY); foreach($iterators as $iterator) { $mi->attachIterator($iterator); } foreach($mi as $values) { yield $callback(...$values); } } http://nl3.php.net/manual/en/function.array-slice.php ... Splat Operator PHP >= 5.6.0 Argument Packing/Unpacking
  • 31. Cat Herding with PHP Generators Lexie Located Achievement Unlocked
  • 32. Cat Herding with PHP Generators – Reduce • A reduce aggregates all the values in the Traversable to a single value. • A callback function determines the process for the aggregation.
  • 33. Cat Herding with PHP Generators – Reduce array_reduce() Iteratively reduces the array to a single value using a callback function. mixed array_reduce ( array $array , callable $callback [, mixed $initial = NULL ] ) array_reduce() applies the callback function iteratively to the elements of the array, so as to reduce the array to a single value.
  • 34. Cat Herding with PHP Generators – Reduce function reduce(Traversable $iterator, Callable $callback, $initial = null) { $result = $initial; foreach($iterator as $value) { $result = $callback($result, $value); } return $result; }
  • 35. Cat Herding with PHP Generators – Reduce • Bounding Box What Coordinates should I use for the bounding box when displaying the track on a map? • Distance How far has Roman walked while he’s been out? What is the furthest distance that Osiris has travelled from home?
  • 36. Cat Herding with PHP Generators – Reduce // Iterate over our trackpoint set from the gpx file (mapping the distance as we go) // and reducing the results to calculate the total distance travelled $totalDistance = reduce( map([$distanceCalculator, 'setDistance'], $gpxReader->getElements('trkpt')), function($runningTotal, $value) { $runningTotal += $value->distance; return $runningTotal; }, 0.0 ); // Display the results of our reduce printf( 'Total distance travelled is %5.2f km' . PHP_EOL, $totalDistance / 1000 );
  • 37. Cat Herding with PHP Generators – Reduce Total distance travelled is 4.33 km
  • 38. Cat Herding with PHP Generators – Reduce namespace GpxReaderHelpers; class BoundingBox { function calculate($discard, GpxReaderGpxElement $point) { $this->top = max($point->position->latitude, $this->top); $this->bottom = min($point->position->latitude, $this->bottom); $this->left = min($point->position->longitude, $this->left); $this->right = max($point->position->longitude, $this->right); return $this; } }
  • 39. Cat Herding with PHP Generators – Reduce // Create our initial Generator to read the gpx file $gpxReader = new GpxReaderGpxHandler($gpxFilename); // Set our bounding box callback $boundaries = new GpxReaderHelpersBoundingBox(); // Reduce our trackpoint set from the gpx file against the bounding box callback $boundingBox = reduce( $gpxReader->getElements('trkpt'), [$boundaries, 'calculate'] ); // Display the results of our reduce printf( 'Top: %7.4f Bottom: %7.4f' . PHP_EOL . 'Left: %7.4f Right: %7.4f' . PHP_EOL, $boundingBox->top, $boundingBox->bottom, $boundingBox->left, $boundingBox->right );
  • 40. Cat Herding with PHP Generators – Reduce Top: 53.5445 Bottom: 53.5426 Left: -2.7433 Right: -2.7393
  • 41. Cat Herding with PHP Generators Roman Located Achievement Unlocked
  • 42. Cat Herding with PHP Generators iterator_apply() Call a function for every element in an iterator. int iterator_apply ( Traversable $iterator , callable $function [, array $args ] )
  • 43. Cat Herding with PHP Generators iterator_count() Count the elements in an iterator. int iterator_count ( Traversable $iterator )
  • 44. Cat Herding with PHP Generators iterator_to_array() Copy all values from the iterator into an array. array iterator_to_array ( Traversable $iterator [, bool $use_keys = true ] )
  • 45. Cat Herding with PHP Generators // Create an instance of the fluent Generator Helper and set our filters, // mapper offset and limits // and the display callback to "do" (or execute) // In this case, the "do" is a display callback, // but it could also be a "reduce" callback withGenerator($trackPoints) ->filteredBy($boundingBoxFilter) ->filteredBy($timeFilter, ARRAY_FILTER_USE_KEY) ->map([$distanceCalculator, 'setDistance']) ->offset(1) ->limit(1) ->do($display);
  • 46. A Functional Guide to Cat Herding with PHP Generators https://github.com/lstrojny/functional-php
  • 47. A Functional Guide to Cat Herding with PHP Generators No cats were forced to walk anywhere that they didn't want to go during the writing of this presentation.
  • 48. A Functional Guide to Cat Herding with PHP Generators ? Questions
  • 49. Who am I? Mark Baker Design and Development Manager InnovEd (Innovative Solutions for Education) Ltd Coordinator and Developer of: Open Source PHPOffice library PHPExcel, PHPWord, PHPPresentation (formerly PHPPowerPoint), PHPProject, PHPVisio Minor contributor to PHP core @Mark_Baker https://github.com/MarkBaker http://uk.linkedin.com/pub/mark-baker/b/572/171 http://markbakeruk.net