23

If my URL is http://www.server.com/myapp/stuff/to/see and my directory structure on disk is htdocs/myapp/*, how can I extract the /myapp part? Also, what if there was no application folder and the application root was just '/'? Is there a predefined variable for getting that value?

What I want is a function that is able to trim /myapp off of the request URI, so that I'm only left with /stuff/to/see. AND, if I were to move the application to the server document root, have it determine that as well (so that /stuff/to/see is just returned as /stuff/to/see)

My directory structure is this:

application
  |-config
    |-config.inc.php
library
  |-autoload.class.php
public
  |-css
  |-img
index.php

So, from index.php, I want to know how to get what I asked above.

scottm
  • 27,829
  • 22
  • 107
  • 159

7 Answers7

18

When you access a page using http://www.server.com/myapp/stuff/to/see, and your webserver's document root is at /something/htdocs/, then the current local path is /something/htdocs/myapp/stuff/to/see.

There is no definite solution to get /something/htdocs/myapp/ as a result now, because there is no clear definition which path you should get. When you have some rule for that, tell us, and we might be able to come up with something, but without computation, the only paths you can see are:

  • http://www.server.com/myapp/stuff/to/see
    $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']
  • /something/htdocs/myapp/stuff/to/see/index.php
    $_SERVER['SCRIPT_FILENAME']
  • /something/htdocs/
    $_SERVER['DOCUMENT_ROOT']
  • /myapp/stuff/to/see
    $_SERVER['REQUEST_URI']
  • /myapp/stuff/to/see/index.php
    $_SERVER['SCRIPT_NAME'] and $_SERVER['PHP_SELF']
poke
  • 369,085
  • 72
  • 557
  • 602
  • Can you clarify what variables you used to get those values? – scottm Feb 22 '10 at 15:53
  • 2
    Make a test file with ``. Then you get an idea of what you can get in what way :) But I have also updated my post to include the correct variables. – poke Feb 22 '10 at 17:43
  • It sure would be cool to see a built in for something like jQuery's `closest()` function, so we could get the path of the folder closest to the current script, by passing the folder name – Brian Leishman Jun 08 '17 at 20:14
12

For the web root, there is DOCUMENT_ROOT as pointed out in several answers. For the application root, there is no way for the system to tell which folder in your application is the root folder. You will have to set that manually.

Most applications that use a single entry point, define an application root using __DIR__ constant in this single entry point file, or a config setting and store that in a constant that is available throughout the application.

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
Pekka
  • 442,112
  • 142
  • 972
  • 1,088
  • Do I need to hard code it? There's nothing I can add, in say DOC_ROOT/myapp/index.php, that can programmatically figure out that this is the app root? – scottm Feb 22 '10 at 15:58
  • 1
    If you are in /myapp/index.php, `dirname(__FILE__)` (= "give me the current directory of this file") will give you the definitive app root . You can store that in a constant and use it. – Pekka Feb 22 '10 at 16:03
3
<?php
define('ABSPATH', dirname(__FILE__));

Put the following code in a file located in the root folder of your application and include it on every page load.

Then, you can simply always do $path = ABSPATH . '/path/to/file.php'; regardless of if your local copy is in a sub-directory folder or not.


If your application already has a file which is included on every page load, you can simply drop the code above in that file and it will work.

Just note that you may have to add additional dirname() calls depending on where that file is located. Add one for each directory you pass from the root of your webapp.

For example, if your webapp is located in /webapp/ and your "global include" is located in /webapp/includes/framework/init.php, then the above code needs to be modified as such:

define('ABSPATH', dirname(dirname(dirname(__FILE__))));

ie.: 2 additional dirname() calls due to two additional folders from the webapp root (includes/framework)


Clarification

The code above is meant to be in one file, and one file only in your web application. That file needs to be included on each page load.

If you already have a file which is included before any processing (such as a configuration file or other), you may copy and paste that code in that file.

The number of dirname() calls depends on how deep the file you copied and pasted the code in is relative to the root directory of your web application. For the examples above, assume the root of your web application is represented by ~.

If you copy-paste my code into ~/abspath.php, then you need one dirname() call.

If you copy-paste my code into ~/includes/abspath.php, then you need two dirname() calls.

If you copy-paste my code into ~/includes/config/abspath.php, then you need three dirname() calls. Now let's just say that's its final location.

In ~/index.php, you do the following:

<?php
require_once('includes/config/abspath.php');

and you have access to ABSPATH.

In ~/dir/someOtherPage.php you do the following:

<?php
require_once('../includes/config/abspath.php');

and you have access to ABSPATH.

This is why I'm saying that if you already have a file which is included on each page load, its simpler just to drop the above code in it. Just make sure you modify the amount of dirname() calls accordingly. Again, this code is meant to be in ONLY ONE FILE.


Then do get the URL path, its a simple matter of removing the DOCUMENT_ROOT FROM ABSPATH:

