...

View Full Version : Need help with SSI paths in php



andrew55
10-08-2012, 07:35 AM
I just migrated to a new hosting account. Almost all of my files are in php. In my last hosting account, to create a server side include, I used something like:


<?php
require_once($_SERVER['DOCUMENT_ROOT'].'/includes/header.php');
?>

New hosting account won't seem to let me do this. Everything has to be relative such as


<?php
include ("../includes/header.php");
?>

But...this also seems to work in the new hosting account:



<?php
include ("includes/header.php");
?>

Is it OK to code all SSIs as demonstrated in the last example, or is this a bad practice. Having to set the relative paths will be much more complex and time consuming so I'm trying to avoid it. Thank you for any suggestions.

Fou-Lu
10-08-2012, 08:10 AM
These aren't actually SSI's. These are inclusions which effectively assemble the parts from smaller parts. SSI's are interpreted during the serve, while the includes are interpreted during the request. The virtual() function can be used to create actual SSI's if for whatever reason you need them.

I do not recommend simply using a flat path unless its taken well into control. Inclusions and requires are always based off of the executing file's working directory, regardless of the depth of the files used for including. For this reason, only your first example is the proper usable one.
You can get around this by setting include paths (using set_include_path and get_include_path to append). This lets you search a directory for these paths and then include. It is based on order it is found.
If you like the relative, always go relative to this file. So in that second example, it would be require_once __DIR__ . '/../includes/header.php';, or dirname(__FILE__) if you're on an older version of PHP. Unless there is a particular need for it, don't use a regular require or include, always use the _once function to avoid stomping created variables, and avoid fatal errors on already declared functions, constants, classes, etc. Prior to this, we would use a defined() check, but that is no longer necessary. Also, you'll very rarely need an actual include; mostly you are constructing out of other pieces, so these are typically required.

andrew55
10-08-2012, 05:03 PM
Fou-Lu,

Thank you for your thorough response. When I use the first example, I receive this error message:


Warning: require_once(/usr/local/apache/htdocs/includes/header.php) [function.require-once]: failed to open stream: No such file or directory in /home/mysitename/public_html/index.php on line 25

Fatal error: require_once() [function.require]: Failed opening required '/usr/local/apache/htdocs/includes/header.php' (include_path='.:/usr/lib/php:/usr/local/lib/php') in /home/mysitename/public_html/index.php on line 25

So for some reason, the "require_once($_SERVER['DOCUMENT_ROOT']" call is not working properly on my new server.

Any ideas on how to modify this to get it working properly? You mentioned this is the proper method and I prefer it much more than using relative paths. Thank you for any suggestions.

Fou-Lu
10-08-2012, 05:57 PM
No it sure isn't working. They've managed to do something to rewrite it. DOCUMENT_ROOT should be virtually mapped to you, but it clearly isn't:


/usr/local/apache/htdocs/includes/header.php
/home/mysitename/public_html/index.php

The DOCUMENT_ROOT should be pathed to /home/mysitename/public_html, but it has been improperly configured from the looks of it. Best to contact your host about that.

Do the relative to this directory approach. Overall its far more useful anyways since you can use it in cron jobs while DOCUMENT_ROOT cannot be (unless you manually set it).


require_once __DIR__ . '/../includes/header.php';

The only thing to remember is you will now always go relative to THIS file that the require is called in, not to the file that is currently executing. This does make nested includes a lot easier to work with though since you never need to concern yourself with where it is running from.

andrew55
10-08-2012, 10:17 PM
I talked to the hosting account techs and although they are a great company, they let me know setting the document root functionality is not natively supported in their cPanel at this time.

I have a couple thousand SS includes (or whatever they technically are) that I will have to edit in the site, and I am trying to avoid using relative paths for this reason - this seems as if will be very time consuming

Just to make sure I understand, the following method does work when I test it, but you are suggesting that I do not use this method?




<?php
include ("includes/header.php");
?>


Thank you for any suggestions.

Fou-Lu
10-09-2012, 12:15 AM
You should never use a relative path alone since their paths are resolved to the current working directory which is always the executing script. Doing so will mean you cannot change the nesting. If you include this file in a file that's two directories below it, it will attempt to load includes off of the directory two below. Using __DIR__ resolves this as it will always be relative to this script, not the executing script.

andrew55
10-09-2012, 01:01 AM
Upon testing, this example seems to work:



<?php
require_once __DIR__ . '/includes/header.php';
?>


Just to confirm, would this be the correct method? My apologies for all of the questions, I'm just trying to make sure I understand this correctly.

andrew55
10-09-2012, 03:13 AM
I think I understand..if the file is in the root, it should be:


<?php
require_once __DIR__ . '/includes/header.php';
?>

If it's one directory deep, it should be:


<?php
require_once __DIR__ . '/../includes/header.php';
?>

If it's two directories deep, it should be:


<?php
require_once __DIR__ . '/../../includes/header.php';
?>

etc...

Please confirm this is correct and thank you.

Fou-Lu
10-09-2012, 03:23 AM
By deep, you mean this file right?
Then yep that's exactly what that is. That second one would take this file, and move up two directories to find includes/header.php. The difference in this route is (as mentioned) the use of inclusion nesting:


/
- index.php
-- includes
- header.php
- footer.php
-- functions
- generic.php

With the above, if you were to include the generic.php within the header.php, that would be require_once '../functions/generic.php';. However, if you include header.php into index.php, then it will throw a fatal error since it cannot find /../functions/generic.php. This is why if you use a relative path you should make it relative from this file, not from an unknown working directory. By putting __DIR__ or dirname(__FILE__) on older PHP versions gets around this. Now when you include header, it will always look a directory up from the header file, not from the index file.

andrew55
10-09-2012, 03:42 AM
thank you very much - now it's off to work to change quite a few of these



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum