代码之家  ›  专栏  ›  技术社区  ›  TRiG

当文件不存在时抑制PHP filemtime()错误

  •  0
  • TRiG  · 技术社区  · 8 年前

    我们通常不想抑制PHP错误,但在这种特定的情况下我们愿意。我们缓存复杂查询的结果,因此可以避免对数据库造成太大的冲击。从缓存中读取时,我们检查文件(a)是否存在,以及(b)是否太旧。有时,第二次检查失败,因为文件在此期间已不存在。

    $file = self::getFile($name);
    if (!file_exists($file)) {
        return;
    }
    
    $modtime = @filemtime($file);
    if (!$modtime) {
        // Looks like the file has been deleted since the file_exists() call,
        // even though that was just a couple of lines ago.
        return;
    }
    
    if (($modtime + $expires) < time()) {
        self::delete($name);
        return;
    }
    

    @filemtime ,我们仍然偶尔会收到错误报告:

    filemtime():stat对于/tmp/websites/cache/example.com/7f93434/products-data.aaa5df0c1d251a494234b325b280eca.cache失败

    如果 @filemtime()

    2 回复  |  直到 8 年前
        1
  •  0
  •   Barry    8 年前
    $file = 'none.php';
    if(is_file($file) && is_readable($file)){
        $time = filemtime($file);
    }
    
        2
  •  0
  •   TRiG    7 年前

    结果发现 @ 抑制错误,但是我们的自定义错误处理程序忽略了这个事实。自定义错误处理程序仍会为隐藏的错误调用。

    因此,我们的自定义错误处理程序必须进行调整以允许这样做。

    旧自定义错误处理程序的摘录:

     public static function shouldIgnoreThisError(array $error)
     {
        // Stupid PHP still raises a E_WARNING when deleting a non-existing file
        // or directory, even with the @ operator. Sigh!
        $regexs = array(
           '/unlink\(.*\.cache\)\: No such file or directory/i',
           '/mkdir\(\)\: File exists/',
           '/.cache\)\: failed to open stream/',
        );
    
        foreach ($regexs as $regex) {
            if (preg_match($regex, $error['text'])) {
                return true;
            }
        }
    
        return false;
     }
    

    当我明白这一点后,同样的函数被重写了:

     public static function shouldIgnoreThisError(array $error)
     {
        /**
         * If you have set a custom error handler function with set_error_handler()
         * then it will still get called, but this custom error handler can (and
         * should) call error_reporting() which will return 0 when the call that
         * triggered the error was preceded by an @.
         *
         * http://php.net/manual/en/language.operators.errorcontrol.php
         */
        return !error_reporting();
     }