3.4. Итератор
3.4.1. Предназначение
За да направите обекта итеративен и да го направите да изглежда като колекция от обекти.
3.4.2. Примери
за обработка на файл ред по ред, като просто прекарате всички редове (които имат представяне на обект) за файл (което, разбира се, също е обект)
3.4.3. Забележка
Стандартната PHP библиотека (SPL) определя интерфейсен итератор, който е най-подходящ за това! Често бихте искали да внедрите и Countable интерфейса, за да позволите``count ($ object)`` на вашия итеративен обект
3.4.4. UML Диаграма
3.4.5. Код
Можете също да намерите този код в GitHub
Book.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Behavioral\Iterator;
6
7class Book
8{
9 public function __construct(private string $title, private string $author)
10 {
11 }
12
13 public function getAuthor(): string
14 {
15 return $this->author;
16 }
17
18 public function getTitle(): string
19 {
20 return $this->title;
21 }
22
23 public function getAuthorAndTitle(): string
24 {
25 return $this->getTitle() . ' by ' . $this->getAuthor();
26 }
27}
BookList.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Behavioral\Iterator;
6
7use Countable;
8use Iterator;
9
10class BookList implements Countable, Iterator
11{
12 /**
13 * @var Book[]
14 */
15 private array $books = [];
16 private int $currentIndex = 0;
17
18 public function addBook(Book $book)
19 {
20 $this->books[] = $book;
21 }
22
23 public function removeBook(Book $bookToRemove)
24 {
25 foreach ($this->books as $key => $book) {
26 if ($book->getAuthorAndTitle() === $bookToRemove->getAuthorAndTitle()) {
27 unset($this->books[$key]);
28 }
29 }
30
31 $this->books = array_values($this->books);
32 }
33
34 public function count(): int
35 {
36 return count($this->books);
37 }
38
39 public function current(): Book
40 {
41 return $this->books[$this->currentIndex];
42 }
43
44 public function key(): int
45 {
46 return $this->currentIndex;
47 }
48
49 public function next(): void
50 {
51 $this->currentIndex++;
52 }
53
54 public function rewind(): void
55 {
56 $this->currentIndex = 0;
57 }
58
59 public function valid(): bool
60 {
61 return isset($this->books[$this->currentIndex]);
62 }
63}
3.4.6. Тест
Tests/IteratorTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Behavioral\Iterator\Tests;
6
7use DesignPatterns\Behavioral\Iterator\Book;
8use DesignPatterns\Behavioral\Iterator\BookList;
9use PHPUnit\Framework\TestCase;
10
11class IteratorTest extends TestCase
12{
13 public function testCanIterateOverBookList()
14 {
15 $bookList = new BookList();
16 $bookList->addBook(new Book('Learning PHP Design Patterns', 'William Sanders'));
17 $bookList->addBook(new Book('Professional Php Design Patterns', 'Aaron Saray'));
18 $bookList->addBook(new Book('Clean Code', 'Robert C. Martin'));
19
20 $books = [];
21
22 foreach ($bookList as $book) {
23 $books[] = $book->getAuthorAndTitle();
24 }
25
26 $this->assertSame(
27 [
28 'Learning PHP Design Patterns by William Sanders',
29 'Professional Php Design Patterns by Aaron Saray',
30 'Clean Code by Robert C. Martin',
31 ],
32 $books
33 );
34 }
35
36 public function testCanIterateOverBookListAfterRemovingBook()
37 {
38 $book = new Book('Clean Code', 'Robert C. Martin');
39 $book2 = new Book('Professional Php Design Patterns', 'Aaron Saray');
40
41 $bookList = new BookList();
42 $bookList->addBook($book);
43 $bookList->addBook($book2);
44 $bookList->removeBook($book);
45
46 $books = [];
47 foreach ($bookList as $book) {
48 $books[] = $book->getAuthorAndTitle();
49 }
50
51 $this->assertSame(
52 ['Professional Php Design Patterns by Aaron Saray'],
53 $books
54 );
55 }
56
57 public function testCanAddBookToList()
58 {
59 $book = new Book('Clean Code', 'Robert C. Martin');
60
61 $bookList = new BookList();
62 $bookList->addBook($book);
63
64 $this->assertCount(1, $bookList);
65 }
66
67 public function testCanRemoveBookFromList()
68 {
69 $book = new Book('Clean Code', 'Robert C. Martin');
70
71 $bookList = new BookList();
72 $bookList->addBook($book);
73 $bookList->removeBook($book);
74
75 $this->assertCount(0, $bookList);
76 }
77}