1. Code
  2. PHP

Set Up Caching in PHP With the Symfony Cache Component

Scroll to top

Today, I'll show you the Symfony Cache component, an easy way to add caching to your PHP applications. This helps improve the overall performance of your application by reducing the page load time.

The Symfony Cache Component

The Symfony Cache component allows you to set up caching in your PHP applications. The component itself is very easy to install and configure and allows you to get started quickly. Also, it provides a variety of adapters to choose from, as shown in the following list:

  • database adapter
  • filesystem adapter
  • memcached adapter
  • Redis adapter
  • APCu adapter
  • and more

When it comes to caching using the Symfony Cache component, there are a couple of terms that you should get familiar with. The Symfony Cache component allows you to choose between two different caching approaches.

PSR-6 Caching

It's a generic cache system which revolves around cache pools and cache items.

To start with, the cache item refers to the content which is stored. Each item is stored as a key-value pair. Cache items are managed by the cache pool, which groups them logically. In fact, you need to use the cache pool to manipulate cache values.

Finally, it's the cache adapter which does all the heavy lifting to store items in the cache back-end.

Cache Contracts

It's a simple but more powerful way to cache values based on recomputation callbacks. It also comes with built-in Stampede prevention. It's also the recommended way since it requires less code compared to PSR-6 caching.

In this article, we'll explore both ways to understand how you can unleash the power of the Symfony Cache component. As usual, we'll start with installation and configuration, and then we'll go on to explore a few real-world examples in the latter half of the article.

Installation and Configuration

In this section, we're going to install the Cache component. I assume that you have already installed Composer in your system—you'll need it to install the Cache component available at Packagist.

Once you have installed Composer, go ahead and install the Cache component using the following command.

1
$composer require symfony/cache

That should have created a composer.json file, which should look like this:

1
{
2
    "require": {
3
        "symfony/cache": "^4.1"
4
    }
5
}

That's it for installation, but how are you supposed to add it to your application? It's just a matter of including the autoload.php file created by Composer in your application, as shown in the following snippet.

1
<?php
2
require_once './vendor/autoload.php';
3
 
4
// application code

5
?>

PSR-6 Caching: A Real-World Example

In this section, we'll go through an example which demonstrates how you could use the Cache component in your applications to cache content with the PSR-6 caching method.

To start with, let's go ahead and create the index.php file with the following contents.

1
<?php
2
require_once './vendor/autoload.php';
3
 
4
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
5
6
$cachePool = new FilesystemAdapter();
7
8
// 1. store string values

9
$demoString = $cachePool->getItem('demo_string');
10
if (!$demoString->isHit())
11
{
12
    $demoString->set('Hello World!');
13
    $cachePool->save($demoString);
14
}
15
16
if ($cachePool->hasItem('demo_string'))
17
{
18
    $demoString = $cachePool->getItem('demo_string');
19
    echo $demoString->get();
20
    echo "<br>";
21
}
22
23
// delete all items

24
$cachePool->clear();
25
26
if (!$cachePool->hasItem('demo_string'))
27
{
28
    echo "The cache entry demo_string was deleted successfully!\n";
29
}
30
31
// 2. store array values

32
$demoOne = $cachePool->getItem('demo_array');
33
if (!$demoOne->isHit())
34
{
35
    $demoOne->set(array("one", "two", "three"));
36
    $cachePool->save($demoOne);
37
}
38
39
if ($cachePool->hasItem('demo_array'))
40
{
41
    $demoOne = $cachePool->getItem('demo_array');
42
    var_dump($demoOne->get());
43
    echo "<br>";
44
}
45
46
// delete specific item

47
$cachePool->deleteItem('demo_array');
48
49
if (!$cachePool->hasItem('demo_array'))
50
{
51
    echo "The cache entry demo_array was deleted successfully!\n";
52
    echo "<br>";
53
}
54
55
// 3. set expiry on items

