An introduction to
in PHP
By @JeroenDeDauw
www.EntropyWins.wtf
Use "page down" and "page up" to navigate
function doStuff(array $things) {
foreach ($things as $thing) {
/* ... */
}
}
function doStuff(Iterator $things) {
foreach ($things as $thing) {
/* ... */
}
}
function findFileWithNyanCat(string $path): ?string {
foreach (glob($path . '*.txt') as $file) {
$fileContent = file_get_contents($file);
if (in_string('~=[,,_,,]:3', $fileContent)) {
return $fileContent;
}
}
return null;
}
function getContentsOfTextFiles($path): array {
// glob and file_get_contents
}
function findTextWithNyanCat(array $texts): ?string {
foreach ($texts as $text) {
if (in_string('~=[,,_,,]:3', $text)) {
return $text;
}
}
return null;
}
findTextWithNyanCat(getContentsOfTextFiles($path));
class TextFileIterator implements Iterator {
/* ... */
public function current() {
// return file_get_contents
}
/* ... */
}
function findTextWithNyanCat(Iterator $texts): ?string {
foreach ($texts as $text) {
if (in_string('~=[,,_,,]:3', $text)) { /*...*/ }
}
return null;
}
findTextWithNyanCat(new TextFileIterator($path));
findTextWithNyanCat(new DatabaseIterator(/*...*/));
findTextWithNyanCat(new ArrayIterator(['test text', '~=[,,_,,]:3']));
function newNyanGenerator(): Generator {
yield '~=[,,_,,]:3';
yield 'Nyan!';
}
$generator = newNyanGenerator();
foreach ($generator as $text) {
echo $text . ' ';
}
// ~=[,,_,,]:3 Nyan!
IteratorAggregate + Generator = <3
function newNyanGenerator(): Generator {
yield '~=[,,_,,]:3';
yield 'Nyan!';
}
$generator = newNyanGenerator();
foreach ($generator as $text) {
echo $text;
}
foreach ($generator as $text) {
echo $text; // BOOM!
}
interface IteratorAggregate extends Traversable {
public function getIterator(): Traversable;
}
class NyanNyan implements IteratorAggregate {
public function getIterator(): Traversable {
yield '~=[,,_,,]:3';
yield 'Nyan!';
}
}
$traversable = new NyanNyan();
foreach ($traversable as $text) {
echo $text;
}
foreach ($traversable as $text) {
echo $text; // works fine
}
private function getMailTemplatesOnDisk(array $mailTemplatePaths): array {
$mailTemplatesOnDisk = [];
foreach ($mailTemplatePaths as $path) {
$mailFilesInFolder = glob($path . '/Mail_*');
array_walk($mailFilesInFolder, function(&$filename) {
$filename = basename($filename);
});
$mailTemplatesOnDisk = array_merge($mailTemplatesOnDisk, $mailFilesInFolder);
}
return $mailTemplatesOnDisk;
}
class MailTemplateFilenameTraversable implements \IteratorAggregate {
public function __construct(array $mailTemplatePaths) {
$this->mailTemplatePaths = $mailTemplatePaths;
}
public function getIterator() {
foreach ($this->mailTemplatePaths as $path) {
foreach (glob( $path . '/Mail_*') as $fileName) {
yield basename($fileName);
}
}
}
}
Generators also can...
yield "Iterators" => "are useful";
yield "Generators" => "are awesome";
// ["Iterators" => "are useful",
// "Generators" => "are awesome"]
yield from [1, 2, 3];
yield from new ArrayIterator([4, 5]);
// 1, 2, 3, 4, 5
// Flattens iterable[] into Generator
foreach ($collections as $collection) {
yield from $collection;
}
class SeriousBiznessTest extends PHPUnitSomething {
public function testContainsNyan(string $text) {
$this->assertContains('~=[,,_,,]:3', $text);
}
public function nyanTextProvider(): array {
return [
[ 'Foo ~=[,,_,,]:3' ],
[ 'Bar ~=[,,_,,]:3' ],
[ 'message' => 'Baz ~=[,,_,,]:3' ],
];
}
}
public function nyanTextProvider(): iterable {
yield [ 'Foo ~=[,,_,,]:3' ];
yield [ 'Bar ~=[,,_,,]:3' ];
yield [ 'message' => 'Baz ~=[,,_,,]:3' ];
}
function doStuff(iterable $things) {
foreach ($things as $thing) {
/* ... */
}
}
function doStuff(iterable $things) {
foreach (array_chunk($things, 2) as $twoThings) {
/* ... */
}
}
function iterable_to_array(iterable $iterable): array {
if (is_array($iterable)) {
return $iterable;
}
return iterator_to_array($iterable);
}
iterable → Iterator
function iterable_to_iterator(iterable $iterable): Iterator {
if ($iterable instanceof Iterator) {
return $iterable;
}
if (is_array($iterable)) {
return new ArrayIterator($iterable);
}
// TODO: IteratorAggregate case
}
return new IteratorIterator($iterable);
interface IteratorAggregate extends Traversable {
public function getIterator();
}
return new \WMDE\TraversableIterator\TraversableIterator($iterable);
github.com/wmde/iterable-functions
Questions?
www.EntropyWins.wtf
@JeroenDeDauw