Phalcon 提供的缓存组件由前端 Phalcon\Cache\FrontendInterface 和后端 Phalcon\Cache\BackendInterface 组件组成,可以更快地接入获取使用频繁或者已经被处理的数据。
前端组件如输入源或者接口,后端组件则为这个类提供了存储的选项。
尽管这个组件运行非常快速,但如果不加考虑就使用它会适得其反,特别在不需要或者不适宜使用缓存时。 我们建议你在使用缓存前核对一下场景:
温馨提示 即使使用了这些缓存,你仍然应该定期检测缓存的命中率。 通过后台提供的相关工具,这一点很容易做得到,特别是使用Memcached或者APC时。
缓存流程可以分为两部分:
输出片段是指一小块缓存和返回都一样的HTML或者文本内容。输出的内容应该是能自动 被 ob_* 函数捕获或者直接是PHP输出,这样才能缓存起来。以下实例演示了这样的使用。 它接收PHP生成的页面输出并保存在一个文件里面。缓存文件的内容每隔172800秒(2天)刷新一次。
使用这个缓存机制,无论何时调用这块代码,我们都可以通过避免重复执行辅助插件 Phalcon\Tag::linkTo()
从而获得更高的性能。
<?php
use Phalcon\Tag;
use Phalcon\Cache\Backend\File as BackFile;
use Phalcon\Cache\Frontend\Output as FrontOutput;
// Create an Output frontend. Cache the files for 2 days
$frontCache = new FrontOutput(
array(
"lifetime" => 172800
)
);
// Create the component that will cache from the "Output" to a "File" backend
// Set the cache file directory - it's important to keep the "/" at the end of
// the value for the folder
$cache = new BackFile(
$frontCache,
array(
"cacheDir" => "../app/cache/"
)
);
// Get/Set the cache file to ../app/cache/my-cache.html
$content = $cache->start("my-cache.html");
// If $content is null then the content will be generated for the cache
if ($content === null) {
// Print date and time
echo date("r");
// Generate a link to the sign-up action
echo Tag::linkTo(
array(
"user/signup",
"Sign Up",
"class" => "signup-button"
)
);
// Store the output into the cache file
$cache->save();
} else {
// Echo the cached output
echo $content;
}
温馨提示 在上面的实例中,我们的代码维持不变,即输出给用户的内容和之前展示的内容是一样的。我们的缓存组件 以透明的方式捕获了页面输出并保存在缓存文件(当缓存生成时)或者在早期的一次调用时将它发送回用户预编译,故而可以避免高昂的操作。
仅仅是缓存数据,对于你的应用来说也是同等重要的。缓存通过重用常用的(非更新的)数据可以减少数据库的加载, 从而加速你的应用。
其中一个缓存适配器是文件’File’。文件适配器的配置中只需要一个key:指明缓存文件存放的目录位置。 这个配置通过cacheDir选项控制,必须,且要以反斜杠结尾。
<?php
use Phalcon\Cache\Backend\File as BackFile;
use Phalcon\Cache\Frontend\Data as FrontData;
// Cache the files for 2 days using a Data frontend
$frontCache = new FrontData(
array(
"lifetime" => 172800
)
);
// Create the component that will cache "Data" to a "File" backend
// Set the cache file directory - important to keep the "/" at the end of
// of the value for the folder
$cache = new BackFile(
$frontCache,
array(
"cacheDir" => "../app/cache/"
)
);
// Try to get cached records
$cacheKey = 'robots_order_id.cache';
$robots = $cache->get($cacheKey);
if ($robots === null) {
// $robots is null because of cache expiration or data does not exist
// Make the database call and populate the variable
$robots = Robots::find(
array(
"order" => "id"
)
);
// Store it in the cache
$cache->save($cacheKey, $robots);
}
// Use $robots :)
foreach ($robots as $robot) {
echo $robot->name, "\n";
}
当我们改用Memcached作为后端存储器时,上面的实例改动很轻微(特别就配置而言)。
<?php
use Phalcon\Cache\Frontend\Data as FrontData;
use Phalcon\Cache\Backend\Memcached as BackMemCached;
// Cache data for one hour
$frontCache = new FrontData(
array(
"lifetime" => 3600
)
);
// Create the component that will cache "Data" to a "Memcached" backend
// Memcached connection settings
$cache = new BackMemCached(
$frontCache,
array(
"servers" => array(
array(
"host" => "127.0.0.1",
"port" => "11211",
"weight" => "1"
)
)
)
);
// Try to get cached records
$cacheKey = 'robots_order_id.cache';
$robots = $cache->get($cacheKey);
if ($robots === null) {
// $robots is null because of cache expiration or data does not exist
// Make the database call and populate the variable
$robots = Robots::find(
array(
"order" => "id"
)
);
// Store it in the cache
$cache->save($cacheKey, $robots);
}
// Use $robots :)
foreach ($robots as $robot) {
echo $robot->name, "\n";
}
添加到缓存的元素根据唯一的key进行识别区分。这使用文件缓存作为后端时,key就是实际的文件名。 为了从缓存中获得数据,我们仅仅需要通过唯一的key调用即可。如果key不存在,get方法将会返回null。
<?php
// Retrieve products by key "myProducts"
$products = $cache->get("myProducts");
如果你想知道在缓存中存放了哪些key,你可以调用queryKeys方法:
<?php
// Query all keys used in the cache
$keys = $cache->queryKeys();
foreach ($keys as $key) {
$data = $cache->get($key);
echo "Key=", $key, " Data=", $data;
}
// Query keys in the cache that begins with "my-prefix"
$keys = $cache->queryKeys("my-prefix");
有些时机你需要强制废除一个缓存的实体(如对被缓存的数据进行了更新)。 而仅仅需要做的只是知道对应缓存的数据存放于哪个key即可。
<?php
// Delete an item with a specific key
$cache->delete("someKey");
// Delete all items from the cache
$keys = $cache->queryKeys();
foreach ($keys as $key) {
$cache->delete($key);
}
也有可能需要根据一个给定的key来判断缓存是否存在:
<?php
if ($cache->exists("someKey")) {
echo $cache->get("someKey");
} else {
echo "Cache does not exists!";
}
“有效期”是指缓存可以多久时间(在以秒为单位)内有效。默认情况下,全部被创建的缓存都使用前端构建中设定的有效期。 你可以在创建时指定一个有效期或者在从缓存中获取数据时:
Setting the lifetime when retrieving:
<?php
$cacheKey = 'my.cache';
// Setting the cache when getting a result
$robots = $cache->get($cacheKey, 3600);
if ($robots === null) {
$robots = "some robots";
// Store it in the cache
$cache->save($cacheKey, $robots);
}
在保存时设置有效期:
<?php
$cacheKey = 'my.cache';
$robots = $cache->get($cacheKey);
if ($robots === null) {
$robots = "some robots";
// Setting the cache when saving data
$cache->save($cacheKey, $robots, 3600);
}
缓存组件的特点,就是允许开发人员使用多级缓存。这个新特性非常有用, 因为你可以在多个缓存媒介结合不同的有效期中保存相同的数据,并在有效期内从首个最快的缓存适配器开始读取,直至到最慢的适配器。
<?php
use Phalcon\Cache\Multiple;
use Phalcon\Cache\Backend\Apc as ApcCache;
use Phalcon\Cache\Backend\File as FileCache;
use Phalcon\Cache\Frontend\Data as DataFrontend;
use Phalcon\Cache\Backend\Memcached as MemcachedCache;
$ultraFastFrontend = new DataFrontend(
array(
"lifetime" => 3600
)
);
$fastFrontend = new DataFrontend(
array(
"lifetime" => 86400
)
);
$slowFrontend = new DataFrontend(
array(
"lifetime" => 604800
)
);
// Backends are registered from the fastest to the slower
$cache = new Multiple(
array(
new ApcCache(
$ultraFastFrontend,
array(
"prefix" => 'cache',
)
),
new MemcachedCache(
$fastFrontend,
array(
"prefix" => 'cache',
"host" => "localhost",
"port" => "11211"
)
),
new FileCache(
$slowFrontend,
array(
"prefix" => 'cache',
"cacheDir" => "../app/cache/"
)
)
)
);
// Save, saves in every backend
$cache->save('my-key', $data);
作为缓存的接口或者输入源的前端适配器有:
适配器 | 描述 | 示例 |
---|---|---|
Output | 从标准PHP输出读取输入数据 | Phalcon\Cache\Frontend\Output |
Data | 可用于缓存任何类型的PHP数据(大数组,对象,文本等)。在存入后端前数据将会被序列化。 | Phalcon\Cache\Frontend\Data |
Base64 | 可用于缓存二进制数据。在存入后端前数据会以base64_encode编码进行序列化。 | Phalcon\Cache\Frontend\Base64 |
Json | 在存入后端前数据使用JSON编码。从缓存获取后进行JSON解码。此前端适配器可用于跨语言和跨框架共享数据。 | Phalcon\Cache\Frontend\Json |
IgBinary | 用于缓存任何类型的PHP数据(大数组,对象,文本等)。在存入后端前数据会使用IgBinary进行序列化。 | Phalcon\Cache\Frontend\Igbinary |
None | 用于缓存任何类型的PHP数据而不作任何序列化操作。 | Phalcon\Cache\Frontend\None |
为了创建你自己的前端适配器或者扩展已有的适配器,你必须 实现 Phalcon\Cache\FrontendInterface 接口。
用于存放缓存数据的后端适配器有:
适配器 | 描述 | 信息 | 需要的扩展 | 示例 | |
---|---|---|---|---|
File | 在本地绝对路径的文件上存放数据 | 无 | 无 | Phalcon\Cache\Backend\File |
Lmdb | 使用内存映射文件技术加速速度的读取 | 无 | 无 | Phalcon\Cache\Backend\Lmdb |
Memcached | 在memcached服务器存放数据 | Memcached | memcached extension | Phalcon\Cache\Backend\Memcached |
APC | 在opcode缓存 (APC)中存放数据 | APC | APC extension | Phalcon\Cache\Backend\Apc |
Mongo | 在Mongo数据库中存放数据 | MongoDb | Mongo | Phalcon\Cache\Backend\Mongo |
XCache | 在XCache中存放数据 | XCache | xcache extension | Phalcon\Cache\Backend\Xcache |
Redis | Stores data in Redis | Redis | redis extension | Phalcon\Cache\Backend\Redis |
Yac | Stores data in Yac | Yac | yac extension | Phalcon\Cache\Backend\Yac | |
Memeory | 存储数据在内存中,请求完成后释放 | 无 | 无 | Phalcon\Cache\Backend\Memory |
为了创建你自己的后端适配器或者扩展已有的后端适配器,你必须 实现 Phalcon\Cache\BackendInterface 接口。
此后端存储器把缓存内容存放到本地服务器的文件。对应的选项有:
选项 | 描述 |
---|---|
prefix | 自动追加到缓存key前面的前缀 |
cacheDir | 放置缓存文件且可写入的目录 |
此后端存储器将缓存的内容存放在memcached服务器。对应的选项有:
选项 | 描述 |
---|---|
prefix | 自动追加到缓存key前面的前缀 |
host | memcached 域名 |
port | memcached 端口 |
persistent | 创建一个长连接的memcached连接? |
此后端存储器将缓存内容存放到MongoDB服务器。对应的选项有:
选项 | 描述 |
---|---|
prefix | 自动追加到缓存key前面的前缀 |
uri | MongoDB的连接串 |
db | Mongo数据库名 |
collection | Mongo数据库连接 |
此后端存储器将缓存内容存放到XCache (XCache)。对应的选项有:
选项 | 描述 |
---|---|
prefix | 自动追加到缓存key前面的前缀 |
This backend will store cached content on a Redis server (Redis). The available options for this backend are:
Option | Description |
---|---|
prefix | A prefix that is automatically prepended to the cache keys |
redis | Redis 对象实例,如果设置该项将忽略 host 等选项 |
host | Redis host |
port | Redis port |
auth | Password to authenticate to a password-protected Redis server |
persistent | Create a persistent connection to Redis |
db | The index of the Redis database to use |