如何使用PHP在文件中添加或更新值



我正在开发一个小类,它将允许我将队列数据写入文件。类似于PHP $_SESSION. 的想法

我认为以下步骤将完成

  1. 'a+'模式下使用fopen()打开文件
  2. 使用flock()和LOCK_EX类型锁定文件,以防止其他进程使用同一文件
  3. 使用fread()读取文件的现有内容。然后使用json_decode(array, true)将数据放入数组
  4. 现在数据在数组中。如果数组中存在键,则更新其值,否则将键插入数组
  5. 在用文件中需要的所有数据创建数组后,我使用ftruncate()截断文件,并使用fwrite()将新数据写入文件
  6. 使用flock(解锁文件),并使用LOCK_UN类型以允许其他进程使用它
  7. 最后关闭文件

我相信我编写代码是为了满足updateCache()方法中的上述步骤。但它似乎不能正常工作。它不跟踪数据。

这是我的班级

<?php
namespace ICWS;
use ICWSshowVar;
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(mt_rand(1, 100) <= 5){
            $this->collectGarbage();
        }
    }
    private function print_me($a)
    {
        echo '<pre>';
        print_r($a);
        echo '</pre>';
    }
    /**
    * 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 = $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 = $storage[$key][$id];
            foreach($field as $k => $v){
                $currentVal[$k] = $v; //update existing key or add a new one
            }
        }
        $storage[$key][$id] =  $currentVal; 
        $this->updateFile($storage);
        $this->unlockFile();
        $this->closeFile();
    }
    /**
    * gets the current cache/session for a giving $key
    *
    * @param string $key. If null is passed it will return everything in the cache
    * @return object or boolean
    */  
    public function getCache($key = null)
    {
        $value = false;
        $this->openFile();
        rewind($this->handle);
        $storage = $this->readFile();
        if(!is_null($key) && isset($storage[$key])){
            $value = $storage[$key];
        }

        if(is_null($key)){
            $value = $storage;
        }
        $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 = "a+")
    {
        $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 = json_encode($data);
        $this->truncateFile();
        fwrite($this->handle, $raw);
    }
    /**
    * Delete the file content;
    *
    * @return void
    */
    private function truncateFile( )
    {
        ftruncate($this->handle, 0);
        rewind($this->handle);
    }

    /**
    * 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, $length);
            return json_decode($raw, true);
        }
        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
                && $file->getFilename() != 'index.html'
            ) {
                unlink($file->getPathName());
            }
        }
    }
    function addSlashes($str)
    {
        return addslashes($str);
    }

}

这就是我如何使用它

<?php
    require 'autoloader.php';
    try {
        $cache = new ICWSCacheHandler('cache/879');
        $field = array('name' => 'Mike A', 'Address' => '123 S Main', 'phone' => '2152456245', 'ext' => 123);
        $cache->updateCache('NewKey', 'first', $field);
        $cache->updateCache('NewKey', 'second', $field);
        $field = array('Address' => '987 S Main', 'phone' => '000000000000', 'ext' => 5555);
        $cache->updateCache('NewKey', 'first', $field);
    $field = array('locations' => array('S' => 'South', 'N' => 'North', 'E' => 'East'));
    $cache->updateCache('NewKey', 'first', $field);
        echo '<pre>';
        print_r($cache->getCache());
        echo '</pre>';  

    } catch (exception $e){
        echo $e->getMessage();
    }
?>

我希望阵列看起来像这个

Array
(
    [first] => stdClass Object
        (
            [name] => Mike A
            [Address] => 987 S Main
            [phone] => 000000000000
            [ext] => 5555
            [locations] => Array
                (
                    [S] => South
                    [N] => North
                    [E] => East
                )
        )
    [second] => stdClass Object
        (
            [name] => Mike A
            [Address] => 123 S Main
            [phone] => 2152456245
            [ext] => 123
        )
)

但是在第一次执行之后,我得到了一个空白数组。然后,在我再次执行脚本后,我得到以下数组。

Array
(
    [NewKey] => Array
        (
            [first] => Array
                (
                    [locations] => Array
                        (
                            [S] => South
                            [N] => North
                            [E] => East
                        )
                )
        )
)

是什么原因导致数据无法正确更新?

我使用$_SESSION编写了updateCache(),这给了我正确的输出,但我需要在没有会话的情况下这样做

这是我的会话基础方法

public function updateCache($key, $id, array $field)
{
    $currentVal = (object) $field;
    //create a new if the $id does not exists in the cache
    if( isset($_SESSION[$key]) && array_key_exists($id, $_SESSION[$key]) ){
        $currentVal = (object) $_SESSION[$key][$id];
        foreach($field as $k => $v){
            $currentVal->$k = $v; //update existing key or add a new one
        }
    }
    $_SESSION[$key][$id] =  $currentVal;    
}

问题就在这里:

private function readFile()
{
    $length = filesize($this->filename);
    if($length > 0){
        rewind($this->handle);
        $raw = fread($this->handle, $length);
        return json_decode($raw, true);
    }
    return array();
}

filesize()的文件规定:

注意:此函数的结果是缓存的。有关更多详细信息,请参阅clearstatcache()。

因为启动时文件是空的,所以它会缓存该信息,并且在下一次脚本执行之前,分支会被完全跳过。这应该解决它:

private function readFile()
{
    rewind($this->handle);
    $raw = stream_get_contents($this->handle);
    return json_decode($raw, true) ?: [];
}

相关内容

  • 没有找到相关文章

最新更新