开发者

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

开发者 https://www.devze.com 2023-03-11 03:28 出处:网络
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;

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消