在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_EXTENSION
和PATHINFO_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,是因为在其他一些示例中,如果用户在其中一个参数中放入"/",则在没有额外清理的情况下,您将得到意外的结果。此外,并不是所有的服务器都支持所有的头变量,但这里的头变量非常常见。