Welcome back, and this is the third article of the patterns series. We are going to implement a practical structural design pattern — Proxy. So, let’s begin with the theoretical part.
Introduction
First, let’s see what the definition of the Proxy pattern can tell us:
Proxy is a structural design pattern that lets you provide a substitute or placeholder for another object. A proxy controls access to the original object, allowing you to perform something either before or after the request gets through to the original object.
And let’s check the UML schema to visualize how it’s working:
Example of a problem
Imagine that you have a database with a lot of different financial data, and in your application, you make a lot of the same requests to receive data that consumes a large amount of resources. In this case, it will be good to implement caching for some requests that fetch data that is rarely changed.
Implementation
To solve this, we can implement some kind of class that will always be requested before proceeding to the original class that we need — you can imagine that like a guard that does a check. Let’s continue our example, and let’s imagine that we want to have a Redis caching for posts in our application, and instead of always making requests to the database — we can cache this data for 12 hours and retrieve it — and to handle this, we are going to use the Proxy pattern as was mentioned before. So first, let’s create our simple Post model that will be used in the service class later:
<?php
namespace App\Models\Post;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $fillable = ['title', 'content'];
}
Next, we need to have an actual service to retrieve posts from the database:
<?php
namespace App\Services;
use App\Models\Post;
use Illuminate\Support\Collection;
class PostService
{
public function find(int $id): ?Post
{
return Post::find($id);
}
public function latest(int $limit = 10): Collection
{
return Post::latest()->limit($limit)->get();
}
}
And finally — PostCache class — that will be our Proxy for caching or getting actual data from the database if we don’t have cached data:
<?php
namespace App\Cache;
use App\Services\PostService;
use App\Models\Post;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Collection;
class PostCache
{
public function __construct(
private PostService $service
) {}
public function find(int $id): ?Post
{
// As you can see, when there is no cached post
// we request again actual data from service
return Cache::remember(
"posts:{$id}",
now()->addMinutes(10),
fn () => $this->service->find($id)
);
}
public function latest(int $limit = 10): Collection
{
return Cache::remember(
"posts:latest:{$limit}",
now()->addMinutes(5),
fn () => $this->service->latest($limit)
);
}
public function forgot(int $id): void
{
Cache::forget("posts:{$id}");
Cache::forget("posts:latest:*");
}
}
And finally, let’s create a controller to use it:
<?php
namespace App\Http\Controllers;
use App\Cache\PostCache;
class PostController
{
public function __construct(
private PostCache $cache
) {}
public function index()
{
$posts = $postCache->latest();
return response()->json($posts);
}
public function show(int $id)
{
$post = $postCache->find($id);
return response()->json($post);
}
}
Conclusion
As you can see, it’s pretty easy to use the proxy pattern, and it’s very useful when you want to use it in caching to implement it with the cache-aside pattern with Redis or Memcached.

Top comments (0)