SlideShare a Scribd company logo
By: Sandy Smith (originally by Eli White) 
CEO & Founding Partner: 
musketeers.me 
Training Director: 
phparch.com 
! 
! 
@SandyS1 
– Oh My! 
Iterators, ArrayAccess & Countable
1st: The SPL (Standard PHP Library) 
A standard set of ! 
interfaces & classes for PHP5 
! 
Designed to solve standard problems 
and provide efficient data access. 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
2
SPL Features 
! 
SPL includes numerous types of features: 
- Data Structures (Linked Lists, Stacks, Queues, Heaps, …) 
- Iterators (w/ Filtering, Caching, Recursion, …) 
- Various standard objects (FileObject, ArrayObject, …) 
- Subject/Observer Interface 
- Exceptions 
- and more … 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
3
This talk … 
Will focus on a core set that are generically 
useful for all your data access objects. 
(and maybe a few others) 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
4 
! 
! 
Iterators, ArrayAccess, Countable 
!
Why? 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
5 
! 
Allows your user-space objects to be 
treated like native 1st class types.
Starting us off 
You have to start from somewhere … 
! 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
6
Features we want to duplicate 
All features built in to arrays 
! 
foreach iteration: 
foreach ($array as $key => $value) { 
echo "{$key}: {$value}n"; 
} 
! 
direct item access: 
echo $array[5]; 
! 
countability: 
echo count($array); 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
7
A Basic Class 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
8 
class Set 
{ 
protected $_set; 
public function __construct(Array $parameters = NULL) 
{ 
$this->_set = $this->_loadFromCache($parameters); 
if ($this->_set === NULL) { 
$this->_set = $this->_loadFromDatabase($parameters); 
} 
if ($this->_set === NULL) { 
$this->_set = []; 
} 
} 
protected function _loadFromCache(Array $parameters = NULL) 
{ 
// Pull data from cache, returning an array of arrays or objects 
} 
protected function _loadFromDatabase(Array $parameters = NULL) 
{ 
// Pull data from DB, returning an array of arrays or objects 
} 
}
But you need to access the data… 
So you need to implement some access method: 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
9 
class SetAccess extends Set 
{ 
public function getAll() 
{ 
return $this->_set; 
} 
public function get($index) 
{ 
if (array_key_exists($index, $this->_set)) { 
return $this->_set[$index]; 
} else { 
return NULL; 
} 
} 
} 
!
Inelegant solution 
Leaves you accessing data in these ways: 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
10 
! 
$myset = new SetAccess(); 
print_r($myset->get(3)); 
! 
$myset = new SetAccess(); 
$all = $myset->getAll(); 
foreach ($all as $item) { 
print_r($item); 
}
Iterators 
Natively use foreach on your objects 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
11
Iterator Interface 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
12 
interface Iterator extends Traversable { 
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 ) 
} 
! 
5 methods to define, revolve around remembering state: 
current(): Retur ns the current value 
key(): Returns the current value’s access key 
next(): Moves the inter nal pointer to the next item 
rewind(): Needs to reset the inter nal pointer to the first item 
valid(): Returns whether the internal pointer is at a valid data item
Easy to implement with Arrays 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
13 
class SetIteratable extends SetAccess implements Iterator 
{ 
public function current() { 
return current($this->_set); 
} 
public function key() { 
return key($this->_set); 
} 
public function next() { 
next($this->_set); 
} 
public function rewind() { 
reset($this->_set); 
} 
public function valid() { 
return (key($this->_set) !== NULL); 
} 
}
Now have direct access… 
Now we can access the object directly in a foreach loop! 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
14 
$myset = new SetIteratable(); 
foreach ($myset as $key => $item) { 
echo "{$key}: ", print_r($item, true), "<br/>n"; 
} 
!
ArrayAccess 
Treat your object like it was an array. 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
15
ArrayAccess Interface 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
16 
interface ArrayAccess { 
abstract public boolean offsetExists ( mixed $offset ) 
abstract public mixed offsetGet ( mixed $offset ) 
abstract public void offsetSet ( mixed $offset , mixed $value ) 
abstract public void offsetUnset ( mixed $offset ) 
} 
! 
4 methods to define, to gain direct key access: 
offsetExists(): Does the provided key exist? 
offsetGet(): Retur n the value at provided key 
offsetSet(): Set the value at the provided key 
offsetUnset(): Remove the value (and key) provided
Again easy to code with builtins … 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
17 
class SetArray extends SetIteratable implements ArrayAccess 
{ 
public function offsetExists($offset) 
{ 
return array_key_exists($offset, $this->_set); 
} 
public function offsetGet($offset) 
{ 
return $this->_set[$offset]; 
} 
public function offsetSet($offset, $value) 
{ 
if (is_null($offset)) { 
$this->_set[] = $value; 
} else { 
$this->_set[$offset] = $value; 
} 
} 
public function offsetUnset($offset) 
{ 
unset($this->_set[$offset]); 
} 
}
Treat it like an array… 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
18 
! 
You can now directly treat the object like an array: 
$myset = new SetArray(); 
print_r($myset[3]); 
if (isset($myset['Sandy'])) { 
echo “Smith"; 
} 
$myset['Eli'] = 'White'; 
echo '<p>', $myset['Eli'], '</p>'; 
unset($myset['Eli']); 
$myset[] = [2013, 2014, 2015]; 
$myset[] = 'php[tek] 2015'; 
! 
NOTE: 
You don’t have to implement 
everything. Create blank 
offsetSet() and offsetUnset() if 
you don’t want to allow 
modification!
Countable 
And while we are at it … 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
19
Countable Interface 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
20 
! 
Just one method: 
count(): How many items in this object? 
class SetCountable extends SetArray implements Countable 
{ 
public function count() 
{ 
return count($this->_set); 
} 
} 
$myset = new SetCountable(); 
echo count($myset);
Return whatever you want though… 
Like all these, what you return is up to you! 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
21 
! 
class SetCountable extends SetArray implements Countable 
{ 
public function count() 
{ 
return count($this->_set, COUNT_RECURSIVE); 
} 
} 
$myset = new SetCountable(); 
echo count($myset);
Serializable 
Another bit of magic… 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
22
Serializable Interface 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
23 
! 
2 methods to let you custom define serialization: 
serialize(): Returns a serialized form of your object 
unserialize(): Instantiates an object, given the serialized form 
interface Serializable { 
abstract public string serialize ( void ) 
abstract public void unserialize ( string $serialized ) 
}
A simple example, just saving data 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
24 
class SetSerial extends SetArray implements Serializable 
{ 
public function serialize() 
{ 
return serialize($this->_set); 
} 
public function unserialize($serialized) 
{ 
$this->_set = unserialize($serialized); 
} 
} 
! 
Simple, and serialization works as normal! 
$myset = new SetSerial(); 
$myset['magazine'] = ‘php[architect]’; 
$save = serialize($myset); 
$restore = unserialize($save); 
echo $restore['magazine'];
But you can return whatever… 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
25 
! 
Only save what data you want. 
Encode in whatever format you want: 
class SetSerialFunky extends SetArray implements Serializable 
{ 
public function serialize() 
{ 
$copy = array_filter($this->_set, function ($val) { return !is_array($val); }); 
return json_encode($copy); 
} 
public function unserialize($serialized) 
{ 
$this->_set = json_decode($serialized, TRUE); 
} 
}
Putting it all together 
So what does this look like… 
! 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
26
Put it all together and what do we get? 
class SetFull implements Iterator, ArrayAccess, Countable, Serializable 
{ 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
27 
// Iterator: 
public function current() { return current($this->_set); } 
public function key() { return key($this->_set); } 
public function next() { next($this->_set); } 
public function rewind() { reset($this->_set); } 
public function valid() { return (key($this->_set) !== NULL); } 
// ArrayAccess: 
public function offsetExists($key) { return array_key_exists($key, $this->_set); } 
public function offsetGet($key) { return $this->_set[$key]; } 
public function offsetUnset($key) { unset($this->_set[$key]); } 
public function offsetSet($key, $value) { 
if (is_null($key)) { $this->_set[] = $value; } 
else { $this->_set[$key] = $value; } 
} 
// Countable: 
public function count() { return count($this->_set); } 
// Serializable 
public function serialize() { return serialize($this->_set); } 
public function unserialize($data) { $this->_set = unserialize($data); } 
}
Get creative! 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
28 
! 
This only scrapes the surface of what is possible! 
! 
None of the methods need to 
retur n ‘basic’ information like this. 
! 
Get as creative as needed for your situation!
Bonus Round! 
Let’s look at some magic methods… 
! 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
29
Magic methods have come a long way… 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
30 
! 
Not just your __get & __set anymore! 
! 
Let’s look at some PHP5 magic methods 
that are useful to data access classes!
__toString() 
Been around a while, but recently become universal 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
31 
! 
class SetString extends SetSerial 
{ 
public function __toString() 
{ 
return "Set: " . print_r($this->_set, TRUE); 
} 
} 
! 
$myset = new SetString(); 
echo $myset;
__set_state() 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
32 
! 
Called statically by var_export() on your object: 
IE: var_export retur ns: SetState::__set_state($data); 
class SetState extends SetString 
{ 
public static function __set_state(Array $array) 
{ 
$obj = new self(); 
$obj->_set = $array['_set']; 
return $obj; 
} 
} 
$myset = new SetState(); 
$export = var_export($myset, TRUE); 
eval('$newset = '. $export. ';'); 
echo $newset;
__callStatic() 
__call() has been around for a while to dynamic method calls. 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
33 
! 
__callStatic() now allows the same feature on static methods. 
class SetCall extends SetState { 
public function __call($name, $args) { 
if ($name == 'flip') { 
return array_reverse($this->_set); 
} 
} 
public function __callStatic($name, $args) { 
if ($name == 'factory') { 
return new self(); 
} 
} 
} 
$myset = SetCall::factory(); 
$reversed = $myset->flip(); 
var_dump($reversed);
__invoke() 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
34 
! 
Blow your mind: 
Allows your object to be called as a function! 
class SetInvoke extends SetCall 
{ 
public function __invoke($start, $length) 
{ 
return array_slice($this->_set, $start, $length, TRUE); 
} 
} 
$myset = new SetInvoke(); 
$slice = $myset(1,3); 
var_dump($slice); 
! 
Can do anything with this!
More Iterator Fun! 
If we have time, let’s play! 
! 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
35
InfiniteIterator 
Causes an iterator to automatically rewind: 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
36 
! 
$forever = new InfiniteIterator(new SetFull()); 
$count = 100; 
foreach ($forever as $item) { 
print_r($item); 
if (!($count--)) break; 
}
LimitIterator 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
37 
! 
Allows you to set a start index & max iterations: 
foreach (new LimitIterator(new SetFull(), 0, 3) as $item) { 
print_r($item); 
} 
$forever = new InfiniteIterator(new SetFull()); 
foreach (new LimitIterator($forever, 0, 100) as $item) { 
print_r($item); 
}
FilterIterator 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
38 
! 
Apply your own filtering to what items are returned 
class ArrayFilter extends FilterIterator 
{ 
public function accept() 
{ 
return is_array($this->getInnerIterator()->current()); 
} 
} 
foreach (new ArrayFilter(new SetFull()) as $item) { 
print_r($item); 
}
RegexIterator 
Predefined instance of FilterIterator with regex 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
39 
! 
$regex = new RegexIterator(new SetFull(), '/^tek[0-9]+/', RegexIterator::MATCH); 
foreach ($regex as $item) { 
print_r($item); 
} ! 
Lots of options/flags: 
RegexIterator::MATCH 
RegexIterator::GET_MATCH 
RegexIterator::ALL_MATCHES 
RegexIterator::SPLIT 
RegexIterator::REPLACE 
RegexIterator::USE_KEY
MultipleIterator 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
40 
! 
Allows iterating over multiple iterators at once 
$multiple = new MultipleIterator(); 
$multiple->attachIterator(new SetFull()); 
$multiple->attachIterator(new SetFull(['other','parameters'])); 
foreach ($multiple as $both) { 
$setOne = print_r($both[0], TRUE); 
$setTwo = print_r($both[1], TRUE); 
echo "One: {$setOne} | Two: {$setTwo} <br/>n"; 
} 
! 
Stops whenever any one runs out of items
RecursiveIterator & RecursiveIteratorIterator 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
41 
class SetRecursable extends SetFull implements RecursiveIterator 
{ 
public function hasChildren() 
{ 
return is_array(current($this->_set)); 
} 
public function getChildren() { 
return new RecursiveArrayIterator(current($this->_set)); 
} 
} 
foreach (new RecursiveIteratorIterator(new SetRecursable()) as $item) { 
echo " {$item} "; 
} 
! 
2 methods to you define to allow recursion: 
hasChildren(): Does the current item have any children? 
getChildren(): If so, return a RecursiveIterator to iterate them.
And so much more… 
! 
ArrayIterator ! 
NoRewindIterator 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
42 
! 
SeekableIterator 
! 
ParentIterator 
! 
AppendIterator 
CachingIterator 
! 
CallbackFilterIterator 
! 
DirectoryIterator 
! 
EmptyIterator 
! 
FilesystemIterator 
! 
GlobIterator 
! 
! 
RecursiveCachingIterator 
! 
RecursiveFilterIterator ! 
RecursiveDirectoryIterator 
! 
RecursiveCallbackFilterIterator 
! 
RecursiveRegexIterator 
! 
RecursiveTreeIterator
Brief Commercial Interruption… 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
43
Get a discount to php[world]! 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
44
Win an ElePHPant! 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
45 
Drop your card/name & email in the shoebox at our table
Questions? 
Twitter: @SandyS1, @phparch 
php[architect]: http://phparch.com/ 
musketeers: http://musketeers.me/ 
Rate me: https://joind.in/11744 
! 
! 
! 
! 
! 
Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 
46