$docRoot = rtrim($_SERVER['DOCUMENT_ROOT'], '/');
define('RELADDR', substr(ABSPATH, strlen($docRoot));
Andrew Moore
  • 93,497
  • 30
  • 163
  • 175
1

$_SERVER['DOCUMENT_ROOT'] will give you the path to htdocs, then you can go from there

EDIT

$_SERVER['REQUEST_URI'] will always give you /myapp/stuff/to/see from your sample url above, regardless of the files location on disk or from which file it is invoked.

so it only a matter of explodeing, array_shifting, and implodeing.

btw, from your directory structure, it looks like you're using a framework. some frameworks have a URI/URL library that you can find useful (at least CodeIgniter has, not 100% sure with other frameworks)

widyakumara
  • 1,065
  • 1
  • 9
  • 14
0

Try this:

 echo dirname(__FILE__);

where __FILE__ is the name of current executing script, and dirname gets folder/application folder out of it.

More Options:

echo $_SERVER['DOCUMENT_ROOT']; // gives you the root dir

On PHP.net

Sarfraz
  • 377,238
  • 77
  • 533
  • 578
0

I incurred a similar issue. Basically, in PHP if a file 'A.php' uses relative path to refer a resource, then the current path location used as a prefix to the relative path is of the top parent php under which 'A.php' is included.

This won't be a problem if A.php itself is top parent or when A.php sits at the same folder as is its top parent. But it will break the import otherwise.

The best solution I found was to make the reference explicitly absolute by using DIR (which gives current location of the file) and then going to the referred by from this location for e.g. DIR."/../help.php" to refer to a file help.php sitting 1 level above A.php.

saurabh.in
  • 389
  • 3
  • 13
-1

This is how bramus/router does it

function getBasePath()
{
    return implode('/', array_slice(explode('/', $_SERVER['SCRIPT_NAME']), 0, -1)) . '/';
}

Update:

To clarify, if you just want the resource path relative to getBasePath() above, then you can use

function getBaseURI()
{
    $basePath = implode('/', array_slice(explode('/', $_SERVER['SCRIPT_NAME']), 0, -1)) . '/';
    // Get the current Request URI and remove rewrite base path from it (= allows one to run the router in a sub folder)
    $uri = substr(rawurldecode($_SERVER['REQUEST_URI']), strlen($basePath));

    // Don't take query params into account on the URL
    if (strstr($uri, '?')) {
        $uri = substr($uri, 0, strpos($uri, '?'));
    }

    // Remove trailing slash + enforce a slash at the start
    return '/' . trim($uri, '/');
}

If your .php is in htdocs/myapp/ and the current URL is http://www.server.com/myapp/stuff/to/see

getBasePath() = /myapp/
getBaseURI()  = /stuff/to/see

IF your .php is in htdocs/ and the current URL is http://www.server.com/stuff/to/see

getBasePath() = /
getBaseURI()  = /stuff/to/see
Andrew Lim
  • 196
  • 3
  • 9
  • it returns a relative path, not absolute – Your Common Sense Mar 07 '23 at 07:39
  • Isn't that what the OP asked? "how can I extract the /myapp part?" – Andrew Lim Mar 07 '23 at 07:40
  • Don't you understand that for /myapp/, /myapp/stuff/, /myapp/stuff/to/ and /myapp/stuff/to/see your code will return a DIFFERENT result every time? – Your Common Sense Mar 07 '23 at 07:43
  • I've updated my answer. If you want /myapp, use getBasePath(), if you want /stuff/to/see regardless of the subfolder use getBaseURI() – Andrew Lim Mar 07 '23 at 07:53
  • You don't seem to understood my comment. your getBasePath returns ***different*** results depends on where it's called. it returns /myapp/stuff/to/see/ when called from /myapp/stuff/to/see/index.php – Your Common Sense Mar 07 '23 at 08:38
  • Yes getBasePath() returns the parent URI part of index.php. If you move index.php to somewhere else, of course it is different. But if you want the child path `/stuff/to/see`relative to index.php, you can use getBaseURI() in the updated answer, which will return the same result always. This solves OP's original question. – Andrew Lim Mar 07 '23 at 08:48
  • The OP didn't ask to get the parent URI part of index.php, that is /myapp/stuff/to/see/. He asked how to get /myapp/. BOTH your functions return relative paths and therefore unusable. – Your Common Sense Mar 07 '23 at 08:54
  • Like I said above, in case current url is http://www.server.com/myapp/stuff/to/see/index.php, getBasePath() = /myapp/stuff/to/see/. You don't seem to understand relative paths and that is the problem – Your Common Sense Mar 07 '23 at 09:53
  • I understand relative paths just fine. You are just not understanding the question. `/stuff/to/see` is virtual part of the application that index.php routes to. If index.php is moved into `/htdocs` or `/htdocs/myapp` or `/htdocs/myapp/a/b/c`, getBasePath() returns something DIFFERENT but getBaseURI() should always return the SAME `/stuff/to/see`, – Andrew Lim Mar 07 '23 at 10:12
  • *You* are nowhere getting "penalized". Your *answer* is down voted because being unreliable, based on the relative path to the file serving particular request, and therefore always returning different value. A correct answer would be $_SERVER['DOCUMENT_ROOT'] plus whatever path you consider an "app root" for a filesystem path, and / plus whatever path you consider an "app root" for a web-server path. – Your Common Sense Mar 07 '23 at 10:43
  • It's reliable. That's why routers likes bramus work in any subfolder you put them in: https://github.com/bramus/router#subfolder-support – Andrew Lim Mar 07 '23 at 10:46