56
$foo = $cachePool->getItem('foo');
57
if (!$foo->isHit())
58
{
59
    $foo->set('bar');
60
    $foo->expiresAfter(5);
61
    $cachePool->save($foo);
62
}
63
64
if ($cachePool->hasItem('foo'))
65
{
66
    $foo = $cachePool->getItem('foo');
67
    echo $foo->get();
68
    echo "<br>";
69
}
70
sleep(6);
71
if ($cachePool->hasItem('foo'))
72
{
73
    $foo = $cachePool->getItem('foo');
74
    echo $foo->get();
75
    echo "<br>";
76
}
77
else
78
{
79
    echo "Cache item was expired!\n";
80
}

Let's go through the main parts of the index.php file to understand their purpose.

Create the Cache Pool

As we discussed earlier, cached items are stored in a cache pool. Furthermore, each cache pool is backed by a specific cache back-end and adapter. If you want to store items in the file system cache, for example, you need to initialize the cache pool of the file system adapter.

1
$cachePool = new FilesystemAdapter();

You can provide three optional arguments to the FilesystemAdapter object:

  • the namespace in which you would like to create cache entries
  • a lifetime in seconds for cache items
  • the directory in which the cache will be stored.

How to Store String Values

Since we've already created the cache pool, we can use it to store cache items.

Firstly, we've used the getItem method to fetch the cache item with the demo_string key. Next, we've used the isHit method to check if the value we're looking for is already present in the cache item $demoString.

1
$demoString = $cachePool->getItem('demo_string');
2
if (!$demoString->isHit())
3
{
4
    $demoString->set('Hello World!');
5
    $cachePool->save($demoString);
6
}

Since this is the first time we're fetching the demo_string cache item, the isHit method should return false. Next, we've used the set method of the $demoString object to set the cache value. Finally, we've saved the $demoString cache item into the $cachePool cache pool using the save method.

Now that we've stored the item in the cache, let's see how to fetch it from the cache.

1
if ($cachePool->hasItem('demo_string'))
2
{
3
    $demoString = $cachePool->getItem('demo_string');
4
    echo $demoString->get();
5
    echo "\n";
6
}

Here, we've used the hasItem method to check the existence of the cache item in the cache pool before retrieving it. 

Next, let's see how to delete all cache items from the cache pool:

1
$cachePool->clear();

How to Store Array Values

In the previous section, we discussed how to store basic values in the cache pool. Storing array values is pretty much the same, as you can see in the following example.

1
$demoOne = $cachePool->getItem('demo_array');
2
if (!$demoOne->isHit())
3
{
4
    $demoOne->set(array("one", "two", "three"));
5
    $cachePool->save($demoOne);
6
}
7
 
8
if ($cachePool->hasItem('demo_array'))
9
{
10
    $demoOne = $cachePool->getItem('demo_array');
11
    var_dump($demoOne->get());
12
    echo "\n";
13
}

As you can see, we can simply set the cache item with an array value, just the same as we did for a string. 

Next, let's see how to delete a specific cache item from the cache pool.

1
$cachePool->deleteItem('demo_array');

Here, we've used the deleteItem method to delete the demo_array item from the cache pool.

How to Set an Expiry Date for Cached Items

So far, we've cached items into the pool without an expiry date. However, you don't typically want to store items in the cache permanently. For example, you want to refresh cache items periodically, so you need a mechanism which purges expired cache items.

In this section, we'll discuss how to store items in the cache along with an expiry date.

1
$foo = $cachePool->getItem('foo');
2
if (!$foo->isHit())
3
{
4
    $foo->set('bar');
5
    $foo->expiresAfter(30);
6
    $cachePool->save($foo);
7
}

As you can see in the above snippet, you can use the expiresAfter method to set an expiry date for the cached item. You can pass the number of seconds you would like to cache an item for in the first argument of the expiresAfter method.

In our example, we've used the sleep method to test if the cached item is still available in the cache pool.

1
if ($cachePool->hasItem('foo'))
2
{
3
    $foo = $cachePool->getItem('foo');
4
    echo $foo->get();
5
    echo "\n";
6
}
7
sleep(60);
8
if ($cachePool->hasItem('foo'))
9
{
10
    $foo = $cachePool->getItem('foo');
11
    echo $foo->get();
12
    echo "\n";
13
}
14
else
15
{
16
    echo "Cache item was expired!\n";
17
}

Go ahead and test it to see how it works!

