Use the Proxy Design Pattern | PHP Code Examples in 2023

Last Updated on

CraftyTechie is reader-supported. When you buy through links on our site, we may earn an affiliate commission.

Using the Proxy Design Pattern in PHP

The proxy design pattern is a structural design pattern that provides a substitute object (proxy) for another object (service) while controlling access to the service. This layer of encapsulation is helpful in processing request/response cycles.

Article Highlights

  • The proxy design pattern provides a substitute for another object.
  • Benefit – Uses the same interface as the service and doesn’t need any extra integrations
  • Negative – Can add unnecessary complexity for simple scripts
  • Logger packages are common use cases for the proxy pattern
/*
Proxy class for the repository service. It implements the same interface and delegates the job to the concrete service object.
It only provides a round robin algorithm for selecting read replicas and then calling methods on them.
The client doesn't bother if it is working with a proxy or a concrete service object because both of them implement the same interface.
*/
class RepositoryServiceProxy implements RepositoryServiceInterface{


   private $read_replicas;
   private $count;
   private $repositoryService;


   function __construct($service) {
       $this->read_replicas = [new Database(), new Database(), new Database()];
       $this->count = 0;
       $this->repositoryService = $service;
   }


   //Selects a read replica in a round robin fashion
   public function selectReplica() {
       $DB = $this->read_replicas[$this->count];


       $this->count++;


       if($this->count > count($this->read_replicas)) $this->count = 0; //Round robin goes 1-2-3-1-2-3 and so on....


       return $DB;
   }


   public function listItems() {
      
       $DB = $this->selectReplica();
      
      //Delegate listItems() call to service object
   }


   public function getItem($itemID) {


       $DB = $this->selectReplica();


       //Delegate getItem() call to service object
   }


}
Proxy Design Pattern in PHP
Proxy Design Pattern in PHP

This article features an example of an online store that was in need of architecture to support its business needs. Learn how the proxy pattern in PHP helps them tackle its biggest business challenge.

What is the Proxy Design Pattern

“Proxy design pattern is a structural design pattern that provides a substitute object (proxy) for another object (service). A proxy can control access to the service object and thus it can perform some operations before or after the request gets through the service.”

Proxy Design Pattern in PHP
Proxy Design Pattern

Proxy Design Pattern Example

Scentino is a new fragrance startup with an online presence. They had employed us for their online store creation. Due to budget constraints, the Scentino team wanted a minimalistic solution with a web application and a standard relational database. 

scentino-ui

Let’s go through an interesting example where the proxy pattern in PHP effectively solves a design problem.

Scentino Application Design

The project was simple and straightforward and so were the initial design and architecture.

Proxy Design Pattern in PHP

As the startup continues to grow in terms of traffic and sales, it decided to create a mobile app too. So, we were hired again for this project.

Soon after introducing a mobile app and months of effective marketing strategies, their traffic surged up to a million. Good news! 

However, with great powers come great responsibilities. Scentino was about to hit the wall with its super simple application architecture.

Problem 🙁

Scentino’s applications became super sluggish with the surging traffic volume. The worst part came in the form of frequent downtimes as the database was choked with thousands of simultaneous requests, a number beyond its limit.

database-down

This problem was certain and natural. Initially, the application worked fine with a few hundred visitors but now Scentino was a brand and it had to scale up to improve user experience, stay ahead of its competitors, and make more sales.

stocks-image

Solution 🙂

Our architects proposed adding read-only database replicas so to distribute traffic load and improve throughput. Scentino’s team insisted on not modifying the codebase. They agreed on adding replicas though. 

So, the objective was to add replicas and then add a load balancer, a proxy to distribute network load without the application realizing what’s happening under the hood meaning that the application would just call the same set of methods it used to call before.

read-replicas

Introducing Proxy Objects

The proxy objects are substitutes or placeholders for other objects often called services. It has access to the service object and could sit before and after the service object. The following are features of the proxy objects.

  • Implements the same service interface and thus applications work flawlessly with a proxy just as it does with a service.
  • Satisfies the open/closed principle because we can add as many proxies without modifying the existing code.
  • A proxy can control access to service objects and thus define a firewall or a protective layer over it.
  •  A proxy can exist both before and after the service object in a request & response cycle allowing it to add more functionalities in addition to the base service functions.
  • It can work even if the underlying service is not available by diverting a request or simply exiting the cycle gracefully without crashing the complete application.

Implementing a Proxy

A load balancer is actually a reverse proxy that sits in-between client and server. It forwards requests from the client to the server. Now, a load balancer is what we need here.

reverse-proxy
Reverse proxy

Remember that a proxy generally can exist before and after the service. The reverse proxy is a more specialized term.

Following is the RepositoryServiceProxy pseudoclass example which distributes network traffic in a round-robin fashion. Mind that it will implement the same RepositoryServiceInterface.

