在析构函数中创建/编写PHP文件

时间:2011-07-08 18:51:52

标签: php caching serialization destructor

在析构函数中调用file_put_contents()时,会导致文件写入SERVER_ROOT ...(Yikes!)变通办法?

tldr:

我想缓存一个数组,可能包含序列化的类实例。我想,现在,我会编写一个使用unserialize()/file_get_contents()serialize()/file_put_contents()实现缓存的类,然后将其功能隐藏在更通用的Cache类之后。 (我不知道我的客户主机是否有共享内存或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()函数,因为它是特定于实现的。

3 个答案:

答案 0 :(得分:8)

我假设您未在$this->filename中指定完整的限定路径。

在某些PHP配置中,当调用析构函数时(在脚本关闭阶段),工作目录可以更改。然后,相对路径会解析到另一个位置。

PHP Manual中的相关注释进行比较:

  

注意:

     

在脚本关闭期间调用的析构函数已经发送了HTTP头。脚本关闭阶段的工作目录可能与某些SAPI(例如Apache)不同。

如果您将该路径设为绝对路径,它将按预期工作。

编辑:当您更新代码时,这是确保您获得绝对路径的简单方法:

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

或者更好 构造函数:

$this->filename = realpath($filename);

答案 1 :(得分:2)

您可以在load()__destruct() flush()或{{1}}中使用create a file handle

答案 2 :(得分:1)

你使用相对路径作为$ filename吗?我会传入一个绝对路径到你想要文件的位置。如果您希望它相对于脚本的位置,您可以使用以下内容:

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