36

This is the url of my script: localhost/do/index.php

I want a variable or a function that returns localhost/do (something like $_SERVER['SERVER_NAME'].'/do')

nalply
  • 26,770
  • 15
  • 78
  • 101
cdxf
  • 5,501
  • 11
  • 50
  • 65

11 Answers11

35
$_SERVER['SERVER_NAME'] . dirname($_SERVER['REQUEST_URI']);
Blazemonger
  • 90,923
  • 26
  • 142
  • 180
www333
  • 386
  • 2
  • 2
  • excellent answer, but this doesn't work on IIS unfortunately as dirname returns windows backslashes – icc97 Apr 28 '13 at 09:03
  • 4
    actually it only returns a backslash if the request URI is localhost/do/ rather than localhost/do/index.php. I got around this by using the PHP_SELF which always includes the index.php, so `$current_dir_url = $_SERVER['SERVER_NAME'] . dirname($_SERVER['PHP_SELF']);` – icc97 Apr 28 '13 at 09:21
  • 1
    I do not suggest using dirname(). At first: This answer is wrong, as it returns the parent and not the current directory, but even if you add a trailing slash (like @Your Common Sense did) you are facing a problem with $_SERVER['REQUEST_URI'] as it contains only `/` if you call `http://example.com/`. By that `dirname()` would return `/` and as you add your second `/` it results `//`. You have the same problem with using `$_SERVER['PHP_SELF'])`. See my answer for further informations. – mgutt Mar 19 '15 at 15:06
34

Try:

$url = $_SERVER['REQUEST_URI']; //returns the current URL
$parts = explode('/',$url);
print_r($parts);

EDIT:

$url = $_SERVER['REQUEST_URI']; //returns the current URL
$parts = explode('/',$url);
$dir = $_SERVER['SERVER_NAME'];
for ($i = 0; $i < count($parts) - 1; $i++) {
 $dir .= $parts[$i] . "/";
}
echo $dir;

This should return localhost/do/

Calvin
  • 8,697
  • 7
  • 43
  • 51
  • 1
    It is enough to use `dirname()`, which doesn't check if the directory really exists. The value returned from `dirname('/solar/system'`) is `'/solar'`, whatever the directory /solar exists, or not. – apaderno Aug 07 '10 at 06:05
  • that's ugliest way I've ever seen. you've at least use implode – Your Common Sense Aug 07 '10 at 06:51
  • $_SERVER['REQUEST_URI'] does not contains the current script path when using url rewriting. That would not work in this case. – Leto Oct 05 '11 at 21:11
  • using implode instead of for loop is more elegant and convenient – Med Abida May 30 '16 at 08:32
  • 1
    This does not work with urls such as localhost:8888/do/index.php as it does not include the port. – Andrew Downes Aug 09 '16 at 11:03
9

I suggest not to use dirname(). I had several issues with multiple slashes and unexpected results at all. That was the reason why I created currentdir():

function currentdir($url) {
    // note: anything without a scheme ("example.com", "example.com:80/", etc.) is a folder
    // remove query (protection against "?url=http://example.com/")
    if ($first_query = strpos($url, '?')) $url = substr($url, 0, $first_query);
    // remove fragment (protection against "#http://example.com/")
    if ($first_fragment = strpos($url, '#')) $url = substr($url, 0, $first_fragment);
    // folder only
    $last_slash = strrpos($url, '/');
    if (!$last_slash) {
        return '/';
    }
    // add ending slash to "http://example.com"
    if (($first_colon = strpos($url, '://')) !== false && $first_colon + 2 == $last_slash) {
        return $url . '/';
    }
    return substr($url, 0, $last_slash + 1);
}

Why you should not use dirname()

Assume you have image.jpg located in images/ and you have the following code:

<img src="<?php echo $url; ?>../image.jpg" />

Now assume that $url could contain different values:

  • http://example.com/index.php
  • http://example.com/images/
  • http://example.com/images//
  • http://example.com/
  • etc.

Whatever it contains, we need the current directory to produce a working deeplink. You try dirname() and face the following problems:

1.) Different results for files and directories

File
dirname('http://example.com/images/index.php') returns http://example.com/images

Directory
dirname('http://example.com/images/') returns http://example.com

But no problem. We could cover this by a trick:
dirname('http://example.com/images/' . '&') . '/'returns http://example.com/images/

Now dirname() returns in both cases the needed current directory. But we will have other problems:

2.) Some multiple slashes will be removed
dirname('http://example.com//images//index.php') returns http://example.com//images

Of course this URL is not well formed, but multiple slashes happen and we need to act like browsers as webmasters use them to verify their output. And maybe you wonder, but the first three images of the following example are all loaded.

<img src="http://example.com/images//../image.jpg" />
<img src="http://example.com/images//image.jpg" />
<img src="http://example.com/images/image.jpg" />
<img src="http://example.com/images/../image.jpg" />

Thats the reason why you should keep multiple slashes. Because dirname() removes only some multiple slashes I opened a bug ticket.

3.) Root URL does not return root directory
dirname('http://example.com') returns http:
dirname('http://example.com/') returns http:

4.) Root directory returns relative path
dirname('foo/bar') returns .

I would expect /.

5.) Wrong encoded URLs
dirname('foo/bar?url=http://example.com') returns foo/bar?url=http:

All test results:
http://www.programmierer-forum.de/aktuelles-verzeichnis-alternative-zu-dirname-t350590.htm#4329444

