file_exists() returns false, but the file DOES exist

后端 未结 14 1283
一向
一向 2020-12-05 09:40

I\'m having a very weird issue with file_exists(). I\'m using this function to check if 2 different files in the same folders do exist. I\'ve double-checked, they BOTH do ex

14条回答
  •  旧时难觅i
    2020-12-05 10:18

    In my case, the problem was a misconception of how file_exists() behaves with symbolic links and .. ("dotdot" or double period) parent dir references. In that regard, it differs from functions like require, include or even mkdir().

    Given this directory structure:

    /home/me/work/example/
      www/
    /var/www/example.local/
      tmp/
      public_html -> /home/me/work/example/www/
    

    file_exists('/var/www/example.local/public_html/../tmp/'); would return FALSE even though the subdir exists as we see, because the function traversed up into /home/me/work/example/ which does not have that subdir.


    For this reason, I have created this function:

    /**
     * Resolve any ".." ("dotdots" or double periods) in a given path.
     *
     * This is especially useful for avoiding the confusing behavior `file_exists()`
     * shows with symbolic links.
     *
     * @param string $path
     *
     * @return string
     */
    function resolve_dotdots( string $path ) {
    
        if (empty($path)) {
            return $path;
        }
    
        $source = array_reverse(explode(DIRECTORY_SEPARATOR, $path));
        $balance = 0;
        $parts = array();
    
        // going backwards through the path, keep track of the dotdots and "work
        // them off" by skipping a part. Only take over the respective part if the
        // balance is at zero.
        foreach ($source as $part) {
            if ($part === '..') {
                $balance++;
    
            } else if ($balance > 0) {
                $balance--;
    
            } else {
                array_push($parts, $part);
            }
        }
    
        // special case: path begins with too many dotdots, references "outside
        // knowledge".
        if ($balance > 0) {
            for ($i = 0; $i < $balance; $i++) {
                array_push($parts, '..');
            }
        }
    
        $parts = array_reverse($parts);
        return implode(DIRECTORY_SEPARATOR, $parts);
    }
    

提交回复
热议问题