More Related Content

PPTX
PHP Functions & Arrays
PDF
PHP Unit 4 arrays
PDF
Arrays in PHP
PPT
Class 4 - PHP Arrays
PDF
Sorting arrays in PHP
PDF
Php array
PPTX
Chap 3php array part1
PPT
PHP Functions & Arrays
PHP Unit 4 arrays
Arrays in PHP
Class 4 - PHP Arrays
Sorting arrays in PHP
Php array
Chap 3php array part1

What's hot (19)

PPT
Php Using Arrays
PPTX
PHP array 1
PDF
4.1 PHP Arrays
PDF
PHP for Python Developers
PDF
PhpUnit - The most unknown Parts
ODP
Writing Maintainable Perl
PPTX
07 php
KEY
Spl Not A Bridge Too Far phpNW09
PPT
Php array
PPT
Arrays in php
PDF
Static Optimization of PHP bytecode (PHPSC 2017)
PDF
WordCamp Portland 2018: PHP for WordPress
PDF
Your code sucks, let's fix it
DOCX
PERL for QA - Important Commands and applications
PDF
Improving Dev Assistant
PDF
Difference between mysql_fetch_array and mysql_fetch_assoc in PHP
PPTX
Chap 3php array part 3
PDF
PHP Performance Trivia
Php Using Arrays
PHP array 1
4.1 PHP Arrays
PHP for Python Developers
PhpUnit - The most unknown Parts
Writing Maintainable Perl
07 php
Spl Not A Bridge Too Far phpNW09
Php array
Arrays in php
Static Optimization of PHP bytecode (PHPSC 2017)
WordCamp Portland 2018: PHP for WordPress
Your code sucks, let's fix it
PERL for QA - Important Commands and applications
Improving Dev Assistant
Difference between mysql_fetch_array and mysql_fetch_assoc in PHP
Chap 3php array part 3
PHP Performance Trivia
Ad

