DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Cover image for Design Patterns in PHP 8: Prototype
Max Zhuk
Max Zhuk

Posted on • Updated on

Design Patterns in PHP 8: Prototype

Hi!
Design pattern Prototype give us control of making clones of objects. In php syntax we have special keyword/command clone for making object's copy. But it does not allow you to clone correctly some parameters that are implementations of other classes.

I propose to consider an example that can be encountered when developing a blog or an online publication. On such resources, one of the main entity is the Page, which, of course, has an author.

Let's implement this. The author will have, of course, the name, as well as the list of pages of this author. In this case, the list will contain not just an id, but a full-fledged page object.

class Author
{
    public function __construct(
        public readonly string $name,
        private array $pages = []
    ) {}

    public function addPage(Page $page): void
    {
        $this->pages[] = $page;
    }

    public function getPages(): array
    {
        return $this->pages;
    }
}
Enter fullscreen mode Exit fullscreen mode

Also, each page must have an author property that implements the Author class. In addition to other necessary data.

class Page
{
    public function __construct(
        private string $title,
        private string $body,
        public readonly Author $author,
        private array $comments = [],
        private \DateTime $date = new \DateTime()
    ) {
        $this->author->addPage($this);
    }

    public function getTitle(): string
    {
        return $this->title;
    }

    public function setTitle(string $title): void
    {
        $this->title = $title;
    }

    public function getBody(): string
    {
        return $this->body;
    }

    public function setBody(string $body): void
    {
        $this->body = $body;
    }

    public function getComments(): array
    {
        return $this->comments;
    }

    public function addComment(string $comment): void
    {
        $this->comments[] = $comment;
    }

    public function getDate(): \DateTime
    {
        return $this->date;
    }
}
Enter fullscreen mode Exit fullscreen mode

Now, with such a structure, cloning pages becomes not an easy task for PHP. And this may well be necessary if the author wants to make a copy of his article, which in the future will publish a new one based on it. It is for this situation that the Prototype template exists, which allows you to configure exactly how to clone complex objects.

Let's add an implementation of the magic cloning method to the Page class, in which we will describe exactly how we need to clone objects of this class.

public function __clone()
{
    $this->title = "Copy of " . $this->title;
    $this->author->addPage($this);
    $this->comments = [];
    $this->date = new \DateTime();
}
Enter fullscreen mode Exit fullscreen mode

Of course, we can implement more complex logic in the method. In practice, the Page can refer to more other objects in its properties. In such a case Prototype can be a very useful approach.

Top comments (1)

Collapse
sergei_shaikin_becf4a1e8c profile image
Sergei Shaikin

Good article

🌚 Life is too short to browse without dark mode