What is PSR-6? A Beginner’s Guide to PHP Caching Standards

Harish Kumar · · 5658 Views
What is PSR-6? A Beginner’s Guide to PHP Caching Standards

Is your PHP application slowing down because of repeated database queries or inefficient caching? Do you wish switching between caching libraries was simpler? That’s where PSR-6 comes in—a PHP standard that provides a consistent interface for caching systems, making your code flexible, efficient, and easier to maintain.

What Problem Does PSR-6 Solve?

Before PSR-6, every caching library had its own unique way of working. Switching from Memcached to Redis, for example, required significant code changes. Similarly, moving to a new framework often meant learning a completely different caching API.

PSR-6 fixes this by providing a standardized caching interface that all libraries can follow. This makes caching predictable and interchangeable—so you can swap caching backends without rewriting your application.

Key Interfaces in PSR-6

At the core of PSR-6 are two main interfaces:

1. CacheItemPoolInterface

This acts as the "manager" for your cache. It provides methods to retrieve, save, and delete cache items.

Key methods include:

  1. getItem($key): Retrieve a single cache item by its key.

  2. save(CacheItemInterface $item): Save an item to the cache.

  3. clear(): Clear all items from the cache.

2. CacheItemInterface

This represents a single item in the cache. It provides methods to manage the cache item's data and expiration time.

Key methods include:

  1. get(): Get the cached value.

  2. set($value): Set a new value for the item.

  3. expiresAfter($time): Set how long the item should remain valid.

Implementing PSR-6 in Real Life

Let’s walk through a simple example of implementing a PSR-6-compatible caching system using a file-based approach.

1. Creating a Cache Item Class

We’ll first create a class to represent individual cache items.

namespace MyApp\Cache;

use Psr\Cache\CacheItemInterface;
use DateTime;

class CacheItem implements CacheItemInterface
{
    private string $key;
    private $value;
    private bool $isHit = false;
    private ?DateTime $expiration = null;

    public function __construct(string $key)
    {
        $this->key = $key;
    }

    public function getKey(): string
    {
        return $this->key;
    }

    public function get()
    {
        return $this->value;
    }

    public function isHit(): bool
    {
        return $this->isHit;
    }

    public function set($value): self
    {
        $this->value = $value;
        return $this;
    }

    public function expiresAt(?DateTime $expiration): self
    {
        $this->expiration = $expiration;
        return $this;
    }

    public function expiresAfter($time): self
    {
        $this->expiration = (new DateTime())->modify("+{$time} seconds");
        return $this;
    }

    // Internal helpers
    public function setHit(bool $hit): void
    {
        $this->isHit = $hit;
    }

    public function getExpiration(): ?DateTime
    {
        return $this->expiration;
    }
}

2. Creating a File-Based Cache Pool

Next, we’ll create a class to manage these cache items and store them in files.

namespace MyApp\Cache;

use Psr\Cache\CacheItemPoolInterface;
use Psr\Cache\CacheItemInterface;

class FileCachePool implements CacheItemPoolInterface
{
    private string $directory;

    public function __construct(string $directory)
    {
        if (!is_dir($directory) && !mkdir($directory, 0777, true)) {
            throw new \RuntimeException("Cannot create cache directory: {$directory}");
        }
        $this->directory = $directory;
    }

    public function getItem($key): CacheItemInterface
    {
        $filePath = $this->getFilePath($key);
        $item = new CacheItem($key);

        if (file_exists($filePath)) {
            $data = unserialize(file_get_contents($filePath));
            if (!$data['expiration'] || $data['expiration'] > time()) {
                $item->set($data['value']);
                $item->setHit(true);
            }
        }

        return $item;
    }

    public function save(CacheItemInterface $item): bool
    {
        $filePath = $this->getFilePath($item->getKey());
        $data = [
            'value' => $item->get(),
            'expiration' => $item->getExpiration()?->getTimestamp(),
        ];

        return file_put_contents($filePath, serialize($data)) !== false;
    }

    public function clear(): bool
    {
        foreach (glob($this->directory . '/*.cache') as $file) {
            unlink($file);
        }
        return true;
    }

    private function getFilePath(string $key): string
    {
        return $this->directory . '/' . sha1($key) . '.cache';
    }
}

Using the Cache in Your Application

Here’s how you can use the cache system in a real application:

use MyApp\Cache\FileCachePool;

// Create a cache pool with a file directory
$cachePool = new FileCachePool(__DIR__ . '/cache');

// Fetch a cache item
$item = $cachePool->getItem('user_123');

if (!$item->isHit()) {
    // Item not found in cache, fetch from database
    $userData = getUserFromDatabase(123);
    $item->set($userData)
         ->expiresAfter(3600); // Cache for 1 hour

    // Save the item in the cache
    $cachePool->save($item);
}

// Use the cached data
$user = $item->get();
print_r($user);

Why Use PSR-6?

  1. Flexibility: Easily swap caching backends (e.g., from Redis to Memcached) without rewriting your code.

  2. Consistency: Standardized methods mean you don’t need to learn a new API for every caching library.

  3. Improved Performance: Reduces database calls and speeds up your application.

.

🔥 Boost Your Productivity with Ctrl+Alt+Cheat!

Take your coding efficiency to the next level with Ctrl+Alt+Cheat, the ultimate VSCode extension for developers. Whether you're working with PHP, JavaScript, Laravel, or any other technology, this extension provides over 60 curated cheat sheets to speed up your workflow.

Special Offer: Use the discount code "YT-FAMILY" at checkout and get an exclusive 50% discount. Don't miss this chance to supercharge your development experience—grab Ctrl+Alt+Cheat today!

👉 Download Ctrl+Alt+Cheat today and start coding like a pro!

0

Please login or create new account to add your comment.

0 comments
You may also like:

Composition vs. Inheritance in PHP: Why Composition is Better for Your Code

In object-oriented programming, polymorphism can be achieved through two primary approaches: Inheritance and Composition. Let’s dive into their definitions and explore why composition (...)
Harish Kumar

Understanding PHP Invokable Classes: Examples, Use Cases, and Real-World Applications

In PHP, an invokable class is a class you can call like a function. To make a class invokable, PHP provides a special magic method called __invoke(). Once implemented, this allows (...)
Harish Kumar

Exploring Asymmetric Property Visibility in PHP 8.4

The release of PHP 8.4 introduces a powerful new feature: Asymmetric Property Visibility, enabling developers to define separate visibility rules for reading and writing properties. (...)
Harish Kumar

What's New in PHP 8.4: Key Enhancements and Updates

As PHP 8.4's release on November 21, 2024, approaches, it's clear that PHP continues to evolve and delight its developer community. For those who have been coding with PHP since (...)
Harish Kumar

Introducing Tools to Supercharge PHP-FPM Efficiency and Monitoring

PHP-FPM stands for PHP FastCGI Process Manager. It’s an improved way to manage PHP processes that makes web applications faster and more efficient. Instead of running each PHP (...)
Harish Kumar

PHP 8.4 Property Hooks: The Ultimate Guide for Developers

PHP 8.4, coming in November 2024, introduces a new feature called property hooks. This feature makes it easier to work with class properties by allowing you to define custom behavior (...)
Harish Kumar