Cache Contracts: A Real-World Example

In this section, we'll go through an example which demonstrates how you could use the Cache component in your applications to cache content with the help of Cache Contracts.

To start with, let's go ahead and create the cache_contracts.php file with the following contents.

1
<?php
2
require_once './vendor/autoload.php';
3
4
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
5
use Symfony\Contracts\Cache\ItemInterface;
6
7
$cachePool = new FilesystemAdapter();
8
9
// 1. store string values

10
$value = $cachePool->get('demo_string', function (ItemInterface $item) {
11
    return 'Hello World!';
12
});
13
14
echo $value;
15
echo "<br>";
16
17
// delete specific item

18
$cachePool->delete('demo_string');
19
20
// 2. set expiry on items

21
$value = $cachePool->get('foo', function (ItemInterface $item) {
22
    $item->expiresAfter(5);
23
24
    // retrieve/calculate the value of this cache item as you want

25
    $cacheItemValue = 'bar';
26
27
    return $cacheItemValue;
28
});

Let's go through the main parts of the cache_contracts.php file to understand their purpose.

How to Store Cache Values With Cache Contracts

First of all, it's important to note that Cache Contracts only support two methods. The get method is used to get and set cache values. On the other hand, the delete method is used to delete the cache item.

Now, let's quickly look at the following snippet which is used to set and get the cache value at the same time.

1
$cachePool = new FilesystemAdapter();
2
$value = $cachePool->get('demo_string', function (ItemInterface $item) {
3
    return 'Hello World!';
4
});

First of all, you need to initialize the cache pool instance. Now, we can use this object to set cache values with the help of Cache Contracts. As you can see, the first argument is a cache key, and the second argument is a PHP callable, which is only executed if the key is not found in the cache pool. The PHP callable is responsible for generating the cache value and returning it.

How to Set an Expiry Date for Cached Items With Cache Contracts

It's very easy to set the cache item along with an expiry date. Let's quickly look at the following snippet.

1
$value = $cachePool->get('foo', function (ItemInterface $item) {
2
    $item->expiresAfter(5);
3
4
    // retrieve/calculate the value of this cache item as you want

5
    $cacheItemValue = 'bar';
6
7
    return $cacheItemValue;
8
});

As you can see, we've used the expiresAfter method of the $item object to set the expiration date.

Invalidate Cache Items With Cache Tags

When you create cache items, you can attach a tag to them. So it's like keeping logically grouped cache items together under the same tag. It's really useful when you want to delete all cache items that are related to each other, and don't want to delete them by key.

Let's quickly look at the following snippet.

1
<?php
2
require_once './vendor/autoload.php';
3
4
use Symfony\Component\Cache\Adapter\FilesystemTagAwareAdapter;
5
use Symfony\Contracts\Cache\ItemInterface;
6
7
$cachePool = new FilesystemTagAwareAdapter();
8
9
$value = $cachePool->get('foo_product_details', function (ItemInterface $item) {
10
    $item->tag('foo');
11
    return 'Hello World!';
12
});
13
$value = $cachePool->get('foo_product_categories', function (ItemInterface $item) {
14
    $item->tag('foo');
15
    return array('Category One', 'Category Two');
16
});
17
$value = $cachePool->get('foo_product_variations', function (ItemInterface $item) {
18
    $item->tag('foo');
19
    return array('Product Variation One', 'Product Variation Two');
20
});
21
22
$cachePool->invalidateTags(['foo']);

It's important to note that when you want to attach tags to cache items, you need to use the tag-aware cache adapter. Thus, we've used the FilesystemTagAwareAdapter adapter which is the tag-aware version of the FilesystemAdapter adapter.

Next, you need to use the tag method to attach a tag to the cache item. And finally, you can use the invalidateTags method of the adapter class to remove cache entries associated with specific cache tags.

So that's how you can use Cache Contracts for cache management in your projects.

Conclusion

Today, we had a brief look at the Symfony Cache component, which allows you to set up caching in your PHP applications. It also supports a variety of caching adapters that together give you the flexibility to choose the kind of back-end you want to use.

Post thumbnail generated by OpenAI DALL-E.

Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.