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

发布于 2024-11-18 22:21:55 字数 2258 浏览 0 评论 0原文

在析构函数中调用 file_put_contents() 时,它会导致文件写入 SERVER_ROOT...(哎呀!)解决方法?

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() 的调用了吗?我真的不想使用 publiclush() 函数,因为它是特定于实现的。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

彻夜缠绵 2024-11-25 22:21:55

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

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

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

注意:

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

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

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

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

或者在构造函数内更好:

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

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:

Note:

Destructors called during the script shutdown have HTTP headers already sent. The working directory in the script shutdown phase can be different with some SAPIs (e.g. Apache).

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:

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

Or much better within the constructor:

$this->filename = realpath($filename);
过潦 2024-11-25 22:21:55

您可以在 load()创建一个文件句柄,您可以在 中使用它__destruct() 或 flush()

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

怪异←思 2024-11-25 22:21:55

您是否使用相对路径作为 $filename ?我会传入您想要文件的位置的绝对路径。如果您希望它与脚本所在的位置相关,您可以使用类似以下内容的内容:

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

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:

$filename = dirname($_SERVER['SCRIPT_FILENAME']) . PATH_SEPARATOR . $filename;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文