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

如何使用PHP在文件中添加或更新值,php,arrays,file,session,fopen,Php,Arrays,File,Session,Fopen,我正在开发一个小类,它允许我将队列数据写入文件。与PHP$\u会话的想法类似。 我想下面的步骤就可以了 在'a+'模式下使用fopen()打开文件 使用Lock\u EX类型的flock()锁定文件,以防止其他进程使用相同的文件 使用fread()读取文件的现有内容。然后使用json\u decode(array,true) 现在数据是数组中的。如果该键存在于数组中,则更新其值,否则将该键插入数组 在创建了一个包含文件中需要的所有数据的数组之后,我使用ftruncate()截断文件,并使用fwr

我正在开发一个小类,它允许我将队列数据写入文件。与PHP
$\u会话的想法类似。

我想下面的步骤就可以了

  • 'a+'
    模式下使用
    fopen()
    打开文件
  • 使用
    Lock\u EX
    类型的
    flock(
    )锁定文件,以防止其他进程使用相同的文件
  • 使用
    fread()
    读取文件的现有内容。然后使用
    json\u decode(array,true)
  • 现在数据是数组中的。如果该键存在于数组中,则更新其值,否则将该键插入数组
  • 在创建了一个包含文件中需要的所有数据的数组之后,我使用
    ftruncate()
    截断文件,并使用
    fwrite()将新数据写入文件
  • 使用
    LOCK\u UN
    类型的
    flock(
    )解锁文件,以允许其他进程使用它
  • 最后关闭文件
  • 我相信我编写代码是为了满足我的
    updateCache()
    方法中的上述步骤。但它似乎不能正常工作。它不跟踪数据

    这是我的班级

    <?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(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);
        }
    
    
    }
    
    但是在第一次执行之后,我得到了一个空数组。然后,在我再次执行脚本之后,我得到以下数组

    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();
    }
    
    是什么导致数据无法正确更新

    我使用
    $\u SESSION
    编写了我的
    updateCache()
    ,它为我提供了正确的输出,但我需要在没有sessions的情况下执行此操作

    这是我的方法

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

    各国的文件:

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

    由于启动时该文件为空,因此它会缓存该信息,并且在下一次脚本执行之前会完全跳过您的分支。这应该可以解决这个问题:


    这个尖叫-使用DB来测量,你在任何地方都使用这个
    'NewKey'
    ,但不要期望它出现在输出中。。。不知道为什么。在任何情况下,与其滚动您自己的缓存内容,为什么不利用像这样的东西?@Dagon DB就太过分了。这些数据是临时的。如果在一个数据库上用10%的代码来处理数据,那就不过分了file@Ja͢如果文件不存在,则ck“c+”不会创建该文件!我很高兴你咳嗽,因为我错过了。。非常感谢,现在它工作得很好。
    Array
    (
        [NewKey] => Array
            (
                [first] => Array
                    (
                        [locations] => Array
                            (
                                [S] => South
                                [N] => North
                                [E] => East
                            )
    
                    )
    
            )
    
    )
    
    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();
    }
    
    private function readFile()
    {
        rewind($this->handle);
        $raw = stream_get_contents($this->handle);
        return json_decode($raw, true) ?: [];
    }