/*
Proxy class for the repository service. It implements the same interface and delegates the job to the concrete service object.
It only provides a round robin algorithm for selecting read replicas and then calling methods on them.
The client doesn't bother if it is working with a proxy or a concrete service object because both of them implement the same interface.
*/
class RepositoryServiceProxy implements RepositoryServiceInterface{


   private $read_replicas;
   private $count;
   private $repositoryService;


   function __construct($service) {
       $this->read_replicas = [new Database(), new Database(), new Database()];
       $this->count = 0;
       $this->repositoryService = $service;
   }


   //Selects a read replica in a round robin fashion
   public function selectReplica() {
       $DB = $this->read_replicas[$this->count];


       $this->count++;


       if($this->count > count($this->read_replicas)) $this->count = 0; //Round robin goes 1-2-3-1-2-3 and so on....


       return $DB;
   }


   public function listItems() {
      
       $DB = $this->selectReplica();
      
      //Delegate listItems() call to service object
   }


   public function getItem($itemID) {


       $DB = $this->selectReplica();


       //Delegate getItem() call to service object
   }


}

Application code doesn’t really bother if it is using a proxy object or a concrete service because they both implement the same interface. The proxy delegates the database calls to the service but before that, it selects a database in a round-robin fashion.

Benefits of the Proxy Design Pattern

  • Uses the same interface as the service and doesn’t need any extra integrations.
  • Adds pre-processing or post-processing in a request/response cycle.
  • Can control and protect access to an underlying service.
  • Can handle downtime events gracefully.

Complete Architecture | Proxy Design Pattern in PHP

Proxy Design Pattern in PHP
Proxy Design Pattern in PHP

Proxy Design Pattern PHP Code Example

<?php


/*
That's the service interface that the proxy is supposed to implement.
Note that we have included only read operations to make the example simpler.
For write operations the proxy has to call methods on the master database which will complicate the
example and we could lose focus on the main subject of proxy here.
*/
interface RepositoryServiceInterface {
   public function listItems();
   public function getItem($itemID);
}


//Database class embodies a database entity
class Database {


   public function get() {
       echo "Fetching all items from database".PHP_EOL;
   }


   public function getByID($ID) {
       echo "Fetching item with ID: ".$ID.PHP_EOL;
   }
}


/*
This is the concrete service class that will call the database methods.
The proxy will delegate calls to it using a different database each time.
*/
class RepositoryService implements RepositoryServiceInterface {


   private $DB;


    public function setDatabase($DB) {
        $this->DB = $DB;
   }


   public function listItems() {
       $this->DB->get();
       //Some more logic
   }


   public function getItem($itemID) {
       $this->DB->getByID($itemID);
       //Some more logic
   }
}




/*
Proxy class for the repository service. It implements the same interface and delegates the job to the concrete service object.
It only provides a round robin algorithm for selecting read replicas and then calling methods on them.
The client doesn't bother if it is working with a proxy or a concrete service object because both of them implement the same interface.
*/
class RepositoryServiceProxy implements RepositoryServiceInterface{


   private $read_replicas;
   private $count;
   private $repositoryService;


   function __construct($service) {
       $this->read_replicas = [new Database(), new Database(), new Database()];
       $this->count = 0;
       $this->repositoryService = $service;
   }


   //Selects a read replica in a round robin fashion
   public function selectReplica() {
       $DB = $this->read_replicas[$this->count];


       $this->count++;


       if($this->count > count($this->read_replicas)) $this->count = 0; //Round robin goes 1-2-3-1-2-3 and so on....


       return $DB;
   }


   public function listItems() {
      
       $DB = $this->selectReplica();


       $this->repositoryService->setDatabase($DB);


       $this->repositoryService->listItems();


       //Some more logic if wanted
   }


   public function getItem($itemID) {


       $DB = $this->selectReplica();


       $this->repositoryService->setDatabase($DB);


       $this->repositoryService->getItem($itemID);


       //Some more logic if wanted
   }


}


function main() {


   $service = new RepositoryService();


   $proxy = new RepositoryServiceProxy($service);


   $proxy->listItems();


   $proxy->getItem("100");


}


main();


/*
OUTPUT
Fetching all items from database
Fetching item with ID: 100
*/


?>

Pros and Cons of the Proxy Pattern in PHP

ProsCons
Satisfies open/closed principle: You can add as many proxies without modifying any existing code.Adds complexity by introducing new proxy objects.
Exists in a complete request/response cycle enabling enhanced functions and processing.Service response times can still be a bottleneck.
Works even if the underlying service is unavailable.
Delegates tasks to the service object without the client knowing about it.

Where is the Proxy Pattern Used?

