检查字符串是否可以是路径(没有警告)

Check if string could be a path (without warning)

如果字符串不是有效路径,我如何在不发出警告的情况下检查 PHP 中的字符串是否是有效路径?

当我将 file_get_contentsis_filerealpathfile_exists 与不是路径的字符串一起使用时,我收到以下警告。

"function_name()" expects parameter 1 to be a valid path, string given in [...]

那么如何判断字符串是否是一个有效的路径。


你到底想干什么?你可能会问...

好吧,我想创建一个这样的函数。

funtion my_smart_function( string $path_or_content )
{
    $content = is_file_without_warning_if_not_a_valid_path( $path_or_content )
             ? file_get_contents( $path_or_content )
             :                    $path_or_content;
    // do nice stuff with my $content
}

有时 $path_or_content 将是文件的有效路径,有时 $path_or_content 将是文件本身的内容(例如,动态创建的图像的二进制数据不甚至没有路径(至少现在还没有)。在后一种情况下,我上面提到的所有这些与字符串相关的函数(例如 file_exists())都会发出警告(参见上面的引用)。


我想知道的事情。
realpath('xyz') 不发出警告但
realpath( file_get_contents('path/to/actual/image.jpg') ) 确实...

所以realpath和上面提到的其他函数区分字符串字符串是有效路径那么我们怎样才能事先做呢?

我想你错过了 file_exists 功能。来自文档:

file_exists — Checks whether a file or directory exists

bool file_exists ( string $filename )

Returns TRUE if the file or directory specified by filename exists; FALSE otherwise.

我相信这正是您想要的。 ctype_print 检查提供的字符串中的所有字符是否都是可打印的。如果是这样,将其传递给 file_exists.

function my_smart_function( $path_or_content )
{

    $content = ctype_print($path_or_content) && file_exists( $path_or_content )
             ? file_get_contents( $path_or_content )
             :                    $path_or_content;

    // do nice stuff with my $content
}

这可能是使用 @ 修饰符抑制错误的合理时机。

funtion my_smart_function( string $path_or_content )
{
    $content =      @file_exists( $path_or_content )
             ? file_get_contents( $path_or_content )
             :                    $path_or_content;
}

如果它不是有效路径,file_exists() 将 return 一个错误的值,并且 @ 将阻止它抱怨错误的字符串。

在 Linux 上,路径中唯一不允许出现的字符是空字节。所以你可以检查这个:

if (strpos($path_or_contents, "[=11=]") === false) {
    return file_get_contents($path_or_contents);
} else {
    return $path_or_contents;
}

file_exists 不检查路径是否为有效路径并且具有未记录的行为。同时没有检查路径是否有效的功能。最低限度的检查可以按照 Barmar 的建议进行:return strpos($path, "[=11=]") === false

但是通常你也不希望文件名中有不可打印的字符,所以在将路径传递给 file_exists 之前只使用 ctype_print 函数是相当公平的假设(正如 Daan 所建议的那样) ).

一些背景知识

尽管每个人都使用 file_exists 来检查...该文件是否存在,但此函数(和其他一些函数)的作用远不止于此。

准确地说,如果路径不是有效路径(即包含 [=16=]),则 returns null。这是一个 PHP bug

这是非常令人困惑的行为。尽管 documentation 表示 file_exists "Returns TRUE if the file or directory specified by filename exists; FALSE otherwise.",但这不是当前的实现行为。

根据来自 PHP 社区的人的说法:

No, file_exists does not test valid paths. It tests if a "file" exists. The presumption is that the path you are giving is valid, because if not then it couldn't possibly exist.