PHP Design Patterns

PHP patterns?

Design patterns are optimized solutions that can be reused on everyday programming problems. They are not classes or libraries that we can connect to our system. Neither are specific to a programming language.

A design pattern is a description or template for how to solve a problem that can be used in many different situations. Patterns are formalized best practices that the programmer can use to solve common problems when designing an application or system.

“Each pattern describes a problem which occurs over and over again… and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without doing it the same way twice”

Christopher Alexander

This guide

In this guide I’m going to present 3 types of PHP design patterns:

  • Structural patterns usually create relationship between entities, making them easier to work together.
  • Creational patterns provide instantiation mechanisms (creates the object instances of a class); therefore, they facilitate the creation of objects in the way that suits the solution.
  • Behavioural patterns are used in communication between entities. They make the communication between these entities easier and more flexible.

I’m going to introduce the, in my opinion, most common Design Patterns used in PHP programming language, 3 Structural patterns (Adapter, Decorator, Front Controller), 2 Creational patterns (Factory, Singleton), and 3 Behavioural patterns (Strategy, Observer, Chain of Responsibility).

Adapter Pattern

The Adapter Pattern is an structural pattern which converts the interface of a class into another interface that clients expect. An adapter lets classes work together that could not otherwise because of incompatible interfaces. The enterprise integration pattern equivalent is the translator.

Adapter pattern. PHP design patterns
Adapter pattern. PHP design patterns

The Adapter Pattern expressed in UML

When to use it?

In case we have a class with a specific functionality, and we have to use that functionality in another class with different parameters. Then, following the Adapter pattern, we could create an adapter class that uses the previous classes and returns the information in the given format.

Example

class Shop {
    public function __construct() { }
}

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

class PaypalAdapter implements shopAdapter {
    private $shop;
    public function __construct(Shop $shop) {
        $this->shop = $shop;
    }
    public function pay($amount) {
        // paypal process...
        $this->shop->sendPayment($amount);
    }
}

$paypal = new PaypalAdapter(new Shop());
$paypal->pay('2629');

Decorator Pattern

The Decorator Pattern (also known as Wrapper) is a structural pattern that attaches additional responsibilities to an object dynamically keeping the same interface. Decorators provide a flexible alternative to subclassing for extending functionality.

Decorator pattern. PHP design patterns
Decorator pattern. PHP design patterns

Decorator Pattern expressed in UML

When to use it?

Imagine we have a class with some features, and we want to add new features to that class, so we create a new class that extends the previous class to add the features… But if we keep doing this we could end up with a class like LineBreakFixingEncryptingZippingStream, in this case we could have created the classes LineBreakFixingDecorator,  EncryptingDecorator, and ZippingDecorator. And then create the object like:

$stream = new ZippingDecorator(
    new EncryptingDecorator(
        new LineBreakFixingDecorator (
            new Stream()
        )
    )
);

Example

class Stream { public function getInfo() }

abstract class StreamDecorator
{
    protected $stream;
    public function __construct(Stream $stream) { 
        $this->stream = $stream; 
    }
    abstract public function getInfo();
}

class ZippingDecorator extends StreamDecorator
{
    public function getInfo() {
        // whatever stream parse...
        $this->stream->getInfo(); // and call parent
    }
}

Front Controller Pattern

The Front controller pattern is a structural pattern which provides a centralized entry point for handling requests.

When to use it?

Front controllers are often used in web applications to implement workflows. While not strictly required, it is much easier to control navigation across a set of related pages (for instance, multiple pages used in an online purchase) from a front controller than it is to make the individual pages responsible for navigation. This script, for example an index.php, would handle all tasks that are common to the application or the framework, such as session handling, caching, and input filtering.

Example

/** Filename: index.php */
use LibraryLoaderAutoloader, LibraryControllerFrontController;
require_once__DIR__ . "/Library/Loader/Autoloader.php";

$autoloader= new Autoloader;
$autoloader->register();
$frontController= new FrontController();
$frontController->run();

Factory Method

The Factory Method is a creational pattern that defines an interface for creating a single object, but lets subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses (dependency injection).

Factory Method
Factory Method. PHP design patterns

Factory Method Pattern in UML

When to use it?

Imagine we have to create a variable number of objects without having to know the details of how they’re created, or what their dependencies are – they only have to give the information they actually want.

Example

interface IThingFactory { public function getThing(theString); }

class ThingFactory implements IThingFactory
{
    public function getThing(string theString) {
        return new Thing(theString, ...);
    }
}

Singleton

