默认情况下,Kohana的ORM在识别已加载的对象时并不像我想的那么聪明。它保存通过关系加载的对象,例如:
$obj = $foo->bar; // hits the DB for bar
/* ... Later ... */
$obj = $foo->bar; // had bar preloaded, so uses that instead
但是,如果找到bar
的方法不止一种,那就不会发现它。假设foo
和thing
(我们需要更多元语法变量)与同一bar
有关系:
$obj = $foo->bar; // hits DB
$obj = $thing->bar // hits DB again, even though it's the same object
我试图通过模型和id键入预加载的对象数组来解决这个问题。它有效,但问题是它只有在我提前知道ID时才有效。我重载的ORM函数如下所示:
public function find($id = NULL)
{
$model = strtolower(get_class($this));
if ($id != NULL) // notice I don't have to hit the db if it's preloaded.
{
$key = $model . '_' . $id;
if (array_key_exists($key, self::$preloaded)) return self::$preloaded[$key];
}
$obj = parent::find($id);
$key = $model . '_' . $obj->pk();
// here, I have to hit the DB even if it was preloaded, just to find the ID!
if (array_key_exists($key, self::$preloaded)) return self::$preloaded[$key];
self::$preloaded[$key] = $obj;
return $obj;
}
这样做的目的是,如果我在两个不同的地方访问同一个对象,并且它们有可能是同一个对象,那么它不会错误地半更新两个不同的实例,而是正确更新一个预先加载的实例实例
在我通过主键之外的其他东西找到对象的情况下,上述find方法不必要地命中DB。有什么我可以做的,以防止这种情况,而不是按照每个可以想象的标准键入预加载的对象?这里的核心问题看起来非常基本,我很惊讶它不是原始ORM库的一部分。有没有理由,或者我忽略了什么?大多数人做了什么来解决这个问题或绕过它?无论解决方案是什么,当我将memcache集成到我的代码中时,我将进一步应用它,因此可能有助于牢记这一点。
答案 0 :(得分:1)
在config/database.php
中启用每请求数据库缓存('缓存'参数,默认情况下为FALSE)。这将允许您对相同的查询使用缓存结果。