Creating / writing a PHP file in the destructor

When calling file_put_contents() inside the destructor, it forces the files to be written to SERVER_ROOT ... (Yikes!) Workarounds?

TL; DR:

I want to cache an array, possibly containing serialized instances of the class. I decided that at the moment I would write a class that implements the cache using unserialize()/file_get_contents() and serialize()/file_put_contents() , and then hides its functionality behind the more general Cache class. (I don't know if my client 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 a public flush() function, because it is implementation specific.

+3
source share
3 answers

I assume that you did not specify the full path in $this->filename .

In some PHP configurations, when destructors are called (during the script shutdown phase), the working directory may change. Relative paths are then resolved elsewhere.

Compare with the corresponding note in the PHP Manual :

Note:

Destructors called when the script ends are already sent with HTTP headers. The working directory in the completion phase of the script may differ from some SAPIs (for example, Apache).

If you make this path absolute, it will work as expected.

Edit:. When you update your code, this is an easy way to make sure you have an absolute path:

 $cache = new CacheFile(realpath("cache")); 

Or much better in the constructor:

 $this->filename = realpath($filename); 
+6
source

You can create a file descriptor in load() , which you can use in __destruct() or flush() .

+2
source

Are you using a relative path like $ filename? I would go in the absolute path to where you want the file. If you want it to be relative to your script, you could use something like:

 $filename = dirname($_SERVER['SCRIPT_FILENAME']) . PATH_SEPARATOR . $filename; 
+1
source

Source: https://habr.com/ru/post/894555/


All Articles