当在析构函数中调用file_put_contents()
时,它会导致文件写入SERVER_ROOT
…(呀! !)解决方法?
tldr:
我想缓存一个数组,可能包含序列化的类实例。我想,现在,我将编写一个使用unserialize()/file_get_contents()
和serialize()/file_put_contents()
实现缓存的类,然后将其功能隐藏在更通用的缓存类后面。(我不知道我的客户端主机是否有共享内存或PEAR等)
<?php
class CacheFile {
private $filename;
private $data;
private $dirty = false;
function __construct($filename) {
$this->filename = $filename;
$this->load();
}
function __destruct() {
// Calling file_put_contents within a destructor causes files to be written in SERVER_ROOT...
$this->flush();
}
private function load() {
if(!file_exists($this->filename)) {
$this->data = array();
}
else {
$this->data = unserialize(file_get_contents($this->filename));
// todo
}
$this->dirty = false;
}
private function persist() {
file_put_contents($this->filename, serialize($this->data));
$this->dirty = false;
}
public function get($key) {
if(array_key_exists($key, $this->data)) {
return $this->data[$key];
}
else {
return false;
}
}
public function set($key, $value) {
if(!array_key_exists($key, $this->data)) {
$dirty = true;
}
else if($this->data[$key] !== $value) {
$dirty = true;
}
if($dirty) {
$this->dirty = true;
$this->data[$key] = $value;
}
}
public function flush() {
if($this->dirty) {
$this->persist();
}
}
}
$cache = new CacheFile("cache");
var_dump( $cache->get("item") );
$cache->set("item", 42);
//$cache->flush();
var_dump( $cache->get("item") );
?>
参见析构函数中对flush()
的调用?我真的不想有public flush()
函数,因为它是特定于实现的。
我假设您没有在$this->filename
中指定完整的限定路径。
在某些PHP配置中,当调用析构函数时(在脚本关闭阶段),工作目录可以改变。相对路径解析到另一个位置。
与PHP手册中的相关说明比较:
注意:
在脚本关闭期间调用的析构函数已经发送了HTTP头。脚本关闭阶段的工作目录可能与某些api(例如Apache)不同。
如果你将路径设置为绝对路径,它将按预期工作。
编辑:当你更新你的代码,这是一个简单的方法来确保你有绝对路径:
$cache = new CacheFile(realpath("cache"));
或者在构造函数中使用更好:
$this->filename = realpath($filename);
您可以在load()
中创建一个可以在__destruct()
或flush()
中使用的文件句柄
是否使用相对路径作为$filename?我会传递一个绝对路径到你想要文件的位置。如果你想让它相对于你的脚本的位置,你可以使用这样的东西:
$filename = dirname($_SERVER['SCRIPT_FILENAME']) . PATH_SEPARATOR . $filename;