那么,您必须将每个参数的值添加到缓存键中。类似这样的:
public function stmt($sql, $params) {
$cache_key = sha1($sql . serialize($params));
if($result = cache::get($cache_key)) {
return $result;
}
$sth = $this->connection->prepare($sql);
$i = 0;
foreach ($params as &$param)
{
$sth->bindParam(++$i, $param);
$sth->execute();
}
unset($param)
// fetch all the rows into $result
cache::set($cache_key, $result);
return $result;
}
$obj->stmt('SELECT * FROM table WHERE id = ?', array(&$id));
我会让它适应您的需求。你必须获取行并将它们存储在一个数组中。
这里是你不得不使用的那种包装的:
class stmt
{
protected $sth, $sql, $cache, $params = array();
public function __construct($dbh, $sql)
{
$this->sth = $dbh->prepare($sql);
$this->sql = $sql;
}
public function bindParam($param, &$var)
{
$this->params[$param] =& $var;
return $this->sth->bindParam($param, $var);
// or, if you want to support all the args
$args = func_get_args();
$args[1] =& $var;
return call_user_func_array(array($this->sth, 'bindParam'), $args);
}
public function execute(array $params = null)
{
$str = serialize(isset($params) ? $params : $this->params);
$cache_key = sha1($this->sql . $str);
// insert cache logic here...
if (isset($params))
{
$this->stmt->execute($params);
}
else
{
$this->stmt->execute();
}
$this->cache = $this->stmt->fetchAll();
// save cache here
}
public function fetch()
{
return array_shift($this->cache);
}
}
你不得不与您打算使用的每PDOStatement对象的方法。 PDO :: FETCH_INTO也会带来一些痛苦。我的建议:关注你自己的用法。也许你甚至不需要在dbh级别实现缓存,而是只能在缓存功能的位置添加缓存功能。
无论如何,请记住,您编写的代码越多,您需要维护的代码就越多,并且越有可能在应用程序中引入错误。所以,要小心缓存层的成本/效益分析,它会尝试过于聪明,因为它本身不错:)
好的开始,但是大多数情况下,首先创建语句(从sql),然后再创建参数被添加(而不是同时)? – Xeoncross 2009-12-06 20:18:08
在这种情况下,你几乎搞砸了。 :)我不认为你可以从语句中获得原始SQL,因此你必须创建一个声明包装器,将原始SQL和准备好的声明一起存储。根据我的经验,我发现扩展或包装MySQLi比较困难,因为参数绑定和结果被提取的方式很多,并且因为大多数参数都是通过引用传递的,所以我现在更喜欢使用PDO。 – 2009-12-06 20:24:11
哦,我没有注意到它实际上是PDO的方法签名。我有我自己的stmt()包装,所以我一见钟情就不认识他们。 – 2009-12-06 20:28:58