When calling file_put_contents()
within a destructor, it causes files to be written in SERVER_ROOT
... (Yikes!) Workarounds?
tldr:
I want to cache an array, probably containing serialized class instances. I figured, for now, I would write a class that implements the cache using unserialize()/file_get_contents()
and serialize()/file_put_contents()
and then hide its functionality behind a more generic Cache class. (I don't know if my client's host will have shared memory or PEAR, etc)
<?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") );
?>
See the call to flush()
in the destructor? I really don't want to have the public flush()
function because it's implementation-specific.
Are you using a relative path as $filename? I would pass in an absolute path to where you want the file. If you want it to be relative to where your script is you could use something like:
I assume you have not specified a full qualified path in
$this->filename
.On some PHP configurations, when destructors are called (in the scripts shutdown phase), the working directory can change. Relative paths resolve to another location then.
Compare with the related note in the PHP Manual:
If you make that path absolute, it will work as expected.
Edit: As you've update your code, this is a simple way to ensure you've got the absolute path:
Or much better within the constructor:
You could create a file handle in
load()
which you can use in__destruct()
orflush()
.