mgutt
  • 5,867
  • 2
  • 50
  • 77
  • 1
    makes you think that dirname wasn't meant for URLs – icc97 Aug 03 '15 at 20:47
  • too convoluted answer, takes too much code, better to use regex (see my answer); and if you fear a "wrong encoded url" you should just check using `filter_var($url, FILTER_VALIDATE_URL)` and do nothing if it fails. – Ivan Castellanos Apr 15 '18 at 23:22
8

When I was implementing some of these answers I hit a few problems as I'm using IIS and I also wanted a fully qualified URL with the protocol as well. I used PHP_SELF instead of REQUEST_URI as dirname('/do/') gives '/' (or '\') in Windows, when you want '/do/' to be returned.

if (empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] === 'off') {
    $protocol = 'http://';
} else {
    $protocol = 'https://';
}
$base_url = $protocol . $_SERVER['SERVER_NAME'] . dirname($_SERVER['PHP_SELF']);
icc97
  • 11,395
  • 8
  • 76
  • 90
8

php has many functions for string parsing which can be done with simple one-line snippets
dirname() (which you asked for) and parse_url() (which you need) are among them

<?php

echo "Request uri is: ".$_SERVER['REQUEST_URI'];
echo "<br>";

$curdir = dirname($_SERVER['REQUEST_URI'])."/";

echo "Current dir is: ".$curdir;
echo "<br>";

address bar in browser is

http://localhost/do/index.php

output is

Request uri is: /do/index.php
Current dir is: /do/
Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
  • @Snoob here goes your example. Now if you'll be able to explain what you're trying to use that "base dic" for, I'll tell you why it's not working – Your Common Sense Aug 07 '10 at 09:58
  • 1
    It works if url is localhost/do/index.php, but when i use localhost/do. Output: Request uri is: /ds/ Current dir is: \/ – cdxf Aug 07 '10 at 11:04
2

If you want to include the server name, as I understood, then the following code snippets should do what you are asking for:

$result = $_SERVER['SERVER_NAME'] . dirname(__FILE__);

$result = $_SERVER['SERVER_NAME'] . __DIR__; // PHP 5.3

$result = $_SERVER['SERVER_NAME'] . '/' . dirname($_SERVER['REQUEST_URI']);
apaderno
  • 28,547
  • 16
  • 75
  • 90
1

dirname will give you the directory portion of a file path. For example:

echo dirname('/path/to/file.txt');  // Outputs "/path/to"

Getting the URL of the current script is a little trickier, but $_SERVER['REQUEST_URI'] will return you the portion after the domain name (i.e. it would give you "/do/index.php").

hbw
  • 15,560
  • 6
  • 51
  • 58
  • echo dirname($_SERVER['REQUEST_URI']); http://localhost/do/ => return \; http://localhost/do/index.php => return /do – cdxf Aug 07 '10 at 05:51
  • To notice that if the URL is `http://localhost/do/index.php`, `localhost` is not included from the value returned from `dirname($_SERVER['REQUEST_URI'])`. – apaderno Aug 07 '10 at 06:07
  • @Snoob and @kiamlaluno: I already addressed this in my original post by saying `$_SERVER['REQUEST_URI']` will return you the portion after the domain name (or, in this case, the server name). – hbw Aug 07 '10 at 06:15
1

the best way is to use the explode/implode function (built-in PHP) like so

$actual_link = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$parts = explode('/',$actual_link);
$parts[count($parts) - 1] = "";
$actual_link = implode('/',$parts);
echo $actual_link;
Med Abida
  • 1,214
  • 11
  • 31
0

My Suggestion:

const DELIMITER_URL = '/';
$urlTop = explode(DELIMITER_URL, trim(input_filter(INPUT_SERVER,'REQUEST_URI'), DELIMITER_URL))[0]

Test:

const DELIMITER_URL = '/';
$testURL = "/top-dir";
var_dump(explode(DELIMITER_URL, trim($testURL, DELIMITER_URL))[0]);

$testURL = "/top-dir/";
var_dump(explode(DELIMITER_URL, trim($testURL, DELIMITER_URL))[0]);

$testURL = "/top-dir/test";
var_dump(explode(DELIMITER_URL, trim($testURL, DELIMITER_URL))[0]);

$testURL = "/top-dir/test/";
var_dump(explode(DELIMITER_URL, trim($testURL, DELIMITER_URL))[0]);

$testURL = "/top-dir/test/this.html";
var_dump(explode(DELIMITER_URL, trim($testURL, DELIMITER_URL))[0]);

$testURL = "/top-dir/test.html";
var_dump(explode(DELIMITER_URL, trim($testURL, DELIMITER_URL))[0]);

Test Output:

string(7) "top-dir"
string(7) "top-dir"
string(7) "top-dir"
string(7) "top-dir"
string(7) "top-dir"
string(7) "top-dir"
tylersDisplayName
  • 1,603
  • 4
  • 24
  • 42
0

A shorter (and correct) solution that keeps trailing slash:

$url = $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
$url_dir = preg_replace('/[^\/]+\.php(\?.*)?$/i', '', $url);
echo $url_dir;
Ivan Castellanos
  • 8,041
  • 1
  • 47
  • 42
0

My Contribution
Tested and worked

/**
* Get Directory URL
*/
function get_directory_url($file = null) {
    $protocolizedURL = $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
    $trailingslashURL= preg_replace('/[^\/]+\.php(\?.*)?$/i', '', $protocolizedURL);
    return $trailingslashURL.str_replace($_SERVER['DOCUMENT_ROOT'], '', $file);
}

USAGE
Example 1:
<?php echo get_directory_ur('images/monkey.png'); ?>
This will return http://localhost/go/images/monkey.png

Example 2:
<?php echo get_directory_ur(); ?>
This will return http://localhost/go/