为什么我的文件在尝试使用 PHP 读取时总是空的?

Why my file is always empty when trying to read it using PHP?

我正在尝试编写一个 class 允许我将数据写入文件然后读取它。在某些情况下,我还会锁定文件以进行写入,然后在写入完成后将其解锁。

我遇到的问题是,当尝试使用我的 getCache() 方法获取文件内容时,文件变为空。似乎当 getCache() 方法被调用时,文件的内容由于某种原因被删除了。

这是我的 class

<?php

namespace ICWS;

use \ICWS\showVar;
use \DirectoryIterator;
/**
 * CacheHandler
 *
 * @package ICWS
 */
class CacheHandler {

    /* Max time second allowed to keep a session File */
    private $maxTimeAllowed = 300;


    private $filename = '';
    private $handle;

    public function __construct( $filename ){

        $this->filename = $filename;

        // 5% chance to collect garbage when the class is initialized.
        if(rand(1, 100) <= 5){
            $this->collectGarbage();
        }
    }


    /**
    * Add/Update the cached array in the session
    *
    * @param string $key
    * @param bigint $id
    * @param array $field
    * @return void
    */  
    public function updateCache($key, $id, array $field)
    {

        $currentVal = (object) $field;
        $this->openFile();

        $this->lockFile();
        $storage = $this->readFile();
        //create a new if the $id does not exists in the cache
        if( isset($storage[$key]) && array_key_exists($id, $storage[$key]) ){

            $currentVal = (object) $storage[$key][$id];

            foreach($field as $k => $v){
                $currentVal->$k = $v; //update existing key or add a new one
            }

        }

        $storage[$key][$id] =  $currentVal; 
        new showVar($storage);
        $this->updateFile($storage);
        $this->unlockFile();

        $this->closeFile();
    }

    /**
    * gets the current cache/session for a giving $key
    *
    * @param string $key
    * @return object or boolean
    */  
    public function getCache($key)
    {
        $value = false;
        $this->openFile();

        $storage = $this->readFile();

        if(isset($storage[$key])){
            $value = $storage[$key];
        }

        $this->closeFile();

        return $value;
    }

    /**
    * removes the $id from the cache/session
    *
    * @param string $key
    * @param bigint $id
    * @return boolean
    */      
    public function removeCache($key, $id)
    {

        $this->openFile();

        $this->lockFile();
        $storage = $this->readFile();

        if( !isset($storage[$key][$id])){
            $this->unlockFile();
            $this->closeFile();
            return false;
        }

        unset($storage[$key][$id]);
        $this->updateFile($storage);
        $this->unlockFile();
        $this->closeFile();
        return true;
    }



    /**
    * unset a session
    *
    * @param argument $keys
    * @return void
    */  
    public function truncateCache()
    {
        if(file_exists($this->filename)){
            unlink($this->filename);
        }
    }

    /**
    * Open a file in a giving mode
    *
    * @params string $mode 
    * @return void
    */
    private function openFile( $mode = "w+"){
        $this->handle = fopen($this->filename, $mode);

        if(!$this->handle){
            throw new exception('The File could not be opened!');
        }
    }

    /**
    * Close the file
    * @return void
    */
    private function closeFile(){

        fclose($this->handle);
        $this->handle = null;
    }

    /**
    * Update the file with array data
    * @param array $data the array in that has the data
    * @return void
    */
    private function updateFile(array $data = array() ){
        $raw = serialize($data);    
        fwrite($this->handle, $raw);
    }

    /**
    * Read the data from the opned file
    *
    * @params string $mode 
    * @return array of the data found in the file
    */
    private function readFile() {

        $length = filesize($this->filename);
        if($length > 0){
             rewind($this->handle);
            $raw = fread($this->handle, filesize($this->filename));
            return unserialize($raw);
        }

        return array();
    }


    /**
    * Lock the file
    *
    * @return void
    */  
    private function lockFile( $maxAttempts = 100, $lockType = LOCK_EX) {

        $i = 0;
        while($i <= $maxAttempts){

            // acquire an exclusive lock
            if( flock($this->handle, LOCK_EX) ){
                break;
            }

            ++$i;
        }
    }


    /**
    * Unlock the file
    *
    * @return void
    */  
    private function unlockFile() {

        fflush($this->handle);
        flock($this->handle, LOCK_UN);
    }

    /**
    * Remove add cache files
    *
    * @return void
    */  
    private function collectGarbage(){
        $mydir = dirname($this->filename);

        $dir = new DirectoryIterator( $mydir );
        $time = strtotime("now");
        foreach ($dir as $file) {

            if (  !$file->isDot()
                && $file->isFile()
                && ($time - $file->getATime()) > $this->maxTimeAllowed
                && isset($file->getFilename) && $file->getFilename != 'index.html'
            ) {
                unlink($file->getPathName());

            }

        }
    }   

}

这就是我对 class

的称呼
<?php
    require 'autoloader.php';

    try {
        $cache = new \ICWS\CacheHandler('cache/12300000');

        $field = array('name' => 'Mike A', 'Address' => '123 S Main', 'phone' => '2152456245', 'ext' => 123);
        $cache->updateCache('NewKey', '123456', $field);

        echo '<pre>';
        print_r($cache->getCache('NewKey'));
        echo '</pre>';
    } catch (exception $e){

        echo $e->getMessage();
    }

?>

注释行 print_r($cache->getCache('NewKey')); 文件 12300000 将具有预期的以下数据

a:1:{s:6:"NewKey";a:1:{i:123456;O:8:"stdClass":4:{s:4:"name";s:6:"Mike A";s:7:"Address";s:10:"123 S Main";s:5:"phone";s:10:"2152456245";s:3:"ext";i:123;}}}

但是,当调用方法 print_r($cache->getCache('NewKey')); 时,文件变为空。

我在这里做错了什么?为什么我的 print_r($cache->getCache('NewKey')); 方法正在清空文件?

openFile($mode = "w+")

documentation for fopen() 说:

'w+' Open for reading and writing; place the file pointer at the beginning of the file and truncate the file to zero length. If the file does not exist, attempt to create it.

因此它会重置文件,删除其中的所有内容。

可能你想要模式 a+:

'a+' Open for reading and writing; place the file pointer at the end of the file. If the file does not exist, attempt to create it. In this mode, fseek()() only affects the reading position, writes are always appended.