我试图通过编写处理数组和自动命名的函数来简化对缓存函数的调用。这应该适用于数据更新不频繁的大多数情况。这是我到目前为止所得到的:
function save_cache($data, $name) {
// get id for name of cache
$id=shmop_open(get_cache_id($name), "c", 0644, get_array_size($data));
// return int for data size or boolean false for fail
if ($id) return shmop_write($id, serialize($data), 0);
else return false;
}
function get_cache($name) {
$id=shmop_open(get_cache_id($name), "a", 0644, shmop_size(get_cache_id($name)));
if ($id) $data=unserialize(shmop_read($id, 0, shmop_size($id)));
else return false; // failed to load data
if ($data) return $data; // array retrieved
else return false; // failed to load data
}
function get_cache_id($name) {
// build list to return a number for a string id
// maintain this as new caches are created
$id=array( 'test' => 1,
'test2' => 2
);
return $id[$name];
}
function get_array_size($a){
$size = 0;
while(list($k, $v) = each($a))$size += is_array($v) ? get_array_size($v) : strlen($v);
return $size;
}问题出在get_cache($name)函数的第一行。因为这是动态的,所以我需要根据字符串$name找到所请求的数组的大小,并在get_cache_id($name)中用我的id列表引用它。问题是使用shmop_open我需要来自shmop_size的大小,但要使用shmop_size,我首先需要shmop_open...最后,我的apache错误日志第13行是get_cache($name)中$id变量的赋值。
Wed Mar 06 15:57:57 2013 client 127.0.0.1PHP警告: shmop_size():第13行/home/mark/htdocs/phplib/cache.php中没有id为1的共享内存段Wed Mar 06 15:57:57 2013 client 127.0.0.1PHP注意: unserialize():第14行/home/mark/htdocs/phplib/cache.php中7769字节的偏移量7765处出错
编辑:工作代码和实现-除了下面的答案之外,这个脚本的get_array_size函数是错误的,应该完全省略。相反,在save_cache函数中,使用strlen(serialize($data))来确定要存储的缓存大小。此外,您还需要删除之前存储的该ID的缓存。最终脚本应该如下所示:
function save_cache($data, $name, $timeout) {
// delete cache
$id=shmop_open(get_cache_id($name), "a", 0, 0);
shmop_delete($id);
shmop_close($id);
// get id for name of cache
$id=shmop_open(get_cache_id($name), "c", 0644, strlen(serialize($data)));
// return int for data size or boolean false for fail
if ($id) {
set_timeout($name, $timeout);
return shmop_write($id, serialize($data), 0);
}
else return false;
}
function get_cache($name) {
if (!check_timeout($name)) {
$id=shmop_open(get_cache_id($name), "a", 0, 0);
if ($id) $data=unserialize(shmop_read($id, 0, shmop_size($id)));
else return false; // failed to load data
if ($data) { // array retrieved
shmop_close();
return $data;
}
else return false; // failed to load data
}
else return false; // data was expired
}
function get_cache_id($name) {
$id=array( 'test1' => 1
'test2' => 2
);
return $id[$name];
}
function set_timeout($name, $int) {
$timeout=new DateTime(date('Y-m-d H:i:s'));
date_add($timeout, date_interval_create_from_date_string("$int seconds"));
$timeout=date_format($timeout, 'YmdHis');
$id=shmop_open(100, "a", 0, 0);
if ($id) $tl=unserialize(shmop_read($id, 0, shmop_size($id)));
else $tl=array();
shmop_delete($id);
shmop_close($id);
$tl[$name]=$timeout;
$id=shmop_open(100, "c", 0644, strlen(serialize($tl)));
shmop_write($id, serialize($tl), 0);
}
function check_timeout($name) {
$now=new DateTime(date('Y-m-d H:i:s'));
$now=date_format($now, 'YmdHis');
$id=shmop_open(100, "a", 0, 0);
if ($id) $tl=unserialize(shmop_read($id, 0, shmop_size($id)));
else return true;
shmop_close($id);
$timeout=$tl[$name];
return (intval($now)>intval($timeout));
}在AJAX自动完成搜索中使用的对此函数的示例调用:
header('Content-type: application/json; charset=utf-8');
include '../phplib/conn.php';
include '../phplib/cache.php';
$searchTerm=$_GET['srch'];
$test=array();
$test=get_cache('test');
if (!$test) {
$odbc=odbc_connection(); // defined in conn.php
$sql="SELECT * FROM mysearchtable";
$result=odbc_exec($odbc, $sql) or
die("<pre>".date('[Y-m-d][H:i:s]').
" Error: [".odbc_error()."] ".odbc_errormsg()."\n\n $sql");
$i=0;
while ($row=odbc_fetch_array($result)) {
foreach ($row as $key => $value) $row[$key]=trim($value);
$test[$i]=$row;
$i++;
}
save_cache($test, 'test1', 600); // 10 minutes timeout
odbc_close($odbc);
}
$result=array();
foreach ($test as $key) {
if (strpos($key['item'])===0) { // starts the string
// if (strpos($key['item'])!==false) { // in the string anywhere
$result[]=array('item' => $key['item'], 'label' => $key['label']);
}
}
echo json_encode($result);发布于 2013-03-07 06:24:25
查看函数说明中的注释:shmop_open
打开已存在的段时,shmop_open第3和第4个参数应为0。如果您要获取缓存,则应该已经创建了段,因此您不需要在get_cache中获取段大小。
https://stackoverflow.com/questions/15259111
复制相似问题