【问题标题】:Check if string could be a path (without warning)检查字符串是否可以是路径(没有警告)
【发布时间】:2019-02-24 01:04:19
【问题描述】:

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

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

"function_name()" 期望参数 1 是有效路径,字符串在 [...] 中给出

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


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

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

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 函数?
  • 亲爱的朋友们!请 - 我不会编码 3 天或 3 年 :)
  • 你真的必须让你的用例更清晰。
  • 二进制内容会抛出这个警告(特别是 NUL)。你还有其他具体的例子吗?
  • @Axel 很高兴你得到了答案。

标签: php validation path suppress-warnings


【解决方案1】:

file_exists 不检查路径是否为有效路径并且具有未记录的行为。同时没有检查路径是否有效的功能。 Barmar 建议的最小检查可能是:return strpos($path, "\0") === false

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

一点背景

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

确切地说,如果路径不是有效路径(即包含\0),则返回null。这是一个 PHP bug

这是非常令人困惑的行为。尽管documentationfile_exists“如果文件名指定的文件或目录存在则返回TRUE;否则返回FALSE。”,这不是当前的实现行为。

根据 PHP 社区的某人的说法:

不,file_exists 不测试有效路径。它测试是否存在“文件”。假设您给出的路径是有效的,因为如果不是,那么它就不可能存在。

【讨论】:

  • 确实是很好的补充说明。 +1
【解决方案2】:

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

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() 将返回一个错误值,@ 将阻止它抱怨错误的字符串。

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

if (strpos($path_or_contents, "\0") === false) {
    return file_get_contents($path_or_contents);
} else {
    return $path_or_contents;
}

【讨论】:

  • 就是这样!非常感谢我之前尝试过 try{}catch($e){} 但这并没有收到来自 cource 的警告......再次感谢!
  • @Axel 如果您使用的是 PHP 7,我相信警告现在可以使用 catch (Throwable $t)
  • 是的 @MadhurBhaiya 我在 PHP7 上,但我想让我的函数向后兼容。
  • @Barmar 编辑了您的答案以准确匹配问题。希望你没事。
  • 启用严格类型后,这仍然会引发 \TypeError,谢天谢地,这是可以捕获的。
【解决方案3】:

我相信这正是您想要的。 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
}

【讨论】:

  • 亲爱的 Dann 非常感谢您抽出一些时间。你的答案正是我已经尝试过的。请致电my_smart_function( file_get_contents('path/to/actual/image.jpg') ),您将收到警告!
  • 当然你必须确保path/to/actual/image.jpg实际上指向一个图像...
  • @Axel 我已经更新了我的答案,你可以试试这个例子吗?
  • 我刚刚启动了一个服务器并尝试了这个功能。工作得很好。
  • @Daan 你是如何以非字符串的方式创建无效路径的?
【解决方案4】:

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

file_exists — 检查文件或目录是否存在

bool file_exists ( string $filename )

如果文件名指定的文件或目录存在,则返回TRUE; 否则为 FALSE。

【讨论】:

  • 问题现在说file_exists()也报错了。
  • @Barmar 问题不明确。标题和一些描述表明 OP 希望将字符串检查为有效路径与否。但是,现在他的智能函数也可以将“文件内容”作为输入
  • 这个问题对我来说似乎很清楚。他的意思是一个不会导致所有与文件相关的函数抱怨“期望参数1是有效路径”的字符串。这与作为现有文件的路径不同(file_put_contents() 不需要文件存在,因为它会创建它)。
  • 但是,如果字符串不是有效路径,file_exists 将返回 null,请参阅 bugs.php.net/bug.php?id=76406
猜你喜欢
  • 2018-05-23
  • 2016-06-24
  • 2016-07-25
  • 1970-01-01
  • 2022-12-15
  • 1970-01-01
  • 1970-01-01
  • 2014-09-04
相关资源
最近更新 更多