您将如何缓存MVC项目中的内容

时间:2012-11-21 16:36:31

标签: php model-view-controller caching

我有一个项目,是几个体育赛事系列的结果数据库。 如您所想,大多数内容大致相同。 我想缓存一些内容来保存数据库查询。

该项目使用PHP构建,并使用自定义MVC。 你会在哪里添加缓存逻辑?

5 个答案:

答案 0 :(得分:2)

使用Memcached。像这样的东西,你在那里缓存查询的结果,并尝试在DB之前从缓存中检索。

编辑:添加了json_encoding数据... json_encode比PHP的数组默认序列化稍快,并且可以被访问数据的其他应用程序使用

默认情况下,Memcached使用FastLZ压缩。

// The ID of the item you're looking for (from $_GET or whatever)
$id = 1;

// Create a memcached instance
$m = new Memcached();
$m->addServer('localhost', 11211);

// Try retrieving the event from memcached
$data = $m->get('event_' . $id);

if ($data) {
    // If you found data in memcached, decode it for use in code
    $data = json_decode($data);
} else {
    // If you didn't find the data in memcached, try retrieving from the DB
    $result = mysqli_query('SELECT * FROM events WHERE id = ' . $id);
    // If you found results in the DB...
    if ($data = mysqli_fetch_assoc($result)) {
        // Save them to memcached for future calls
        // Note: here, I'm using the optional param to expire it after 1 day
        $m->set('event_' . $id, json_encode($data), 86400);
    }
}
// Now you can use your data
var_dump($data);

编辑在代码中添加评论

答案 1 :(得分:2)

有两点可以在MVC和MVC启发的设计模式中使用缓存:输出和数据检索:

缓存输出:

这必须在视图中实现,作为UI逻辑的一部分(视图应该是实例,而不仅仅是哑模板)。某处是视图组合响应中的模板的相同区域。只有在这种情况下,一些“模板”实际上完全没有变量。

通过这种方式,您可以在MVC的上下文中缓存HTML片段..但这不适用于您的特定用例。当与数据源的交互花费太多时间时,它更适合于情况。就像存储实际上是REST API一样。

缓存数据:

要启用此功能,必须在模型层中执行。确切地说:在服务(类/实例中,主要包含域和存储逻辑之间的交互)。

如果你有一个完全实现的模型层,你可以将应用程序,域和存储逻辑分开,那么缓存的实现就会看起来像是不同的存储形式。

$user = new User;
$cache = new UserCacheMapper;

$user->setId( 42 );
if ( ! $cache->fetch( $user ) )
{
    $storage = new UserSQLMapper( $pdo );
    $storage->fetch( $user );

    $cache->store( $user );
}

// the $user object has been initialized
  

对象的初始化实际上应该由服务中的工厂执行,但这是一个简化的例子

这样您就可以在不缓存的情况下创建应用程序,并且稍后通过修改services(负责应用程序逻辑)来添加它。 domain objects(域逻辑)和data mappers(存储逻辑)都不得不改变。

答案 2 :(得分:1)

我会使用memcached来构建使用它的缓存解决方案http://memcached.org/

我通常将缓存逻辑放在控制器中,尽管模型通常可能是更正确的位置,原因是模型使用的上下文会影响缓存策略

将它放在模型中会使缓存策略与其他正确的数据访问功能保持一致,这意味着您可以交换模型,缓存代码随之移动。如果这种情况可能会导致复杂的失效无法放入模型中。

“计算机科学只有两件事:缓存失效和命名事物”Phil Karlton

答案 3 :(得分:1)

可以使用Memcache(d)缓存对象,这对多服务器设置最有用。对于单个服务器,您可以将事物存储在提供缓存功能的APC / Xcache等中。

我会在dataaccess方法中缓存数据。

答案 4 :(得分:1)

您说您正在使用自己的MVC模式框架,因此很难给出具体建议。

您可以缓存一些地方。

如果您正确使用HTTP(idempotency,etags,缓存控制标头等),您可能会将缓存层放在应用程序之外,并使用像varnish这样的转发缓存。缓存整个页面。但是,很容易让HTTP出错,所以这可能不是最佳选择。例如,如果您有用户帐户,并且相同的URL会根据登录的用户生成不同的服务器输出,则无法使用HTTP缓存,因为您的资源依赖于cookie状态。 (您应该做的是将用户放入网址,例如/mysite/{userid}/profile而不是/mysite/profile。)您可能仍然可以通过其更高级的功能使用清漆,但这将更加困难。< / p>

你说你只对缓存数据库查询结果感兴趣,所以我会解决这个问题。

如果您有一些明确定义的查询要缓存数据库响应,则可以将逻辑放在控制器中:在将模型传递给视图之前,请显式缓存它。如果您有多个要缓存的位置,此解决方案会产生混乱的代码库。此外,如果要在不同的控制器中检索相同的数据,则需要仔细并手动确保检索相同模型的所有控制器代码也会查询缓存并使用相同的缓存密钥。显然,打开和关闭缓存也变得很困难。

更清洁的解决方案是以一种透明地缓存结果的方式包装模型。这意味着您可以声明性地添加缓存,而无需对控制器或模型进行实质性更改。但是,这需要一个非常精心设计的模型api,你可能没有。