I've read several guides on implementing a php cache system (my site is custom coded, fairly query heavy and growing) including this one: http://www.snipe.net/2009/03/quick-and-dirty-php-caching/
我已经阅读了几个关于实现php缓存系统的指南(我的网站是自定义编码,相当严重且查询量很大),包括以下内容:http://www.snipe.net/2009/03/quick-and-dirty-php -caching /
I understand them fully but there are certain parts of the page that I can't cache, what's the best way to go about doing that?
我完全理解它们,但页面的某些部分我无法缓存,最好的方法是什么?
4 个解决方案
#1
caching is useful if you do a lot of reads but seldom update. the more often the data in the database changes, the more problematic a caching system becomes. caching does add a certain complexity to your codebase, which can be a pain to handle. and it can even slow your site down in the worst case.
如果您执行大量读取但很少更新,则缓存很有用。数据库中的数据越频繁,缓存系统就越成问题。缓存确实会给代码库增加一定的复杂性,这可能很难处理。它甚至可以在最糟糕的情况下减慢你的网站速度。
the most important question is:
when do you have to invalidate your cache? when does it become stale? in most of the cases, if the database-query returns different rows than at the time you cached that page. but how do you know that? you don't (maybe there is a way, but i can't think of any atm), because to check that, you probably have to query the result to compare.
最重要的问题是:什么时候必须使缓存无效?什么时候变得陈旧?在大多数情况下,如果数据库查询返回的行数与缓存该页面时的行数不同。但你怎么知道的?你没有(也许有办法,但我想不出任何atm),因为要检查一下,你可能要查询结果进行比较。
what you can do:
你可以做什么:
-
clear all your cache everytime the relevant parts of the database are updated
this is indeed possible if your database only rarely gets updated - hourly, daily, weekly. but it's useless if changes are coming in continually. that's the case with most web projects.每次更新数据库的相关部分时清除所有缓存,如果您的数据库很少得到更新(每小时,每天,每周),这确实是可能的。但如果不断变化,它就没用了。大多数网络项目就是这种情况。
-
clear cached items after something happens
this only works if changes do not have to be reflected instantly (e.g. doesn't matter if there's incorrect data for some time). in this case you simply could clear the cache for a certain item if it's older than X minutes, or more than Y pageviews happened.事情发生后清除缓存的项目只有在不必立即反映更改时才有效(例如,如果一段时间内数据不正确则无关紧要)。在这种情况下,如果某个项目超过X分钟,或者超过Y页面浏览量,您只需清除某个项目的缓存即可。
-
clear only the relevant pieces
here you have to figure out which parts of the cache are affected when you're updating the database. if done right, changes are reflected instantly while performance improves.只清除这里的相关部分,您必须确定在更新数据库时哪些部分的缓存会受到影响。如果做得好,则在性能提高时立即反映变化。
most likley is option 3: you have to find out. so, as an example, lets take the classic case of a weblog, consisting of a frontpage, archive pages and a detail-page for every entry.
最喜欢的是选项3:你必须找出答案。因此,作为一个例子,让我们采用博客的经典案例,包括首页,存档页面和每个条目的详细页面。
changes are introduced by: the admin-panel (crud for entries) and comments
更改由以下内容引入:管理面板(条目的crud)和注释
if an entry gets edited or deleted, you have to clear the cache for:
如果编辑或删除条目,则必须清除缓存:
- frontpage, if the entry was new
- the relevant archive page, if the entry was old
- the detail-page for the entry
首页,如果条目是新的
相关的存档页面,如果条目是旧的
条目的详细信息页面
if someone commentes you just have to clear the detail-page, but only if the number of comments is not displayed in the index or archive. otherwise, same as entry-crud.
如果有人推荐您只需要清除详细信息页面,但前提是注释或存档中没有显示注释数量。否则,与入口 - crud相同。
if something sitewide is changed, the whole cache has to be cleared (bad!)
如果站点范围内的某些内容发生了变化,则必须清除整个缓存(不好!)
now, lets think about entry-crud and the archive. if the archive is of the type "one page per month", then clear the month the entry belongs to. but if the archive is kind of entry 1-10, 11-20, 21-30, ... most likley the whole archive-cache has to be rebuild.
现在,让我们考虑一下入口和存档。如果存档的类型为“每月一页”,则清除该条目所属的月份。但是如果存档是1-10,11-20,21-30的条目,那么最重要的是整个存档缓存必须重建。
and so on ...
等等 ...
some of the problems:
一些问题:
-
if you don't identify all the affected pieces correctly, it can lead to stale data and/or (un-)dead links.
如果您没有正确识别所有受影响的部分,则可能导致陈旧数据和/或(非)死链接。
-
if updates happen too often, building the cache is additional work, because when the next pageview happens, the cache is most probably stale again and has to be rebuild anyway.
如果更新经常发生,那么构建缓存是额外的工作,因为当下一个页面视图发生时,缓存很可能再次失效并且无论如何都必须重建。
-
some parts of the page are unfit for caching, e.g. the (custom) search function. if the cache works elsewhere everything is fast and great, but searching is still awfully slow.
页面的某些部分不适合缓存,例如(自定义)搜索功能。如果缓存在其他地方工作,一切都很快很好,但搜索速度仍然非常慢。
-
it can be problematic if you have to clear the whole cache while lots of requests are happening. it then can choke your server, because a cache-miss is normally more expensive than if the page's not cached in the first place. even worse, if 3 request are coming in, and the first request can't cache the page before the other two are handled, the cache gets requested 3 times instead of once.
如果在发生大量请求时必须清除整个缓存,则可能会出现问题。然后它可以阻塞你的服务器,因为缓存缺失通常比首先没有缓存页面更昂贵。更糟糕的是,如果有3个请求进入,并且第一个请求在处理其他两个请求之前无法缓存页面,则缓存会被请求3次而不是一次。
my advice:
-
optimize your database. keys and config ok? maybe it works without caching.
优化您的数据库。键和配置好吗?也许没有缓存就可以了。
-
optimize your queries. "explain select"!
优化您的查询。 “解释选择”!
-
only cache parts of the page - the expensive ones. fill in small, cheap changes with str_replace and placeholders
只缓存页面的部分 - 昂贵的。使用str_replace和占位符填写小的,廉价的更改
-
if everything works, use apc or memcached instead of files (files usually work great, but apc/memc are faster). you can also use your database to cache your database, often that works great!
如果一切正常,请使用apc或memcached而不是文件(文件通常效果很好,但apc / memc更快)。您也可以使用您的数据库来缓存您的数据库,这通常很有用!
-
are you building a lazy or an eager caching system? lazy means: build the cache when the page's first requested, eager means: right after the update.
你在建立一个懒惰或急切的缓存系统?懒惰意味着:在页面首次请求时构建缓存,急切意味着:在更新后立即执行。
meh, i don't have any real advice for you. depends too much on the problem :)
嗯,我对你没有任何真正的建议。过分依赖于问题:)
update
theres a request for the blog-entry with key 256. it shows the blog-entry, the comments and who is currently logged in. it's expensive to query the entry and the comments, and format all the text and everything. the currently logged in user resides in the session.
这是一个带有密钥256的博客条目请求。它显示了博客条目,评论以及当前登录的人。查询条目和评论以及格式化所有文本和所有内容都很昂贵。当前登录的用户驻留在会话中。
first, create a unique key for the part you want to cache. in this case, the cache-key probably is the database id of the entry (with some prefix and postfix).
首先,为要缓存的部分创建唯一键。在这种情况下,缓存键可能是条目的数据库ID(带有一些前缀和后缀)。
so, the cached file should have the name cache/blogentry_256.tmp
. check, if that file exists.
因此,缓存的文件应该具有名称cache / blogentry_256.tmp。检查,如果该文件存在。
-
if it doesn't exist, do all the expensive querying and formatting, leave a placeholder (e.g. {username}) where the name of the current user should be and save the result to
cache/blogentry_256.tmp
. be careful not to write any data into this file that shouldn't be displayed for everyone or changes on every request.如果它不存在,请执行所有昂贵的查询和格式化,留下占位符(例如{username}),其中当前用户的名称应该是,并将结果保存到cache / blogentry_256.tmp。注意不要将任何数据写入此文件,不应为每个人显示或每次请求都要更改。
-
now, read the file (or reuse the data from 1) and str_replace the username into the placeholder.
echo
the result.现在,读取文件(或重用1中的数据)并将用户名str_replace到占位符中。回应结果。
if an entry gets changed or someone comments, you have to delete the cache-file with the entries id.
如果条目被更改或有人注释,则必须删除带有条目id的缓存文件。
this is lazy caching - the cache is built only if the user request the page. be careful - if a user types {username} into a comment, it's inserted there too! that means, you have to escape your cached data and unescape it after str_replacing. this technique works with memcached or apc too.
这是惰性缓存 - 仅当用户请求页面时才构建缓存。小心 - 如果用户在注释中键入{username},它也会插入到那里!这意味着,您必须在str_replacing之后转义缓存的数据并对其进行转换。这种技术也适用于memcached或apc。
problems: you have to build your design around that caching desicion. e.g. if you want to display "comment posted 5 minutes ago" instead of "commented added May 6th, 3:42pm", then you're in trouble.
问题:你必须围绕缓存设计构建你的设计。例如如果你想显示“5分钟前发布的评论”而不是“5月6日下午3:42添加评论”,那么你就麻烦了。
#2
Why can't you cache them? If it's because they change very rapidly, then you're probably better off trying to reduce the retrieval and rendering overhead.
为什么你不能缓存它们?如果是因为它们变化非常快,那么你最好不要试图减少检索和渲染开销。
If the contents vary according to the user, then you can offer up different cached versions per user. If you're using an object cache, for example, then include the user's identifier or some other unique value in the cache key. If you're using a more generic, HTTP-level cache such as Squid, then you can set the Vary
header to, e.g. Vary: Cookie
, which will cause the proxy to double-check who it's serving content to.
如果内容因用户而异,则可以为每个用户提供不同的缓存版本。例如,如果您正在使用对象缓存,则在缓存键中包含用户的标识符或其他一些唯一值。如果您正在使用更通用的HTTP级缓存,例如Squid,那么您可以将Vary标头设置为,例如变化:Cookie,它将导致代理重复检查它为哪些内容提供服务。
You should still instruct caches and proxies not to store any sensitive information in public caches.
您仍应指示缓存和代理不要将任何敏感信息存储在公共缓存中。
#3
Remember that caching isn't a single solution - Your application can have caching on different levels, depending on the scope of variables. Within a single request you may have an identity-map to prevent additional queries for the same data. You can use memcached to cache data across requests. The database itself has a query cache, as well as other types of lower-level caches. Your rendering engine can also cache at different levels - The whole page, individual parts of the page etc. You need to figure out what you can cache and make a strategy for that.
请记住,缓存不是一个单一的解决方案 - 您的应用程序可以在不同的级别上进行缓存,具体取决于变量的范围。在单个请求中,您可能具有标识映射以防止对相同数据的其他查询。您可以使用memcached在请求之间缓存数据。数据库本身具有查询缓存以及其他类型的低级缓存。您的渲染引擎也可以在不同级别进行缓存 - 整个页面,页面的各个部分等。您需要弄清楚可以缓存的内容并为此制定策略。
Also, as with all optimisation, make sure that you measure before you tweak anything. This will ensure that 1) you actually improve things, rather than making them worse and 2) You focus on the stuff that matters, rather than everything else.
此外,与所有优化一样,请确保在调整任何内容之前进行测量。这将确保1)你实际上改善了事情,而不是让事情变得更糟; 2)你专注于重要的事情,而不是其他一切。
#4
Here's my tip: create either an object or function that lets you cache a "section" based upon its name. This way you can cache part of your page, and include the rendering section within an if block. What I did was hash the incoming text and used that as the filename within './cache'
, and returned the boolean value of whether or not regeneration is needed; you will obviously need output buffering for this.
这是我的提示:创建一个对象或函数,让您根据其名称缓存“部分”。这样,您可以缓存部分页面,并在if块中包含渲染部分。我所做的是对输入文本进行散列并将其用作'./cache'中的文件名,并返回布尔值,即是否需要重新生成;你显然需要输出缓冲。
This would give you a cache framework of,
这会给你一个缓存框架,
if(Cache::cached('index-recent-articles', 5 /* minutes */)) {
Cache::start();
echo 'stuff here';
Cache::stop('index-recent-articles');
} // And if Cache::cached could echo the cached HTML when the result is false...
// then this is a tidy else-less bit of code.
I don't know if this is optimal, a server-based solution like memcache would be better, but the concept should help you. Obviously how you manage the cache, whether by files or by database or extension, is up to you.
我不知道这是否是最优的,像memcache这样的基于服务器的解决方案会更好,但这个概念应该对你有帮助。显然,无论是通过文件还是通过数据库或扩展,您如何管理缓存都取决于您。
Edit:
If you wish for file-based caching then a system this simple may be all you need. Obviously I haven't tested it in your shoes, and this is mostly just pulled from the back of my head, but as it stands this is a decent start for what you may desire.
如果您希望进行基于文件的缓存,那么这个简单的系统可能就是您所需要的。显然我还没有在你的鞋子上测试它,这大部分只是从我的后脑中拉出来的,但是就目前而言,这对于你可能想要的东西来说是一个不错的开始。
abstract class Cache {
const path = 'cache/';
static function start() { ob_start(); }
static function end($id, $text = null) {
$filename = sprintf('%s%u', Cache::path, crc32($id));
file_put_contents($filename, $text === null ? ob_get_clean() : $text);
}
static function cached($id, $minutes = 5) {
$filename = sprintf('%s%u', Cache::path, crc32($id));
$time = $minutes * 60;
if(time() - filemtime($filename) > $time) {
return true;
} else {
echo file_get_contents($filename);
return false;
}
}
}
#1
caching is useful if you do a lot of reads but seldom update. the more often the data in the database changes, the more problematic a caching system becomes. caching does add a certain complexity to your codebase, which can be a pain to handle. and it can even slow your site down in the worst case.
如果您执行大量读取但很少更新,则缓存很有用。数据库中的数据越频繁,缓存系统就越成问题。缓存确实会给代码库增加一定的复杂性,这可能很难处理。它甚至可以在最糟糕的情况下减慢你的网站速度。
the most important question is:
when do you have to invalidate your cache? when does it become stale? in most of the cases, if the database-query returns different rows than at the time you cached that page. but how do you know that? you don't (maybe there is a way, but i can't think of any atm), because to check that, you probably have to query the result to compare.
最重要的问题是:什么时候必须使缓存无效?什么时候变得陈旧?在大多数情况下,如果数据库查询返回的行数与缓存该页面时的行数不同。但你怎么知道的?你没有(也许有办法,但我想不出任何atm),因为要检查一下,你可能要查询结果进行比较。
what you can do:
你可以做什么:
-
clear all your cache everytime the relevant parts of the database are updated
this is indeed possible if your database only rarely gets updated - hourly, daily, weekly. but it's useless if changes are coming in continually. that's the case with most web projects.每次更新数据库的相关部分时清除所有缓存,如果您的数据库很少得到更新(每小时,每天,每周),这确实是可能的。但如果不断变化,它就没用了。大多数网络项目就是这种情况。
-
clear cached items after something happens
this only works if changes do not have to be reflected instantly (e.g. doesn't matter if there's incorrect data for some time). in this case you simply could clear the cache for a certain item if it's older than X minutes, or more than Y pageviews happened.事情发生后清除缓存的项目只有在不必立即反映更改时才有效(例如,如果一段时间内数据不正确则无关紧要)。在这种情况下,如果某个项目超过X分钟,或者超过Y页面浏览量,您只需清除某个项目的缓存即可。
-
clear only the relevant pieces
here you have to figure out which parts of the cache are affected when you're updating the database. if done right, changes are reflected instantly while performance improves.只清除这里的相关部分,您必须确定在更新数据库时哪些部分的缓存会受到影响。如果做得好,则在性能提高时立即反映变化。
most likley is option 3: you have to find out. so, as an example, lets take the classic case of a weblog, consisting of a frontpage, archive pages and a detail-page for every entry.
最喜欢的是选项3:你必须找出答案。因此,作为一个例子,让我们采用博客的经典案例,包括首页,存档页面和每个条目的详细页面。
changes are introduced by: the admin-panel (crud for entries) and comments
更改由以下内容引入:管理面板(条目的crud)和注释
if an entry gets edited or deleted, you have to clear the cache for:
如果编辑或删除条目,则必须清除缓存:
- frontpage, if the entry was new
- the relevant archive page, if the entry was old
- the detail-page for the entry
首页,如果条目是新的
相关的存档页面,如果条目是旧的
条目的详细信息页面
if someone commentes you just have to clear the detail-page, but only if the number of comments is not displayed in the index or archive. otherwise, same as entry-crud.
如果有人推荐您只需要清除详细信息页面,但前提是注释或存档中没有显示注释数量。否则,与入口 - crud相同。
if something sitewide is changed, the whole cache has to be cleared (bad!)
如果站点范围内的某些内容发生了变化,则必须清除整个缓存(不好!)
now, lets think about entry-crud and the archive. if the archive is of the type "one page per month", then clear the month the entry belongs to. but if the archive is kind of entry 1-10, 11-20, 21-30, ... most likley the whole archive-cache has to be rebuild.
现在,让我们考虑一下入口和存档。如果存档的类型为“每月一页”,则清除该条目所属的月份。但是如果存档是1-10,11-20,21-30的条目,那么最重要的是整个存档缓存必须重建。
and so on ...
等等 ...
some of the problems:
一些问题:
-
if you don't identify all the affected pieces correctly, it can lead to stale data and/or (un-)dead links.
如果您没有正确识别所有受影响的部分,则可能导致陈旧数据和/或(非)死链接。
-
if updates happen too often, building the cache is additional work, because when the next pageview happens, the cache is most probably stale again and has to be rebuild anyway.
如果更新经常发生,那么构建缓存是额外的工作,因为当下一个页面视图发生时,缓存很可能再次失效并且无论如何都必须重建。
-
some parts of the page are unfit for caching, e.g. the (custom) search function. if the cache works elsewhere everything is fast and great, but searching is still awfully slow.
页面的某些部分不适合缓存,例如(自定义)搜索功能。如果缓存在其他地方工作,一切都很快很好,但搜索速度仍然非常慢。
-
it can be problematic if you have to clear the whole cache while lots of requests are happening. it then can choke your server, because a cache-miss is normally more expensive than if the page's not cached in the first place. even worse, if 3 request are coming in, and the first request can't cache the page before the other two are handled, the cache gets requested 3 times instead of once.
如果在发生大量请求时必须清除整个缓存,则可能会出现问题。然后它可以阻塞你的服务器,因为缓存缺失通常比首先没有缓存页面更昂贵。更糟糕的是,如果有3个请求进入,并且第一个请求在处理其他两个请求之前无法缓存页面,则缓存会被请求3次而不是一次。
my advice:
-
optimize your database. keys and config ok? maybe it works without caching.
优化您的数据库。键和配置好吗?也许没有缓存就可以了。
-
optimize your queries. "explain select"!
优化您的查询。 “解释选择”!
-
only cache parts of the page - the expensive ones. fill in small, cheap changes with str_replace and placeholders
只缓存页面的部分 - 昂贵的。使用str_replace和占位符填写小的,廉价的更改
-
if everything works, use apc or memcached instead of files (files usually work great, but apc/memc are faster). you can also use your database to cache your database, often that works great!
如果一切正常,请使用apc或memcached而不是文件(文件通常效果很好,但apc / memc更快)。您也可以使用您的数据库来缓存您的数据库,这通常很有用!
-
are you building a lazy or an eager caching system? lazy means: build the cache when the page's first requested, eager means: right after the update.
你在建立一个懒惰或急切的缓存系统?懒惰意味着:在页面首次请求时构建缓存,急切意味着:在更新后立即执行。
meh, i don't have any real advice for you. depends too much on the problem :)
嗯,我对你没有任何真正的建议。过分依赖于问题:)
update
theres a request for the blog-entry with key 256. it shows the blog-entry, the comments and who is currently logged in. it's expensive to query the entry and the comments, and format all the text and everything. the currently logged in user resides in the session.
这是一个带有密钥256的博客条目请求。它显示了博客条目,评论以及当前登录的人。查询条目和评论以及格式化所有文本和所有内容都很昂贵。当前登录的用户驻留在会话中。
first, create a unique key for the part you want to cache. in this case, the cache-key probably is the database id of the entry (with some prefix and postfix).
首先,为要缓存的部分创建唯一键。在这种情况下,缓存键可能是条目的数据库ID(带有一些前缀和后缀)。
so, the cached file should have the name cache/blogentry_256.tmp
. check, if that file exists.
因此,缓存的文件应该具有名称cache / blogentry_256.tmp。检查,如果该文件存在。
-
if it doesn't exist, do all the expensive querying and formatting, leave a placeholder (e.g. {username}) where the name of the current user should be and save the result to
cache/blogentry_256.tmp
. be careful not to write any data into this file that shouldn't be displayed for everyone or changes on every request.如果它不存在,请执行所有昂贵的查询和格式化,留下占位符(例如{username}),其中当前用户的名称应该是,并将结果保存到cache / blogentry_256.tmp。注意不要将任何数据写入此文件,不应为每个人显示或每次请求都要更改。
-
now, read the file (or reuse the data from 1) and str_replace the username into the placeholder.
echo
the result.现在,读取文件(或重用1中的数据)并将用户名str_replace到占位符中。回应结果。
if an entry gets changed or someone comments, you have to delete the cache-file with the entries id.
如果条目被更改或有人注释,则必须删除带有条目id的缓存文件。
this is lazy caching - the cache is built only if the user request the page. be careful - if a user types {username} into a comment, it's inserted there too! that means, you have to escape your cached data and unescape it after str_replacing. this technique works with memcached or apc too.
这是惰性缓存 - 仅当用户请求页面时才构建缓存。小心 - 如果用户在注释中键入{username},它也会插入到那里!这意味着,您必须在str_replacing之后转义缓存的数据并对其进行转换。这种技术也适用于memcached或apc。
problems: you have to build your design around that caching desicion. e.g. if you want to display "comment posted 5 minutes ago" instead of "commented added May 6th, 3:42pm", then you're in trouble.
问题:你必须围绕缓存设计构建你的设计。例如如果你想显示“5分钟前发布的评论”而不是“5月6日下午3:42添加评论”,那么你就麻烦了。
#2
Why can't you cache them? If it's because they change very rapidly, then you're probably better off trying to reduce the retrieval and rendering overhead.
为什么你不能缓存它们?如果是因为它们变化非常快,那么你最好不要试图减少检索和渲染开销。
If the contents vary according to the user, then you can offer up different cached versions per user. If you're using an object cache, for example, then include the user's identifier or some other unique value in the cache key. If you're using a more generic, HTTP-level cache such as Squid, then you can set the Vary
header to, e.g. Vary: Cookie
, which will cause the proxy to double-check who it's serving content to.
如果内容因用户而异,则可以为每个用户提供不同的缓存版本。例如,如果您正在使用对象缓存,则在缓存键中包含用户的标识符或其他一些唯一值。如果您正在使用更通用的HTTP级缓存,例如Squid,那么您可以将Vary标头设置为,例如变化:Cookie,它将导致代理重复检查它为哪些内容提供服务。
You should still instruct caches and proxies not to store any sensitive information in public caches.
您仍应指示缓存和代理不要将任何敏感信息存储在公共缓存中。
#3
Remember that caching isn't a single solution - Your application can have caching on different levels, depending on the scope of variables. Within a single request you may have an identity-map to prevent additional queries for the same data. You can use memcached to cache data across requests. The database itself has a query cache, as well as other types of lower-level caches. Your rendering engine can also cache at different levels - The whole page, individual parts of the page etc. You need to figure out what you can cache and make a strategy for that.
请记住,缓存不是一个单一的解决方案 - 您的应用程序可以在不同的级别上进行缓存,具体取决于变量的范围。在单个请求中,您可能具有标识映射以防止对相同数据的其他查询。您可以使用memcached在请求之间缓存数据。数据库本身具有查询缓存以及其他类型的低级缓存。您的渲染引擎也可以在不同级别进行缓存 - 整个页面,页面的各个部分等。您需要弄清楚可以缓存的内容并为此制定策略。
Also, as with all optimisation, make sure that you measure before you tweak anything. This will ensure that 1) you actually improve things, rather than making them worse and 2) You focus on the stuff that matters, rather than everything else.
此外,与所有优化一样,请确保在调整任何内容之前进行测量。这将确保1)你实际上改善了事情,而不是让事情变得更糟; 2)你专注于重要的事情,而不是其他一切。
#4
Here's my tip: create either an object or function that lets you cache a "section" based upon its name. This way you can cache part of your page, and include the rendering section within an if block. What I did was hash the incoming text and used that as the filename within './cache'
, and returned the boolean value of whether or not regeneration is needed; you will obviously need output buffering for this.
这是我的提示:创建一个对象或函数,让您根据其名称缓存“部分”。这样,您可以缓存部分页面,并在if块中包含渲染部分。我所做的是对输入文本进行散列并将其用作'./cache'中的文件名,并返回布尔值,即是否需要重新生成;你显然需要输出缓冲。
This would give you a cache framework of,
这会给你一个缓存框架,
if(Cache::cached('index-recent-articles', 5 /* minutes */)) {
Cache::start();
echo 'stuff here';
Cache::stop('index-recent-articles');
} // And if Cache::cached could echo the cached HTML when the result is false...
// then this is a tidy else-less bit of code.
I don't know if this is optimal, a server-based solution like memcache would be better, but the concept should help you. Obviously how you manage the cache, whether by files or by database or extension, is up to you.
我不知道这是否是最优的,像memcache这样的基于服务器的解决方案会更好,但这个概念应该对你有帮助。显然,无论是通过文件还是通过数据库或扩展,您如何管理缓存都取决于您。
Edit:
If you wish for file-based caching then a system this simple may be all you need. Obviously I haven't tested it in your shoes, and this is mostly just pulled from the back of my head, but as it stands this is a decent start for what you may desire.
如果您希望进行基于文件的缓存,那么这个简单的系统可能就是您所需要的。显然我还没有在你的鞋子上测试它,这大部分只是从我的后脑中拉出来的,但是就目前而言,这对于你可能想要的东西来说是一个不错的开始。
abstract class Cache {
const path = 'cache/';
static function start() { ob_start(); }
static function end($id, $text = null) {
$filename = sprintf('%s%u', Cache::path, crc32($id));
file_put_contents($filename, $text === null ? ob_get_clean() : $text);
}
static function cached($id, $minutes = 5) {
$filename = sprintf('%s%u', Cache::path, crc32($id));
$time = $minutes * 60;
if(time() - filemtime($filename) > $time) {
return true;
} else {
echo file_get_contents($filename);
return false;
}
}
}