2011-07-08 10 views
3

デストラクタ内でfile_put_contents()を呼び出すと、ファイルがSERVER_ROOT ...(Yikes!)に書き込まれます。PHPファイルの作成/デストラクタ内での書き込み

tldr:

私はおそらく、シリアル化されたクラスのインスタンスを含む配列を、キャッシュしたいです。私は、今のところ、unserialize()/file_get_contents()serialize()/file_put_contents()を使ってキャッシュを実装するクラスを作成し、より汎用的なCacheクラスの背後にその機能を隠していると考えました。

<?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")); 
?> 

(私のクライアントのホストは、など、メモリやPEARを共有しているかどうかはわからない)デストラクタでflush()への呼び出しを参照してください?実装固有の機能なので、私は本当にpublic flush()機能を望んでいません。

+3

質問に答えることはできませんが、なぜWebサーバーユーザーが 'SERVER_ROOT'を書き込み可能にするのですか? –

+0

'$ this-> filename'には何がありますか? – hakre

+0

私はOPのコードを変更して動作上の問題を表示しました... $ this-> filename is "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

Perfect!ありがとうございました! –

+0

'__DIR__'だけではないのはなぜですか? – kralyk

関連する問題