今天,我将向你展示Symfony Cache组件,这是一种向你的PHP应用添加缓存的简单方法。这有助于通过减少页面加载时间来提高应用程序的整体性能。
Symfony Cache组件
Symfony Cache组件允许你在你的PHP应用程序中设置缓存。该组件本身非常容易安装和配置,可以让你快速上手。另外,它还提供了多种适配器供你选择,如下面的列表所示:
- 数据库适配器
- 文件系统适配器
- memcached适配器
- Redis适配器
- APCu适配器
- 以及更多
说到使用Symfony Cache组件进行缓存,有几个术语你应该熟悉一下。Symfony Cache组件允许你在两种不同的缓存方式中进行选择。
PSR-6 缓存
这是一个通用的缓存系统,围绕着缓存池和缓存项。
首先,缓存项目指的是被存储的内容。每个项目都以一个键值对的形式存储。缓存项目由缓存池管理,它对它们进行逻辑分组。事实上,你需要使用缓存池来操作缓存值。
最后,是缓存适配器做所有繁重的工作,将项目存储在缓存后端。
缓存合约
这是一种简单但更强大的方式,基于重新计算的回调来缓存值。它也有内置的Stampede预防功能。这也是推荐的方式,因为与PSR-6缓存相比,它需要更少的代码。
在这篇文章中,我们将探讨这两种方式,了解如何释放Symfony Cache组件的力量。像往常一样,我们将从安装和配置开始,然后在文章的后半部分,我们将继续探讨一些实际的例子。
安装和配置
在本节中,我们将安装Cache组件。我假设你已经在你的系统中安装了Composer--你需要它来安装Packagist上的Cache组件。
一旦你安装了Composer,继续使用以下命令安装Cache组件:
$composer require symfony/cache
这应该会创建一个composer.json文件,它看起来应该是这样的:
{
"require": {
"symfony/cache": "^4.1"
}
}
安装完毕,但你该如何把它添加到你的应用程序中呢?这只是一个问题,包括Composer在你的应用程序中创建的autoload.php文件,如下面的片段所示:
<?php
require_once './vendor/autoload.php';
// application code
?>
PSR-6 缓存:一个现实世界的例子
在这一节中,我们将通过一个例子来说明你如何在你的应用程序中使用Cache组件,用PSR-6缓存方法来缓存内容。
首先,让我们继续创建index.php文件,内容如下:
<?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组件,在Cache Contracts的帮助下缓存内容。
首先,让我们继续创建cache_contracts.php文件,内容如下:
<?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!';
});
首先,你需要初始化缓存池实例。现在,我们可以在Cache Contracts的帮助下使用这个对象来设置缓存值。正如你所看到的,第一个参数是一个cache key,第二个参数是一个PHP callable,只有在cache pool中没有找到key时才会执行。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 方法来设置过期日期。
用缓存标签使缓存项目失效
当你创建缓存项目时,你可以给它们附加一个标签。所以这就像把逻辑上分组的缓存项目放在同一个标签下。当您想删除所有相互关联的缓存项目,而又不想按键删除它们时,这真的很有用。
让我们快速看一下下面的片段:
<?php
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 方法来删除与特定缓存标签相关的缓存条目。
所以这就是你如何在你的项目中使用Cache Contracts进行缓存管理。
总结
今天,我们简单了解了一下Symfony Cache组件,它允许你在你的PHP应用程序中设置缓存。它还支持各种缓存适配器,这些适配器可以让你灵活地选择你想使用的后端类型。