在PHP中,有没有一种简单的方法可以获得URI的目录部分


In PHP, is there a simple way to get the directory part of a URI?

在PHP中,有没有一种简单的方法可以只获取HTTP URI的目录部分?也就是说,给定一个带有可选文件名和查询的URI,我只想要没有文件名或查询的目录;

给定回报///a.txt//?x=2//a.txt?x=2//foo//foo//foo/b.txt/foo//foo/b.txt?y=3/foo//foo/bar//foo/bar//foo/bar/c.txt/foo/bar/

等等。

我找不到一个PHP函数来做这件事。我正在使用以下代码片段,但它冗长而过于复杂,因为它感觉应该是一个单独的函数;

$uri_path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$uri_dir = substr($uri_path, 0, 1 + strrpos($uri_path, '/'));

有更干净的方法吗?

编辑

dirname()做不到我想要的。

echo dirname("/foo/bar/");

输出;

/foo

dirname返回目录。

明确地说,$uri_dir = dirname($_SERVER['REQUEST_URI']);

同样,pathinfo返回一个具有PATHINFO_DIRNAME, PATHINFO_BASENAME, PATHINFO_EXTENSIONPATHINFO_FILENAME的关联数组。非常有用。

这是一个单行,它将通过在最后一个斜杠之后剥离所有内容来通过测试

$path=preg_replace('{/[^/]+$}','/', $uri);

dirname函数不能帮你,因为它返回其输入的父目录,即dirname('/foo/bar/')返回'/foo'(然而,请参阅Arvin的评论,即偷偷地在uri上加一个额外的位会欺骗它进行竞价!)

要分解正则表达式。。。

  • 大括号和大括号{}只是模式的分隔符,并且被忽略
  • 我们必须在字符串中匹配的第一件事是/
  • 然后我们在方括号中有一个"字符类"[^/]
    • 前导^的意思是"反转类"-换句话说,匹配不在此类中的任何字符
    • 下一个符号是/
    • 所以这个字符类只匹配任何不是/
  • 接下来,+符号表示"匹配前一个模式的1个或多个"——换句话说,匹配尽可能多的非斜杠字符
  • 最后,$符号与字符串的末尾匹配

因此,正则表达式在字符串中找到最后一个斜杠及其后面的所有字符。

尝试dirname($uri_path);-请参阅dirname()

另一种选择是使用strrpos()函数查找最后出现的/,这可能比dirname更好,因为windows系统上的dirname将'视为/

然后,您应该检查parse_url()是否执行url解码。

$dir = $_SERVER['PHP_SELF']; // $dir = '/foo/'; // also works
$dir = (substr($dir,-1)=='/') ? $dir : dirname($dir) . '/';

看起来也很有效,而且有点短。

使用:'http://' . $_SERVER['HTTP_HOST'] . $dir用于完整URI

我之所以使用PHP_SELF而不是REQUEST_URI,是因为在其他一些示例中,如果用户在其中一个参数中放入"/",则在没有额外清理的情况下,您将得到意外的结果。此外,并不是所有的服务器都支持所有的头变量,但这里的头变量非常常见。