2011-07-08 62 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