PHP Design Patterns: Facade

Antonio Silva - Oct 21 - - Dev Community

The Facade Design Pattern is a structural pattern that provides a simplified interface to a complex set of classes, libraries, or subsystems. It is used to hide the complexity of systems and offer a more user-friendly and easy-to-use interface for clients.

Facade Diagram

Main Goals

  • Simplify interaction: By creating a single, simple interface, the Facade pattern makes it easier to use a complex system without exposing all its internal complexity.
  • Encapsulation of subsystems: The classes that make up the subsystem may be complex, but the facade acts as an abstraction layer, allowing the client to interact only with simple and cohesive methods.
  • Decoupling: The pattern helps keep the client decoupled from the internal implementation, making the system easier to maintain and expand in the future.

Example Using PHPMailer and Facade Pattern

Situation:

Imagine we have an application that needs to send emails in a simple way. The process of sending emails can involve authentication settings, SMTP servers, setting the sender, recipient, email body, attachments, etc. Instead of exposing this entire complex process to the end-user, we can create a Facade to encapsulate these operations.

Install PHPMailer via Composer

composer require phpmailer/phpmailer
Enter fullscreen mode Exit fullscreen mode

Directory System

📦Facade
 ┣ 📂src
 ┃ ┗ 📜MailFacade.php
 ┣ 📂vendor
 ┣ 📜composer.json
 ┗ 📜index.php
Enter fullscreen mode Exit fullscreen mode

Autoload

First, let's make sure that Composer manages the dependencies and autoloads the classes correctly.

In the composer.json file, we can include the autoload of the classes from the src folder and also add the PHPMailer dependency:

{
  "require": {
    "phpmailer/phpmailer": "^6.0"
  },
  "autoload": {
    "psr-4": {
      "App\\": "src/"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Class MailFacade

Now let's create a MailFacade class that will act as the facade to simplify the process of sending emails for the user.

namespace App;

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

// Facade class
class MailFacade {
    private $mail;

    public function __construct() {
        $this->mail = new PHPMailer(true);  // Create a new instance of PHPMailer
        $this->mail->isSMTP();              // Set up to use SMTP
        $this->mail->Host = 'smtp.example.com';  // Set the SMTP server
        $this->mail->SMTPAuth = true;       // Enable SMTP authentication
        $this->mail->Username = 'user@example.com'; // SMTP username
        $this->mail->Password = 'secret';   // SMTP password
        $this->mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // Enable TLS encryption
        $this->mail->Port = 587;            // SMTP server port
    }

}
Enter fullscreen mode Exit fullscreen mode

Method sendEmail

// Method to send a simple email
public function sendEmail($to, $subject, $body) {
    try {
        // Set sender
        $this->mail->setFrom('from@example.com', 'Sender Name');

        // Set recipient
        $this->mail->addAddress($to);  // You can add more with $this->mail->addAddress('recipient2@example.com');

        // Set email subject and body
        $this->mail->Subject = $subject;
        $this->mail->Body = $body;
        $this->mail->isHTML(true); // Set email body to accept HTML

        // Send email
        $this->mail->send();
        echo 'Email successfully sent!';
    } catch (Exception $e) {
        echo "Error sending email: {$this->mail->ErrorInfo}";
    }
}
Enter fullscreen mode Exit fullscreen mode

Method sendEmailWithAttachment

// Method to send an email with an attachment
public function sendEmailWithAttachment($to, $subject, $body, $attachmentPath) {
    try {
        // Same basic configuration as in the previous method
        $this->mail->setFrom('from@example.com', 'Sender Name');
        $this->mail->addAddress($to);

        // Set subject and body
        $this->mail->Subject = $subject;
        $this->mail->Body = $body;
        $this->mail->isHTML(true);

        // Add the attachment
        $this->mail->addAttachment($attachmentPath);

        // Send the email
        $this->mail->send();
        echo 'Email with attachment successfully sent!';
    } catch (Exception $e) {
        echo "Error sending email: {$this->mail->ErrorInfo}";
    }
}
Enter fullscreen mode Exit fullscreen mode

Test

require 'vendor/autoload.php';

use App\MailFacade;

// Using the Facade
$mailFacade = new MailFacade();

// Sending a simple email
$mailFacade->sendEmail('recipient@example.com', 'Email Subject', 'Email body in HTML');

// Sending an email with an attachment
$mailFacade->sendEmailWithAttachment('recipient@example.com', 'Subject with Attachment', 'Here is your attachment', '/path/to/attachment.pdf');
Enter fullscreen mode Exit fullscreen mode

How it works:

  • MailFacade: This class encapsulates all the logic needed to configure and send an email, allowing the user of the facade to simply call a method to send the email.
  • PHPMailer: The complexity of PHPMailer (such as SMTP configuration, authentication, etc.) is hidden within the facade.

Benefits:

  • Simplicity: The client code (who uses the MailFacade) doesn’t need to know details such as server configuration, PHPMailer methods, etc.
  • Reusable: The facade can be used in different parts of the application without needing to repeat code or logic.
  • Maintainable: If something in the implementation needs to change (e.g., switching the SMTP server), you only need to update it within the MailFacade class.

This is a practical example of how the Facade pattern can simplify interactions with complex libraries like PHPMailer.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .