Milind Daraniya

PHP Design Patterns: Implementing Best Practices

Published January 12th, 2023 7 min read

Design patterns are essential tools in software development that provide proven solutions to common problems. In PHP, leveraging design patterns can lead to more organized, maintainable, and scalable code. In this post, we'll explore some of the most popular PHP design patterns and demonstrate how to implement them effectively.

Singleton Pattern

The Singleton pattern ensures that a class has only one instance and provides a global point of access to it.

class Singleton
{
    private static $instance;

    private function __construct() { }

    public static function getInstance()
    {
        if (!self::$instance) {
            self::$instance = new self();
        }

        return self::$instance;
    }
}

Factory Pattern

The Factory pattern centralizes object creation by providing a dedicated method to create instances of related classes.

interface ProductInterface
{
    public function getName();
}

class ProductA implements ProductInterface
{
    public function getName()
    {
        return 'Product A';
    }
}

class ProductB implements ProductInterface
{
    public function getName()
    {
        return 'Product B';
    }
}

class ProductFactory
{
    public static function createProduct($type)
    {
        switch ($type) {
            case 'A':
                return new ProductA();
            case 'B':
                return new ProductB();
            default:
                throw new \InvalidArgumentException('Invalid product type.');
        }
    }
}

Observer Pattern

The Observer pattern allows an object (subject) to notify its dependent objects (observers) of any state changes.

interface Observer
{
    public function update($data);
}

class UserObserver implements Observer
{
    public function update($data)
    {
        echo "User updated: " . $data . "\n";
    }
}

class Subject
{
    private $observers = [];

    public function attach(Observer $observer)
    {
        $this->observers[] = $observer;
    }

    public function notify($data)
    {
        foreach ($this->observers as $observer) {
            $observer->update($data);
        }
    }
}

// Usage
$subject = new Subject();
$userObserver = new UserObserver();

$subject->attach($userObserver);
$subject->notify("John Doe");

Strategy Pattern

The Strategy pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable.

interface PaymentMethod
{
    public function pay($amount);
}

class CreditCardPayment implements PaymentMethod
{
    public function pay($amount)
    {
        echo "Paid $amount via Credit Card.\n";
    }
}

class PayPalPayment implements PaymentMethod
{
    public function pay($amount)
    {
        echo "Paid $amount via PayPal.\n";
    }
}

class ShoppingCart
{
    private $paymentMethod;

    public function setPaymentMethod(PaymentMethod $paymentMethod)
    {
        $this->paymentMethod = $paymentMethod;
    }

    public function checkout($amount)
    {
        $this->paymentMethod->pay($amount);
    }
}

// Usage
$cart = new ShoppingCart();
$cart->setPaymentMethod(new CreditCardPayment());
$cart->checkout(100);

$cart->setPaymentMethod(new PayPalPayment());
$cart->checkout(50);

Implementing PHP design patterns in your codebase leads to more organized, maintainable, and flexible solutions to common programming problems. Understanding and applying design patterns will help you write efficient, modular, and scalable code.

Remember to choose the appropriate design pattern based on your application's requirements and architecture. Familiarize yourself with other design patterns like Decorator, Adapter, and Iterator, as each one serves a specific purpose and can greatly enhance your development process.