今天,我将向各位展示 Symfony 缓存组件,这是一种向 PHP 应用程序添加缓存的简单方法。 这有助于通过减少页面加载时间来提高应用程序的整体性能。
Symfony 缓存组件
Symfony 缓存组件允许我们在 PHP 应用程序中设置缓存。 该组件本身非常易于安装和配置,可让我们快速上手。 此外,它还提供了多种适配器可供选择,如下列表所示:
- 数据库适配器
- 文件系统适配器
- 缓存适配器
- Redis适配器
- APCu适配器
当谈到使用 Symfony 缓存组件进行缓存时,我们应该熟悉几个术语。 Symfony 缓存组件允许我们在两种不同的缓存方法之间进行选择。
PSR-6 缓存
它是一个通用的缓存系统,围绕着缓存池和缓存项。
首先,缓存项是指存储的内容。 每个项目都存储为键值对。 缓存项由缓存池管理,缓存池对它们进行逻辑分组。 实际上,我们需要使用缓存池来操作缓存值。
最后,缓存适配器完成所有繁重的工作,将项目存储在缓存后端。
缓存接口
这是一种基于重新计算回调来缓存值的简单但更强大的方法。 它还带有内置的踩踏预防功能。 这也是推荐的方式,因为与 PSR-6 缓存相比,它需要更少的代码。
在这篇文章中,我们将探索这两种方式来理解如何释放 Symfony 缓存组件的力量。 像往常一样,我们将从安装和配置开始,然后我们将在本文的后半部分继续探索一些真实的示例。
安装和配置
在本节中,我们将安装缓存组件。 我假设大家已经在系统中安装了 Composer——我们将需要它来安装 Packagist 提供的缓存组件。
安装 Composer 后,继续使用以下命令安装 Cache 组件。
$ composer require symfony/cache
那应该已经创建了一个 composer.json 文件,它应该如下所示:
composer.json
{ "require": { "symfony/cache": "^4.1" } }
这就是安装,但是我们应该如何将它添加到您的应用程序中呢? 只需将 Composer 创建的 autoload.php 文件包含在我们的应用程序中即可,如以下代码片段所示。
require_once './vendor/autoload.php';
// 应用程序代码
PSR-6 缓存:一个真实的例子
在本节中,我们将通过一个示例演示如何在您的应用程序中使用缓存组件来通过 PSR-6 缓存方法缓存内容。
首先,让我们继续创建包含以下内容的 index.php 文件。
index.php
require_once './vendor/autoload.php'; use Symfony\Component\Cache\Adapter\FilesystemAdapter; $cachePool = new FilesystemAdapter(); // 1. store string values $demoString = $cachePool->getItem('demo_string'); if (!$demoString->isHit()) { $demoString->set('Hello World!'); $cachePool->save($demoString); } if ($cachePool->hasItem('demo_string')) { $demoString = $cachePool->getItem('demo_string'); echo $demoString->get(); echo "<br>"; } // delete all items $cachePool->clear(); if (!$cachePool->hasItem('demo_string')) { echo "The cache entry demo_string was deleted successfully!\n"; } // 2. store array values $demoOne = $cachePool->getItem('demo_array'); if (!$demoOne->isHit()) { $demoOne->set(array("one", "two", "three")); $cachePool->save($demoOne); } if ($cachePool->hasItem('demo_array')) { $demoOne = $cachePool->getItem('demo_array'); var_dump($demoOne->get()); echo "<br>"; } // delete specific item $cachePool->deleteItem('demo_array'); if (!$cachePool->hasItem('demo_array')) { echo "The cache entry demo_array was deleted successfully!\n"; echo "<br>"; } // 3. set expiry on items $foo = $cachePool->getItem('foo'); if (!$foo->isHit()) { $foo->set('bar'); $foo->expiresAfter(5); $cachePool->save($foo); } if ($cachePool->hasItem('foo')) { $foo = $cachePool->getItem('foo'); echo $foo->get(); echo "<br>"; } sleep(6); if ($cachePool->hasItem('foo')) { $foo = $cachePool->getItem('foo'); echo $foo->get(); echo "<br>"; } else { echo "Cache item was expired!\n"; }
让我们通过 index.php 文件的主要部分来了解它们的用途。
创建缓存池
正如我们之前讨论的,缓存项存储在缓存池中。 此外,每个缓存池都由特定的缓存后端和适配器支持。 例如,如果要在文件系统缓存中存储项目,则需要初始化文件系统适配器的缓存池。
$cachePool = new FilesystemAdapter();
我们可以为 FilesystemAdapter
对象提供三个可选参数:
- 我们要在其中创建缓存条目的名称空间
- 缓存项的生命周期(以秒为单位)
- 将存储缓存的目录。
如何存储字符串值
由于我们已经创建了缓存池,我们可以用它来存储缓存项。
首先,我们使用 getItem
方法通过 demo_string 键获取缓存项。 接下来,我们使用 isHit
方法检查我们要查找的值是否已存在于缓存项 $demoString
中。
$demoString = $cachePool->getItem('demo_string');
if (!$demoString->isHit())
{
$demoString->set('Hello World!');
$cachePool->save($demoString);
}
因为这是我们第一次获取 demo_string 缓存项,所以 isHit
方法应该返回 false。 接下来,我们使用了 $demoString
对象的 set
方法来设置缓存值。 最后,我们使用 save
方法将 $demoString
缓存项保存到 $cachePool
缓存池中。
现在我们已经将项目存储在缓存中,让我们看看如何从缓存中获取它。
if ($cachePool->hasItem('demo_string'))
{
$demoString = $cachePool->getItem('demo_string');
echo $demoString->get();
echo "\n";
}
在这里,我们使用 hasItem
方法在检索之前检查缓存池中是否存在缓存项。
接下来我们看看如何删除缓存池中的所有缓存项:
$cachePool->clear();
如何存储数组值
在上一节中,我们讨论了如何将基本值存储在缓存池中。 存储数组值几乎相同,如大家在以下示例中所见。
$demoOne = $cachePool->getItem('demo_array');
if (!$demoOne->isHit())
{
$demoOne->set(array("one", "two", "three"));
$cachePool->save($demoOne);
}
if ($cachePool->hasItem('demo_array'))
{
$demoOne = $cachePool->getItem('demo_array');
var_dump($demoOne->get());
echo "\n";
}
如大家所见,我们可以简单地使用数组值设置缓存项,就像我们对字符串所做的一样。
接下来,让我们看看如何从缓存池中删除特定的缓存项。
$cachePool->deleteItem('demo_array');
在这里,我们使用 deleteItem
方法从缓存池中删除 demo_array 项。
如何为缓存项设置过期日期
到目前为止,我们已经将没有过期日期的项目缓存到池中。 但是,我们通常不希望将项目永久存储在缓存中。 例如,我们希望定期刷新缓存项,因此我们需要一种清除过期缓存项的机制。
在本节中,我们将讨论如何在缓存中存储项目以及过期日期。
$foo = $cachePool->getItem('foo');
if (!$foo->isHit())
{
$foo->set('bar');
$foo->expiresAfter(30);
$cachePool->save($foo);
}
正如我们在上面的代码片段中看到的,我们可以使用 expiresAfter
方法为缓存项设置到期日期。 我们可以在 expiresAfter
方法的第一个参数中传递我们希望缓存项目的秒数。
在我们的示例中,我们使用 sleep
方法来测试缓存项在缓存池中是否仍然可用。
if ($cachePool->hasItem('foo'))
{
$foo = $cachePool->getItem('foo');
echo $foo->get();
echo "\n";
}
sleep(60);
if ($cachePool->hasItem('foo'))
{
$foo = $cachePool->getItem('foo');
echo $foo->get();
echo "\n";
}
else
{
echo "Cache item was expired!\n";
}
继续测试它,看看它是如何工作的!
缓存接口:一个真实的例子
在本节中,我们将通过一个示例演示如何在缓存接口的帮助下在应用程序中使用缓存组件来缓存内容。
首先,让我们继续创建具有以下内容的 cache_contracts.php 文件。
cache_contracts.php
require_once './vendor/autoload.php'; use Symfony\Component\Cache\Adapter\FilesystemAdapter; use Symfony\Contracts\Cache\ItemInterface; $cachePool = new FilesystemAdapter(); // 1. store string values $value = $cachePool->get('demo_string', function (ItemInterface $item) { return 'Hello World!'; }); echo $value; echo "<br>"; // delete specific item $cachePool->delete('demo_string'); // 2. set expiry on items $value = $cachePool->get('foo', function (ItemInterface $item) { $item->expiresAfter(5); // retrieve/calculate the value of this cache item as you want $cacheItemValue = 'bar'; return $cacheItemValue; });
让我们通过 cache_contracts.php 文件的主要部分来了解它们的用途。
如何使用缓存接口存储缓存值
首先需要注意的是,Cache Contracts
只支持两种方法。 get
方法用于获取和设置缓存值。 另一方面,delete
方法用于删除缓存项。
现在,让我们快速查看以下用于同时设置和获取缓存值的代码片段。
$cachePool = new FilesystemAdapter();
$value = $cachePool->get('demo_string', function (ItemInterface $item) {
return 'Hello World!';
});
首先,我们需要初始化缓存池实例。 现在,我们可以使用这个对象在缓存契约的帮助下设置缓存值。 如我们所见,第一个参数是缓存键,第二个参数是 PHP 可调用对象,只有在缓存池中找不到该键时才会执行。 PHP 可调用对象负责生成缓存值并返回它。
如何使用缓存合约设置缓存项的到期日期
设置缓存项和到期日期非常容易。 让我们快速看一下下面的代码片段。
$value = $cachePool->get('foo', function (ItemInterface $item) {
$item->expiresAfter(5);
// retrieve/calculate the value of this cache item as you want
$cacheItemValue = 'bar';
return $cacheItemValue;
});
如大家所见,我们使用了 $item
对象的 expiresAfter
方法来设置到期日期。
使用缓存标签使缓存项无效
当我们创建缓存项时,我们可以将标签附加到它们。 所以这就像将逻辑分组的缓存项放在同一个标签下。 当你想删除所有相互关联的缓存项,又不想按键删除时,它真的很有用。
让我们快速看一下下面的代码片段。
require_once './vendor/autoload.php';
use Symfony\Component\Cache\Adapter\FilesystemTagAwareAdapter;
use Symfony\Contracts\Cache\ItemInterface;
$cachePool = new FilesystemTagAwareAdapter();
$value = $cachePool->get('foo_product_details', function (ItemInterface $item) {
$item->tag('foo');
return 'Hello World!';
});
$value = $cachePool->get('foo_product_categories', function (ItemInterface $item) {
$item->tag('foo');
return array('Category One', 'Category Two');
});
$value = $cachePool->get('foo_product_variations', function (ItemInterface $item) {
$item->tag('foo');
return array('Product Variation One', 'Product Variation Two');
});
$cachePool->invalidateTags(['foo']);
需要注意的是,当我们想要将标签附加到缓存项时,我们需要使用标签感知缓存适配器。 因此,我们使用了 FilesystemTagAwareAdapter
适配器,它是 FilesystemAdapter
适配器的标签感知版本。
接下来,我们需要使用 tag
方法将标签附加到缓存项。 最后,我们可以使用适配器类的 invalidateTags
方法删除与特定缓存标签关联的缓存条目。
这就是我们可以在项目中使用缓存接口进行缓存管理的方式。
总结
今天,我们简要了解了 Symfony 缓存组件,它允许我们在 PHP 应用程序中设置缓存。 它还支持各种缓存适配器,它们共同使我们可以灵活地选择要使用的后端类型。