Singleton is a creational pattern which ensures that a class has only one instance, and provide a global point of access to it.

When to use it?

Sometimes you need to access to an object, for example a database connection, so you could do something like:

class DB
{
    private static $singleton;
    public static function getSingleton() {
        if (is_null(self::$singleton))
            self::$singleton = new DB();
        return self::$singleton;
    }
}

Strategy Pattern

The Strategy pattern is a behavioural pattern that defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

Strategy pattern. PHP design patterns
Strategy pattern. PHP design patterns

Strategy Method in UML

When to use it?

Imagine that you have a class that can calculate something in different ways. Then you need exactly the same parameters, but depending on the situation you need two different functions.

You could specify the strategy or context into the class and let the context inside the class to decide what to do.

Example

class Thing
{
    private $strategy;
    public function setStrategy ($strat) { 
        $this->strategy = $strat 
    }
    public function caculate($data) { 
        $this->strategy->calculate($data) 
    }
}
interface Strategy
{
    public function calculate($data);
}

class NormalStrategy implements Strategy{
    public function calculate($data) { ...}
}
class SpecialStrategy implements Strategy{
    public function calculate($data) { ...}
}

Observer Pattern

The Observer Pattern (also known as Publish-Subscribe Pattern) is a behavioural design pattern which defines a one-to-many relationship between objects such that, when one object changes its state, all dependent objects are notified and updated automatically.

Observer pattern. PHP design patterns
Observer pattern. PHP design patterns

Observer Pattern expressed in UML

When to use it?

A large monolithic design does not scale well as new graphing or monitoring requirements are levied.

An object with a one-to-many relationship with other objects who are interested in its state is called the subject or publisher. Its dependent objects are called observers or subscribers. The observers are notified whenever the state of the subject changes and can act accordingly. The subject can have any number of dependent observers which it notifies, and any number of observers can subscribe to the subject to receive such notifications.

Example

abstract class Subject
{
    protected $observers;
    function attach(Observer $observer)
    {
        $this­->observers[] = $observer;
    }
    function detach(Observer $observer)
    {
        $key = array_search($this->observers, $observer);
        unset($this->observers[$key]);
    }
    function getState(){ return $this->state; }
    function notify()
    {
        foreach($this­->observers as $observer) {
            $observer­->update($this);
        }
    }
}
abstract class Observer
{
    function update($subject){ $subject->specialFunct(); }
}
class Login extends Subject
{
    //…
    public function handleLogin($user, $pass, $ip)
    {
    //…
    $this­->notify();
    return ... ;
    }
}

class Logger extends Subject
{
    function specialFunct() { .. }
}

$login = new Login();
$login-­>attach(Logger::getInstance());

Chain of Responsibility

The Chain of Responsibility is a Behavioural pattern which avoids coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.

Chain of Responsibility. PHP design patterns
Chain of Responsibility. PHP design patterns

Chain of Responsibility in UML

When to use it?

The Chain of Responsibility design pattern is used when you need a request handled by the most appropriate object for the request. You don’t need to worry about which object handles the request or even if they’ll handle it the same all the time.

Example

abstract class Handler
{
    abstract public function handleRequest($request);
    abstract public function setSuccessor($nextService);
}

class Handle1 extends Handler
{
    private $successor;
    public function setSuccessor($nextService)
    {
        $this->successor=$nextService;
    }
    public function handleRequest ($request)
    {
        if ($this->successor != NULL)
        {
            $this->successor->handleRequest ($request);
        }
    }
}

$handle1 = new Handle1();
$handle2 = new Handle2();
$handle1->setSuccessor($handle2);
$handle1->handleRequest(new Request(...));

Important Notes

Make sure you follow the KISS principle “Keep it simple, stupid” when applying one of this patterns. Using a design pattern in the wrong context can potentially make things worse. But if you use them correctly, they can be your savior.

More references:

Wikipedia: Link
Recommended book: Link

0 0 votes
Article Rating
Subscribe
Notify of
guest
4 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Théo Trautvetter Carranza
Théo Trautvetter Carranza
8 years ago

In the future, whenever I discuss sane programing strategies and techniques, I’ll reference your post.

Joaquín Ruiz
8 years ago

Thanks Théo, I’m glad you like it!

Dharmendra Pradhan
Dharmendra Pradhan
8 years ago

This post explains programming patterns better than some expensive books. Thanks for sharing

Joaquín Ruiz
8 years ago

Cheers Dharmendra!

4
0
Would love your thoughts, please comment.x
()
x