Jump to content

Archived

This topic is now archived and is closed to further replies.

brian914

$_SERVER['DOCUMENT_ROOT'] as path to root?

Recommended Posts

I am pretty new to php, so I apologize if this is a stupid question. I am building a web site and have include files that get used from the root and different sub directories within my site. For example I have a header include that gets used from files both on the root level and inside directories. Inside that header I need to for example call a style sheet. I am trying to do this like this: 

<link rel="stylesheet" href="<?php echo $_SERVER['DOCUMENT_ROOT']; ?>/css/style.css">

 

If I look at the source that this generates, here is what it looks like which is the correct path I think:

<link rel="stylesheet" href="/Users/brian/Documents/Client Name/6_WebFiles/css/style.css">

 

But somehow the stylesheet does not seem to work. What am I doing wrong here?

 

Thanks a lot for help!

Share this post


Link to post
Share on other sites

you may need to do

 

<?php
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
$domain_name = $_SERVER['HTTP_HOST'];
$site_url = $protocol.$domain_name;
?>

<link rel="stylesheet" href="<?php echo $site_url ?>/css/style.css">

Share this post


Link to post
Share on other sites

You don't need to add anything.  If you do this...

 

<link rel="stylesheet" href="/css/style.css">

 

...the browser will automatically make a relative link that starts from the "public root" dir, for example 

 

http://www.yoursite.com/css/style.css  (or https if the page is ssl). 

 

Alternatively, if you do this, without the beginning forward slash...

 

<link rel="stylesheet" href="css/style.css">

 

...the browser will make a relative link that is relative to your current page.  So for instance if you are currently on

 

http://www.yoursite.com/path/to/page.html

 

it will make the link

 

http://www.yoursite.com/path/to/css/style.css

 

 

Share this post


Link to post
Share on other sites

Thank you so much for the help everyone!

 

I really like the second solution for its simplicity and am wondering how I can apply that to include tags, which I can't seem to make work yet. While this seems to work:

<img src="/img/home/home-04.jpg" alt="Home Image">

This doesn't work:

<?php include '/inc/head.php'; ?>

 

I have includes inside other includes files, so they still would all have to know where the "root" is.

 

Thanks a lot!

Share this post


Link to post
Share on other sites

Okay so here is the short version

 

Basically it boils down to this: There are two different definitions of "document root" depending what you are trying to do.  The "document root" is different for these two things, because in each example, the code is being evaluated by two different entities in two different contexts.  In the first example, you have a client that is looking at a relative location on a remote server.  In the second example, you have a server looking at a relative location to itself. 

 

When including a server-side script in your server-side code, you need to use that $_SERVER['DOCUMENT_ROOT'] for an server's-perspective absolute path/to/file, or else make the path relative to the running script.  If the /inc in /inc/head.php is in the same directory as yourscript.php that is including it, you need to remove the forwardslash prefix and just include 'inc/head.php'.  If you need to go up a dir level then you prefix it with ../inc/head.php

 

When including an image for client-side code to be evaluated by a client, you can do as explained in the previous post.

 

 

The TL;DR version

 

Let's put this in human terms to better understand it.  Most everybody has a "public" face that they share with most people, and a separate "private" face that they share with few or no people.  The "public" face is the information about themselves they are willing to share with most anybody.  For instance, lets say you, as a random internet stranger, ask me where I live.  I might be willing to tell you the country I live in, possibly the state/zipcode I live in, and possibly even the city I live in.  So as far as you are concerned, I live in /city/zipcode/state/country/.  This is like your first example with the image link.  You are the client (the browser on a visitor's computer) asking for the location of an image.  You are provided with a relative link, and you know the domain is www.xyz.com, so as far as you are concerned, the path starts at /img/, like xyz.com/img/.., because the relative link started with a forward slash. 

 