Viewers also liked (20)

ODP
Hyperlocalisation or "localising everything"
PDF
Architecting with Queues for Scale, Speed, and Separation (DCPHP 3/11/15)
PDF
Unicode Regular Expressions
PDF
Regular expressions
PDF
Don't Fear the Regex - CapitalCamp/GovDays 2014
ODP
Multibyte string handling in PHP
PDF
Don't Fear the Regex LSP15
KEY
Lessons from a Dying CMS
PDF
GAIQ - Regular expressions-google-analytics
PDF
Grokking regex
PPT
TDA Center Depok update 2014 (Concept)
KEY
Regular expressions
PPTX
Regular expressions
ODP
Regular Expressions: Backtracking, and The Little Engine that Could(n't)?
PPT
Working with Databases and MySQL
PDF
Architecting with Queues - Northeast PHP 2015
PPT
How to report a bug
PDF
EDUPUB 2013: Schema.org LRMI and A11Y for Discovery
Hyperlocalisation or "localising everything"
Architecting with Queues for Scale, Speed, and Separation (DCPHP 3/11/15)
Unicode Regular Expressions
Regular expressions
Don't Fear the Regex - CapitalCamp/GovDays 2014
Multibyte string handling in PHP
Don't Fear the Regex LSP15
Lessons from a Dying CMS
GAIQ - Regular expressions-google-analytics
Grokking regex
TDA Center Depok update 2014 (Concept)
Regular expressions
Regular expressions
Regular Expressions: Backtracking, and The Little Engine that Could(n't)?
Working with Databases and MySQL
Architecting with Queues - Northeast PHP 2015
How to report a bug
EDUPUB 2013: Schema.org LRMI and A11Y for Discovery
Ad

Similar to Iterators, ArrayAccess & Countable (Oh My!) - Madison PHP 2014 (20)

PDF
PHP Belfast | Collection Classes
PDF
Advanced Php - Macq Electronique 2010
ODP
Intro to The PHP SPL
PDF
Using spl tools in your code
PDF
SPL: The Missing Link in Development
PDF
Typed Properties and more: What's coming in PHP 7.4?
PDF
Banishing Loops with Functional Programming in PHP
PDF
Spl in the wild
PDF
Decoupling Objects With Standard Interfaces
PDF
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
PPTX
FFW Gabrovo PMG - PHP OOP Part 3
PPTX
Arrays in PHP
PPT
PHP - Introduction to PHP Arrays
PPTX
Spl to the Rescue - Zendcon 09
KEY
Intermediate PHP
PPTX
Spl in the wild - zendcon2012
PPTX
OOP in PHP.pptx
PDF
PHP 7 – What changed internally? (Forum PHP 2015)
PDF
Overview changes in PHP 5.4
PPTX
PHP in 2018 - Q1 - AFUP Limoges
PHP Belfast | Collection Classes
Advanced Php - Macq Electronique 2010
Intro to The PHP SPL
Using spl tools in your code
SPL: The Missing Link in Development
Typed Properties and more: What's coming in PHP 7.4?
Banishing Loops with Functional Programming in PHP
Spl in the wild
Decoupling Objects With Standard Interfaces
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
FFW Gabrovo PMG - PHP OOP Part 3
Arrays in PHP
PHP - Introduction to PHP Arrays
Spl to the Rescue - Zendcon 09
Intermediate PHP
Spl in the wild - zendcon2012
OOP in PHP.pptx
PHP 7 – What changed internally? (Forum PHP 2015)
Overview changes in PHP 5.4
PHP in 2018 - Q1 - AFUP Limoges

Recently uploaded (20)

PPTX
L1 - Introduction to python Backend.pptx
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PDF
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
PDF
System and Network Administraation Chapter 3
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PDF
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
PPTX
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
PPTX
history of c programming in notes for students .pptx
PPT
Introduction Database Management System for Course Database
PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
PPTX
Introduction to Artificial Intelligence
PPTX
CHAPTER 2 - PM Management and IT Context
PDF
AI in Product Development-omnex systems
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PDF
Softaken Excel to vCard Converter Software.pdf
PDF
medical staffing services at VALiNTRY
PDF
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
PDF
PTS Company Brochure 2025 (1).pdf.......
PDF
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
L1 - Introduction to python Backend.pptx
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
System and Network Administraation Chapter 3
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
Upgrade and Innovation Strategies for SAP ERP Customers
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
history of c programming in notes for students .pptx
Introduction Database Management System for Course Database
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
Introduction to Artificial Intelligence
CHAPTER 2 - PM Management and IT Context
AI in Product Development-omnex systems
Design an Analysis of Algorithms I-SECS-1021-03
Softaken Excel to vCard Converter Software.pdf
medical staffing services at VALiNTRY
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
PTS Company Brochure 2025 (1).pdf.......
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)

Iterators, ArrayAccess & Countable (Oh My!) - Madison PHP 2014

  • 1. By: Sandy Smith (originally by Eli White) CEO & Founding Partner: musketeers.me Training Director: phparch.com ! ! @SandyS1 – Oh My! Iterators, ArrayAccess & Countable
  • 2. 1st: The SPL (Standard PHP Library) A standard set of ! interfaces & classes for PHP5 ! Designed to solve standard problems and provide efficient data access. Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 2
  • 3. SPL Features ! SPL includes numerous types of features: - Data Structures (Linked Lists, Stacks, Queues, Heaps, …) - Iterators (w/ Filtering, Caching, Recursion, …) - Various standard objects (FileObject, ArrayObject, …) - Subject/Observer Interface - Exceptions - and more … Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 3
  • 4. This talk … Will focus on a core set that are generically useful for all your data access objects. (and maybe a few others) Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 4 ! ! Iterators, ArrayAccess, Countable !
  • 5. Why? Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 5 ! Allows your user-space objects to be treated like native 1st class types.
  • 6. Starting us off You have to start from somewhere … ! Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 6
  • 7. Features we want to duplicate All features built in to arrays ! foreach iteration: foreach ($array as $key => $value) { echo "{$key}: {$value}n"; } ! direct item access: echo $array[5]; ! countability: echo count($array); Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 7
  • 8. A Basic Class Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 8 class Set { protected $_set; public function __construct(Array $parameters = NULL) { $this->_set = $this->_loadFromCache($parameters); if ($this->_set === NULL) { $this->_set = $this->_loadFromDatabase($parameters); } if ($this->_set === NULL) { $this->_set = []; } } protected function _loadFromCache(Array $parameters = NULL) { // Pull data from cache, returning an array of arrays or objects } protected function _loadFromDatabase(Array $parameters = NULL) { // Pull data from DB, returning an array of arrays or objects } }
  • 9. But you need to access the data… So you need to implement some access method: Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 9 class SetAccess extends Set { public function getAll() { return $this->_set; } public function get($index) { if (array_key_exists($index, $this->_set)) { return $this->_set[$index]; } else { return NULL; } } } !
  • 10. Inelegant solution Leaves you accessing data in these ways: Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 10 ! $myset = new SetAccess(); print_r($myset->get(3)); ! $myset = new SetAccess(); $all = $myset->getAll(); foreach ($all as $item) { print_r($item); }
  • 11. Iterators Natively use foreach on your objects Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 11
  • 12. Iterator Interface Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 12 interface Iterator extends Traversable { 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 ) } ! 5 methods to define, revolve around remembering state: current(): Retur ns the current value key(): Returns the current value’s access key next(): Moves the inter nal pointer to the next item rewind(): Needs to reset the inter nal pointer to the first item valid(): Returns whether the internal pointer is at a valid data item
  • 13. Easy to implement with Arrays Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 13 class SetIteratable extends SetAccess implements Iterator { public function current() { return current($this->_set); } public function key() { return key($this->_set); } public function next() { next($this->_set); } public function rewind() { reset($this->_set); } public function valid() { return (key($this->_set) !== NULL); } }
  • 14. Now have direct access… Now we can access the object directly in a foreach loop! Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 14 $myset = new SetIteratable(); foreach ($myset as $key => $item) { echo "{$key}: ", print_r($item, true), "<br/>n"; } !
  • 15. ArrayAccess Treat your object like it was an array. Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 15
  • 16. ArrayAccess Interface Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 16 interface ArrayAccess { abstract public boolean offsetExists ( mixed $offset ) abstract public mixed offsetGet ( mixed $offset ) abstract public void offsetSet ( mixed $offset , mixed $value ) abstract public void offsetUnset ( mixed $offset ) } ! 4 methods to define, to gain direct key access: offsetExists(): Does the provided key exist? offsetGet(): Retur n the value at provided key offsetSet(): Set the value at the provided key offsetUnset(): Remove the value (and key) provided
  • 17. Again easy to code with builtins … Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 17 class SetArray extends SetIteratable implements ArrayAccess { public function offsetExists($offset) { return array_key_exists($offset, $this->_set); } public function offsetGet($offset) { return $this->_set[$offset]; } public function offsetSet($offset, $value) { if (is_null($offset)) { $this->_set[] = $value; } else { $this->_set[$offset] = $value; } } public function offsetUnset($offset) { unset($this->_set[$offset]); } }
  • 18. Treat it like an array… Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 18 ! You can now directly treat the object like an array: $myset = new SetArray(); print_r($myset[3]); if (isset($myset['Sandy'])) { echo “Smith"; } $myset['Eli'] = 'White'; echo '<p>', $myset['Eli'], '</p>'; unset($myset['Eli']); $myset[] = [2013, 2014, 2015]; $myset[] = 'php[tek] 2015'; ! NOTE: You don’t have to implement everything. Create blank offsetSet() and offsetUnset() if you don’t want to allow modification!
  • 19. Countable And while we are at it … Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 19
  • 20. Countable Interface Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 20 ! Just one method: count(): How many items in this object? class SetCountable extends SetArray implements Countable { public function count() { return count($this->_set); } } $myset = new SetCountable(); echo count($myset);
  • 21. Return whatever you want though… Like all these, what you return is up to you! Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 21 ! class SetCountable extends SetArray implements Countable { public function count() { return count($this->_set, COUNT_RECURSIVE); } } $myset = new SetCountable(); echo count($myset);
  • 22. Serializable Another bit of magic… Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 22
  • 23. Serializable Interface Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 23 ! 2 methods to let you custom define serialization: serialize(): Returns a serialized form of your object unserialize(): Instantiates an object, given the serialized form interface Serializable { abstract public string serialize ( void ) abstract public void unserialize ( string $serialized ) }
  • 24. A simple example, just saving data Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 24 class SetSerial extends SetArray implements Serializable { public function serialize() { return serialize($this->_set); } public function unserialize($serialized) { $this->_set = unserialize($serialized); } } ! Simple, and serialization works as normal! $myset = new SetSerial(); $myset['magazine'] = ‘php[architect]’; $save = serialize($myset); $restore = unserialize($save); echo $restore['magazine'];
  • 25. But you can return whatever… Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 25 ! Only save what data you want. Encode in whatever format you want: class SetSerialFunky extends SetArray implements Serializable { public function serialize() { $copy = array_filter($this->_set, function ($val) { return !is_array($val); }); return json_encode($copy); } public function unserialize($serialized) { $this->_set = json_decode($serialized, TRUE); } }
  • 26. Putting it all together So what does this look like… ! Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 26
  • 27. Put it all together and what do we get? class SetFull implements Iterator, ArrayAccess, Countable, Serializable { Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 27 // Iterator: public function current() { return current($this->_set); } public function key() { return key($this->_set); } public function next() { next($this->_set); } public function rewind() { reset($this->_set); } public function valid() { return (key($this->_set) !== NULL); } // ArrayAccess: public function offsetExists($key) { return array_key_exists($key, $this->_set); } public function offsetGet($key) { return $this->_set[$key]; } public function offsetUnset($key) { unset($this->_set[$key]); } public function offsetSet($key, $value) { if (is_null($key)) { $this->_set[] = $value; } else { $this->_set[$key] = $value; } } // Countable: public function count() { return count($this->_set); } // Serializable public function serialize() { return serialize($this->_set); } public function unserialize($data) { $this->_set = unserialize($data); } }
  • 28. Get creative! Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 28 ! This only scrapes the surface of what is possible! ! None of the methods need to retur n ‘basic’ information like this. ! Get as creative as needed for your situation!
  • 29. Bonus Round! Let’s look at some magic methods… ! Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 29
  • 30. Magic methods have come a long way… Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 30 ! Not just your __get & __set anymore! ! Let’s look at some PHP5 magic methods that are useful to data access classes!
  • 31. __toString() Been around a while, but recently become universal Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 31 ! class SetString extends SetSerial { public function __toString() { return "Set: " . print_r($this->_set, TRUE); } } ! $myset = new SetString(); echo $myset;
  • 32. __set_state() Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 32 ! Called statically by var_export() on your object: IE: var_export retur ns: SetState::__set_state($data); class SetState extends SetString { public static function __set_state(Array $array) { $obj = new self(); $obj->_set = $array['_set']; return $obj; } } $myset = new SetState(); $export = var_export($myset, TRUE); eval('$newset = '. $export. ';'); echo $newset;
  • 33. __callStatic() __call() has been around for a while to dynamic method calls. Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 33 ! __callStatic() now allows the same feature on static methods. class SetCall extends SetState { public function __call($name, $args) { if ($name == 'flip') { return array_reverse($this->_set); } } public function __callStatic($name, $args) { if ($name == 'factory') { return new self(); } } } $myset = SetCall::factory(); $reversed = $myset->flip(); var_dump($reversed);
  • 34. __invoke() Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 34 ! Blow your mind: Allows your object to be called as a function! class SetInvoke extends SetCall { public function __invoke($start, $length) { return array_slice($this->_set, $start, $length, TRUE); } } $myset = new SetInvoke(); $slice = $myset(1,3); var_dump($slice); ! Can do anything with this!
  • 35. More Iterator Fun! If we have time, let’s play! ! Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 35
  • 36. InfiniteIterator Causes an iterator to automatically rewind: Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 36 ! $forever = new InfiniteIterator(new SetFull()); $count = 100; foreach ($forever as $item) { print_r($item); if (!($count--)) break; }
  • 37. LimitIterator Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 37 ! Allows you to set a start index & max iterations: foreach (new LimitIterator(new SetFull(), 0, 3) as $item) { print_r($item); } $forever = new InfiniteIterator(new SetFull()); foreach (new LimitIterator($forever, 0, 100) as $item) { print_r($item); }
  • 38. FilterIterator Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 38 ! Apply your own filtering to what items are returned class ArrayFilter extends FilterIterator { public function accept() { return is_array($this->getInnerIterator()->current()); } } foreach (new ArrayFilter(new SetFull()) as $item) { print_r($item); }
  • 39. RegexIterator Predefined instance of FilterIterator with regex Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 39 ! $regex = new RegexIterator(new SetFull(), '/^tek[0-9]+/', RegexIterator::MATCH); foreach ($regex as $item) { print_r($item); } ! Lots of options/flags: RegexIterator::MATCH RegexIterator::GET_MATCH RegexIterator::ALL_MATCHES RegexIterator::SPLIT RegexIterator::REPLACE RegexIterator::USE_KEY
  • 40. MultipleIterator Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 40 ! Allows iterating over multiple iterators at once $multiple = new MultipleIterator(); $multiple->attachIterator(new SetFull()); $multiple->attachIterator(new SetFull(['other','parameters'])); foreach ($multiple as $both) { $setOne = print_r($both[0], TRUE); $setTwo = print_r($both[1], TRUE); echo "One: {$setOne} | Two: {$setTwo} <br/>n"; } ! Stops whenever any one runs out of items
  • 41. RecursiveIterator & RecursiveIteratorIterator Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 41 class SetRecursable extends SetFull implements RecursiveIterator { public function hasChildren() { return is_array(current($this->_set)); } public function getChildren() { return new RecursiveArrayIterator(current($this->_set)); } } foreach (new RecursiveIteratorIterator(new SetRecursable()) as $item) { echo " {$item} "; } ! 2 methods to you define to allow recursion: hasChildren(): Does the current item have any children? getChildren(): If so, return a RecursiveIterator to iterate them.
  • 42. And so much more… ! ArrayIterator ! NoRewindIterator Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 42 ! SeekableIterator ! ParentIterator ! AppendIterator CachingIterator ! CallbackFilterIterator ! DirectoryIterator ! EmptyIterator ! FilesystemIterator ! GlobIterator ! ! RecursiveCachingIterator ! RecursiveFilterIterator ! RecursiveDirectoryIterator ! RecursiveCallbackFilterIterator ! RecursiveRegexIterator ! RecursiveTreeIterator
  • 43. Brief Commercial Interruption… Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 43
  • 44. Get a discount to php[world]! Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 44
  • 45. Win an ElePHPant! Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 45 Drop your card/name & email in the shoebox at our table
  • 46. Questions? Twitter: @SandyS1, @phparch php[architect]: http://phparch.com/ musketeers: http://musketeers.me/ Rate me: https://joind.in/11744 ! ! ! ! ! Iterators, ArrayAccess & Countable, Oh My! - Sandy Smith - Madison PHP - September 13, 2014 46