In PHP, is there a neat way to get just the directory part of an HTTP URI? I.e. given a URI with an optional filename and query, I want just the directory without the filename or query;
Given Returns / / /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开发者_C百科/bar/
And so on.
I can't find a PHP function to do it. I'm using the following code snippet but it's long-winded and over-complicated for something that feels like it ought to be a single function;
$uri_path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$uri_dir = substr($uri_path, 0, 1 + strrpos($uri_path, '/'));
Is there a cleaner way?
Edit
dirname() doesn't do what I want.
echo dirname("/foo/bar/");
Outputs;
/foo
dirname returns the directory.
Explicitly, $uri_dir = dirname($_SERVER['REQUEST_URI']);
As well, pathinfo returns an associative array with PATHINFO_DIRNAME, PATHINFO_BASENAME, PATHINFO_EXTENSION
and PATHINFO_FILENAME
. Quite useful.
Here's a one liner that will pass your tests by stripping everything after the final slash
$path=preg_replace('{/[^/]+$}','/', $uri);
The dirname function can't help you, as it returns the parent dir of its input, i.e. dirname('/foo/bar/') returns '/foo' (however, see Arvin's comment that sneakily tacking an extra bit on the uri first would fool it into doing your bidding!)
To break down that regex...
- the opening and closing braces {} are just delimiters for the pattern, and are ignored.
- the first thing we must match in the string is a /
- then we have a 'character class' in square brackets [^/]
- the leading ^ means 'invert the class' - in other words, match any character not in this class
- the next symbol is a /
- so this character class simply matches any character which isn't a /
- next, a + symbol means 'match 1 or more of the previous pattern' - in other words, match as many non-slash characters as possible
- finally the $ symbol matches the end of a string
So, the regex finds the final slash in a string and all the characters following it.
Try dirname($uri_path);
- see dirname()
The other option is to use the strrpos() function to find the last occurring /
which is probably better than dirname as dirname on windows systems treats \
as /
.
Then you should check if parse_url() does urldecoding or not.
$dir = $_SERVER['PHP_SELF']; // $dir = '/foo/'; // also works
$dir = (substr($dir,-1)=='/') ? $dir : dirname($dir) . '/';
also seems to work and is bit shorter.
use: 'http://' . $_SERVER['HTTP_HOST'] . $dir
for full URI
The reason I would use PHP_SELF instead of REQUEST_URI is that in some of the other examples if the user puts a "/" in one of the arguments, you will get unexpected results without additional sanitizing. Also, not all servers support all header variables, but the ones here are pretty common.
精彩评论