But the city I live in is a big city.  There are zones and neighborhoods and streets and houses.  And even if you know my home address, my own home is broken down even further into different rooms.  From my perspective I "live" at my house, more specifically, my personal bedroom where I sleep in.  So from my perspective, I live in /[my room]/[house/lot number]/street/city/zipcode/state/country/.  This is like your second example, with including a file in a script.  I am the server, running a script on myself, referencing a location of a file somewhere within me.  The script provides a relative link to some file, and the domain means nothing in this context (I can look at the domain for other purposes but for this purpose, I already know what domain I am on so it is meaningless to prefix the file with a domain) so as far as I'm concerned, the path starts at /inc/, literally /inc/head.php... but that's not where the file is really located.  From my (the server's) perspective, the file is really located at /[my room]/[house/lot number]/street/city/zipcode/state/country/inc/head.php

 

But it's a pita to have to type all that out in your coding.  That is where that $_SERVER['DOCUMENT_ROOT'] environment variable comes into play.  It contains the full directory path, starting at the server root (from the server's perspective) to the root directory that is displayed to the outside world (the client's perspective).  So in this example, $_SERVER['DOCUMENT_ROOT'] would be /[my room]/[house/lot number]/street/city/zipcode/state/country, so if I do

 

<?php include $_SERVER['DOCUMENT_ROOT'].'/inc/head.php'; ?>

 

It should work out just fine. 

 

NOTE: If you had removed the forwardslash prefix in your include, like this:

 

<?php include 'inc/head.php'; ?>

 

This would have made the server try to locate the file, relative to the script that is running.  So for instance, lets say your script is called myscript.php and it is located here:

 

www.xyz.com/myscript.php

 

or from the server's perspective it is located here:

 

/[my room]/[house/lot number]/street/city/zipcode/state/country/myscript.php

 

If you take off the forwardslash prefix, it would try to look for the include here:

 

/[my room]/[house/lot number]/street/city/zipcode/state/country/inc/head.php

 

Which may actually be accurate, if that's how your two scripts are located, relative to each other.  Or lets say your myscript.php is located in its own subdir (relative to root), so it's on the same level as myscript.php but in a different subdirector. Ffor instance

 

www.xyz.com/control/myscript.php

www.xyz.com/inc/head.php

 

or

 

/[my room]/[house/lot number]/street/city/zipcode/state/country/control/myscript.php

/[my room]/[house/lot number]/street/city/zipcode/state/country/inc/head.php

 

Without the forwardslash prefix, it would try to look for it here:

 

/[my room]/[house/lot number]/street/city/zipcode/state/country/control/inc/head.php

 

which wouldn't work.  But you can still tell the server to look for the file, relative to the running script, by using ../.  This tells the server to move up one directory level before looking for the rest of the path.  So for instance if your structure looks like this:

 

/[my room]/[house/lot number]/street/city/zipcode/state/country/control/myscript.php

/[my room]/[house/lot number]/street/city/zipcode/state/country/inc/head.php

 

You can do this:

 

<?php include '../inc/head.php'; ?>

 

And you can stack ../ to keep backing up dirs, all the way to the server root.  NOTE: you can use ../ with the img src url that the client looks at, as well.  But the difference is, as far as the client is concerned, /country is the root dir (and it doesn't even know what that dir is, it has the www.xyz.com as the placeholder), so from its perspective, doing ../../head.php would *technically* work in this case, because once it gets to the root dir from its perspective, it ignores further ../ but it will not try to look for it at /[my room]/[house/lot number]/street/city/zipcode/inc/head.php (same level as /country/) because as I said, from the client's perspective, the document root starts at /country/.

 

 

One additional note to really make your head hurt if it hasn't been twisted in knots already:  While this is all you *really* need to know for your purposes, note that even this isn't the complete story.  Depending on the server setup, the actual real root dir of the server may go even more deeper than /my room/.  This is common in for instance shared hosting environments, where multiple people share the same server.  There would for instance be the real server root, and a directory for each user account and from their perspective, the root is really a "root" that starts at their account home directory.  And the rabbit hole goes deeper still, because...ah fuck it, you're head probably esploded by now.

Share this post


Link to post
Share on other sites

Wow, amazing! Thank you so much Josh! I so very much appreciate the help!

 

I have one last question in regards to your last comment: "This is common in for instance shared hosting environments, where multiple people share the same server." I guess I am a little bit worried about this, as in my experience, a lot of servers do share. So I was hoping to create a place where I could set a variable referring to "my root". I would like to do this, so if all of a sudden, when I move this to the actual server, or a different server, I could just set the "root" in one place, instead of having to go through all my code and look for the "$_SERVER['DOCUMENT_ROOT'].'/" and make the adjustment in many places.

 

I was hoping there was something I could set in one place, like so:

$my_root =  $_SERVER['DOCUMENT_ROOT'] . '/somedirectory/';

 

Then I could use $my_root the rest of the time, instead of $_SERVER['DOCUMENT_ROOT']. But not sure if that is possible and not sure where that would reside? Maybe this is a pipe dream...

Share this post


Link to post
Share on other sites

you should be fine on that count, no worries.  Server root is always /.  The difference is what may be hiding behind the curtains depending on who is requesting it and from what context.  Just like with a browser requesting a page on your website, like  /index.php, the "root" starts at the designated "public root" folder that your domain resolves to.  There is usually a file like http.conf somewhere on the server that basically has instructions that say "if the domain is www.xyz.com, "/" starts in "/this/folder/here/" so going to "www.xyz.com/index.php" makes the server look in "/this/folder/here/index.php"

 

that same principle carries over when a server is running a server-side script on a shared server.  So if you are on a shared server and you have a script that does like

 

include "/somefile.php";

 

There is another file somewhere on the server that basically says the same thing in principle: starting "/" really means like "/[user]/".

 

So if you start on a shared server, for your user account, your root is / even though there is technically more structure above that.  The server routes it to the correct /[user account/ "root" based on ...well it depends on the server setup.  Some server setups will always automatically prefix your username as the beginning dir in the document root.  So for instance, if I go to

 

http://www.mysite.com/index.php

 

 

$_SERVER['DOCUMENT_ROOT'] might be /josh/htdocs/ or it might just be /htdocs/ (server may or may not show your user dir)

 

So a relative link in an img tag requested by a client as "/image.jpg" would resolve to (absolute path from client's PoV) :

 

http://www.mysite.com/image.jpg

 

and internally (server absolute path) be

 

/josh/htdocs/image.jpg

 

But with a server-side include for instance if I do this:

 

<?php include "/myscript.php" ?>

 

With a shared server, the real root path would be [ic]/ and all accounts might be in a /users/ dir so from someone who has access to the real server root, they would see it as

 

/users/josh/htdocs/myscript.php

 

But from the user's perspective, /josh/ is the highest level they have access to, so they would only see

 

/josh/htdocs/myscript.php

 

or depending on server setup, even only see

 

/htdocs/myscript.php

 

and that is usually reflected in $_SERVER['DOCUMENT_ROOT'].  For portability, like if you were to migrate to a dedicated server, you don't really need to worry about this.  $_SERVER['DOCUMENT_ROOT'] should always show the root path of the user account running the script, to the "public" document root, whether the account is the root/su (super user) account or some other account without root directory access. 

 

So if you have

 

include $_SERVER['DOCUMENT_ROOT']."/myscript.php";

 

It should work if you port your script from shared to dedicated, or whatever.

 

 

Share this post


Link to post
Share on other sites

Okay great. That is even better than what I thought it could be then!

 

Thank you very very much! This is really nice of you to take all this time to answer my questions!

Share this post


Link to post
Share on other sites

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.