那麼,您必須將每個參數的值添加到緩存鍵中。類似這樣的:
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