3.12. Visitor

    The contract is an abstract class but you can have also a cleaninterface. In that case, each Visitor has to choose itself which methodto invoke on the visitor.

    RoleVisitorInterface.php

    RoleVisitor.php

    1. <?php
    2.  
    3. namespace DesignPatterns\Behavioral\Visitor;
    4.  
    5. class RoleVisitor implements RoleVisitorInterface
    6. {
    7. /**
    8. * @var Role[]
    9. */
    10. private $visited = [];
    11.  
    12. public function visitGroup(Group $role)
    13. {
    14. $this->visited[] = $role;
    15. }
    16.  
    17. public function visitUser(User $role)
    18. {
    19. $this->visited[] = $role;
    20. }
    21.  
    22. /**
    23. * @return Role[]
    24. */
    25. public function getVisited(): array
    26. {
    27. return $this->visited;
    28. }

    User.php

    1. <?php
    2.  
    3. namespace DesignPatterns\Behavioral\Visitor;
    4.  
    5. class User implements Role
    6. {
    7. /**
    8. * @var string
    9. */
    10. private $name;
    11.  
    12. public function __construct(string $name)
    13. {
    14. $this->name = $name;
    15. }
    16.  
    17. public function getName(): string
    18. {
    19. return sprintf('User %s', $this->name);
    20. }
    21.  
    22. public function accept(RoleVisitorInterface $visitor)
    23. {
    24. $visitor->visitUser($this);
    25. }
    26. }

    Group.php

    1. <?php
    2.  
    3. namespace DesignPatterns\Tests\Visitor\Tests;
    4.  
    5. use PHPUnit\Framework\TestCase;
    6.  
    7. class VisitorTest extends TestCase
    8. {
    9. /**
    10. * @var Visitor\RoleVisitor
    11. */
    12. private $visitor;
    13.  
    14. protected function setUp()
    15. {
    16. $this->visitor = new Visitor\RoleVisitor();
    17. }
    18.  
    19. public function provideRoles()
    20. {
    21. return [
    22. [new Visitor\User('Dominik')],
    23. [new Visitor\Group('Administrators')],
    24. ];
    25. }
    26.  
    27. /**
    28. * @dataProvider provideRoles
    29. *
    30. * @param Visitor\Role $role
    31. */
    32. public function testVisitSomeRole(Visitor\Role $role)
    33. {
    34. $role->accept($this->visitor);
    35. $this->assertSame($role, $this->visitor->getVisited()[0]);
    36. }