用Symfony Cache组件在PHP中设置高速缓存(附实例)

641 阅读5分钟

今天,我将向你展示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应用程序中设置缓存。它还支持各种缓存适配器,这些适配器可以让你灵活地选择你想使用的后端类型。