2011-07-08 27 views
3

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

tldr:

我想缓存阵列,可能包含序列化类的实例。我现在认为,我会写一个类,它使用unserialize()/file_get_contents()serialize()/file_put_contents()来实现缓存,然后将其功能隐藏在更通用的缓存类中。 (我不知道如果我的客户端的主机将有共享内存或梨等)

<?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

不是您的问题的答案,但为什么SERVER_ROOT可由Web服务器用户写入? –

+0

'$ this-> filename'是什么? – hakre

+0

我更改了OP中的代码以显示问题的实际操作...... $ this-> filename是“cache” –

回答

6

我假设你没有在$this->filename指定完整合格的路径。

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

比较在PHP Manual相关注意事项:

注:

析构函数在脚本关闭时调用有HTTP标头已经发出。脚本关闭阶段的工作目录可能与一些SAPI(例如Apache)不同。

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

编辑:正如你更新你的代码,这是一个简单的方法,以确保你有绝对路径:

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

或在好得多构造:

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

内容翔实!谢谢! –

+0

@Brandon:我已经添加了一个小代码块,与您更新的问题中的代码行相关。 'realpath()'创建一个相对的绝对文件名。 – hakre

+0

真棒,我认为这解决了当我将绝对路径传递给构造函数时会发生什么问题 –

1

您是否使用相对路径作为$ filename?我会传递一个绝对路径到你想要的文件。如果你希望它是相对于您的脚本,你可以使用类似:

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

完美!谢谢! –

+0

为什么不使用'__DIR__'? – kralyk