You can use the proxy pattern in PHP when you want to implement:

  • Load balancers or reverse proxies for your client-server application.
  • Access control objects or firewalls to a service.
  • A logger to record and store service logs.
  • Local proxies for remote server execution.
  • Caching response data to avoid redundant server calls.
  • Proxy servers for routing user requests.
  • API gateways for micro-service architecture.

Frequently Asked Questions on the Proxy Design Pattern

What is the proxy pattern?

A proxy design pattern is a structural design pattern that provides a substitute object (proxy) for another object (service). A proxy can control access to the service object and thus it can perform some operations before or after the request gets through the service.

What is the use of the proxy pattern?

You can use the proxy pattern to create proxy objects that can exist before or after a service. These objects can access underlying services and could add features to the request or response coming into and out of the service. Some common use cases are:

  • Caching proxy to cache responses so as to avoid redundant server calls.
  • Logger proxy to log a server’s log data.
  • Protection proxy to control access to the underlying services.
  • Reverse proxy or load balancer to distribute network traffic.
  • Virtual proxy to act as a placeholder for a resource-intensive object.
  • As a proxy for your network traffic routing.

What is a reverse proxy?

A reverse proxy sits in between a client and a server and acts as a middleman for client-server communication. A client initiates a request that passes through a reverse proxy before it eventually reaches a server. A reverse proxy can do many things, including.

  • Identity protection
  • Load balancing
  • Caching
  • Encryption
  • Access control

What is the difference between the decorator and proxy pattern?

DecoratorProxy
Decorators are generic as they add functionality to and can be applied in any order in the stackProxy is more specialized because it can use a service of one specific kind to add functionalities to the incoming requests to the service.
Decorators are added in a stack-like manner and usually, one or more are required to add multiple functionalities.One proxy is enough to provide a set of functionalities. They can exist in the path of the server, before or after it.
Decorators wrap instances of the same interfaceA proxy can receive a service instance or it can create one itself.

Using the Proxy Pattern in PHP Today

Voila! That’s all about the proxy pattern in PHP. Hope you have enjoyed it. Let’s have a quick recap of what we have seen thus far. The proxy pattern is a structural design pattern that introduces proxy objects as substitutes for another object often called services. The proxy pattern has access to these objects.

The proxy objects can sit anywhere before or after the service and could process incoming requests or outgoing responses. Due to these features, a proxy has many use cases including caching, logging, protection, load balancing, and routing to name a few.

The proxy uses the same interface as the service so the application can initiate a request without knowing much about the underlying proxy and service. 

This article features an example of a popular hypothetical online fragrance shop, Scentino. Scentino begins as a small startup with a few hundred visitors daily and thus they use a very barebone, minimalistic architecture with one database.

As they become more and more popular, their traffic volume increases to thousands and millions but new challenges begin to surface as their architecture become too naive to support huge traffic, something beyond its limit.

The software team adds a read-only replica set of databases to distribute the traffic load and improve throughput. That’s where the proxy pattern comes in handy because they receive requests from the client and distribute them among the replicas in a round-robin fashion.

Thus the proxy object acts as a reverse proxy or a load balancer which is one of its uses besides many others.

That’s all. See you in another design pattern article. Stay tuned at FuelingPHP.

Books on Design Patterns

Want to learn more about Design Patterns? There are many great resources online. We recommend the following books for your collection as they both can teach you the theoretical and the application of using design patterns in your day-to-day programming. Feel free to use the following Amazon affiliate links if you’d like to purchase them and a way to support our efforts.

Design Patterns: Elements of Reusable Object-Oriented Software

Design Patterns: Elements of Reusable Object-Oriented Software book

This is the book that started it all. I believe that every programmer should have a referenced copy to this book at some point in their career. There have been many updates and excellent newer content through the years, but this is a classic. It still stands the test of time and is just as relevant for today as it was in the original printing in the 90s.

Check it out on amazon

Learning PHP Design Patterns

This is an excellent book to go beyond the theory and apply it to writing good PHP code. Learning PHP Design Patterns is published by the popular O’Reilly media company. O’Reilly consistently publishes some of the most useful reference material related to software development. They are known to provide materials that thoroughly cover a topic in a way that is simple to understand. I recommend this book to every PHP developer.

Check it out on amazon

Want to see our full review of books on design patterns? Read our huge review article on over 15 design pattern books.

Design Patterns in PHP Learning Series.

This article is part of our series of design patterns in PHP. We are going through all of the patterns and showing how they can help you build better applications. Browse through our full list of patterns below.

Did you find this article helpful?

Join the best weekly newsletter where I deliver content on building better web applications. I curate the best tips, strategies, news & resources to help you develop highly-scalable and results-driven applications.

Build Better Web Apps

I hope you're enjoying this article.

Get the best content on building better web apps delivered to you.