Design Patterns in PHP 8: Adapter

Max Zhuk - Aug 29 '22 - - Dev Community

Hello, fellow developers!šŸ§‘šŸ¼ā€šŸ’»

Suppose we decide to create a function that will notify the account manager about a new registered user. We create this function, which will call the universal send() function for sending messages, which takes two strings - the subject of the message and its text.

function messageAboutNewClient(): void
{
    send('New client', 'We have a new client...');
}
Enter fullscreen mode Exit fullscreen mode

It will be better to make it more abstract and OOP-like. For that, we can create a special interface and expect that the class implementing it will take all the necessary work on itself. This will allow us to send messages in the way we want. Suppose, when registering in one way, we send messages by email, and in another way, registration causes the sending of messages, for example, by SMS.

function messageAboutNewClient(NotificationInterface $notification): void
{
    $notification->send('New client', 'We have a new client...');
}
Enter fullscreen mode Exit fullscreen mode

Just like this. And it can implement the interface different ways in each class, no matter how many there are. Now we are not tied to a single function for sending messages and can substitute any class that implements the desired interface. Let's prepare this interface.

interface NotificationInterface
{
    public function send(string $title, string $message): void;
}
Enter fullscreen mode Exit fullscreen mode

The send() function from the beginning of the article implemented sending letters using the standard PHP mail method, let's create a class that implements our interface based on this function.

class EmailNotification implements NotificationInterface
{
    public function __construct(public readonly string $adminEmail)
    {
    }

    public function send(string $title, string $message): void
    {
        // Standard php function for sending emails
        mail($this->adminEmail, $title, $message);
    }
}
Enter fullscreen mode Exit fullscreen mode

And this is how you can send messages about new customers:

$notification = new EmailNotification('mail@zhukmax.com');
messageAboutNewClient($notification);
Enter fullscreen mode Exit fullscreen mode

Some time ago, I wrote a library for sending SMS messages, which I posted on github under a free license. I would like to include it in the project. But there is a problem: the library works a little differently than our interface, it doesn't even have a send method. And here the Adapter design pattern comes to the rescue, which allows you to painlessly connect the library with its interfaces and our project using a special layer class.

Let's create an adapter class that will implement NotificationInterface while working with the library in accordance with the documentation.

use Exception;
use Zhukmax\Smsc\Api;

class SmsNotification implements NotificationInterface
{
    private Api $service;
    private array $phones;

    /**
     * @param array $phones
     */
    public function setPhones(array $phones): void
    {
        $this->phones = $phones;
    }

    /**
     * @throws Exception
     */
    public function __construct(array $config, string $from)
    {
        $this->service = new Api(
            $config['login'],
            $config['password'],
            [
                'https' => $config['https'],
                'charset' => $config['charset'],
                'from' => $from,
                'post' => true
            ]
        );
    }

    public function send(string $title, string $message): void
    {
        $this->service->sendSms($this->phones, `$title $message`);
    }
}
Enter fullscreen mode Exit fullscreen mode

Now we can call the messageAboutNewClient function for sending messages about new clients without changing anything in it. Since the library can throw exceptions, we will wrap everything with a try / catch.

try {
    $notification = new SmsNotification($config, 'mail@zhukmax.com');
    $notification->setPhones([+19001234567]);
    messageAboutNewClient($notification);
} catch (Exception $e) {
    // ...
}
Enter fullscreen mode Exit fullscreen mode

P.S. Fellow developers, if you've found value in this article and are eager to deepen your understanding of design patterns in PHP and TypeScript, I have thrilling news for you! I am in the midst of crafting a comprehensive book that delves extensively into these topics, filled with practical examples, lucid explanations, and real-world applications of these patterns.

This book is being designed to cater to both novices and seasoned developers, aiming to bolster your understanding and implementation of design patterns in PHP and TypeScript. Whether you are aiming to refresh your existing knowledge or venture into new learning territories, this book is your perfect companion.

Moreover, your subscription will play a pivotal role in supporting the completion of this book, enabling me to continue providing you with quality content that can elevate your coding prowess to unprecedented heights.

I invite you to subscribe to my blog on dev.to for regular updates. I am eager to embark on this journey with you, helping you to escalate your coding skills to the next level!


Ā© Photo by Tangerine Chan on Unsplash

. . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player