I am attempting to move an old Intranet site running on Apache 2.2, to a WAMP setup (latest version) on my local machine.
One of the issues I have currently, is a require_once path failing to open, and I cannot determine what the cause is.
I have WAMP installed in:
C:\Wamp
I have changed http.conf and vhosts.conf to change the document root from
C:\Wamp\www
to
C:\Wamp\www\Intranet
This folder contains an index.php, which I can see being loaded correctly when browsing to localhost.
Index.php has an iFrame that loads welcome.php from
/site/welcome.php
This works, as the iFrame loads, but throws a 500 error.
Enabling PHP errors, the welcome.php page in the iFrame gives me an error on a require_once. The require_once is:
/site/login/config.php.
As you can see, I am using absolute paths here, so the fact that index.php is able to load /site/welcome.php, tells me it is loading the correct file from:
C:\Wamp\www\Intranet\site\welcome.php
I would expect then, my require_once with an absolute path to be loading:
C:\Wamp\www\Intranet\site\login\config.php
Which is a valid file path.
What is confusing me, is that the first absolute path I am using, seems to be starting from the document root, not the physical directory root.
The second absolute path I am using, does not seem to be starting from the document root.
Even more interestingly, if I change the require_once from:
/site/login/config.php
to
/login/config.php
It works?! I wouldn't expect it to, as that would suggest the absolute path I am specifying, is in fact a relative path?
I don't think this path (/site/login/config.php) makes sense on a windows machine.
Better than hardcoding the full file path, determine it on runtime.
E.g.:
define('ROOT_DIR', realpath(dirname(__FILE__)));
// because *nix and Windows path separators aren't the same (/ vs \)
define('DS', DIRECTORY_SEPARATOR);
// just for convenience sake, you could use DIRECTORY_SEPARATOR on its own.
Then including your config file, from welcome.php would be:
require_once(ROOT_DIR . DS . 'login' . DS . 'config.php');
I think that besides you are confusing the path that you use in the iframe declaration (which is a url path) with the path you use in the require (which is a filesystem path).
How i tend to resolve most of my include/require errors is by setting a variable path:
$path = dirname(__FILE__);
include($path.'/file.php');
This will prevent you from having trouble with different environments in this case being windows and linux.
Or even better:
define('ROOTPATH', realpath(dirname(__FILE__) . '/'));
require ROOTPATH.'login/config.php';
Another thing, probably not causing your issues, but being good practice is to set the DIRECTORY_SEPaRATOR.
define('DS', DIRECTORY_SEPARATOR);
include(DS.'home'.DS.'www'.DS);
This will make PHP use the correct slash (either / or \)
Related
In my php project I try to include another file. However, I find it very confusing how the include statement works.
e.g.
I include the file HelperFile.php in index.php. Both files are in the same directory.
This works: include 'HelperFile.php' but this doesn't include '/HelpferFile.php' & include './HelpferFile.php'
The warning I receive:
PHP Warning include(/HelperFile.php): failed to open stream
Out of curiosity I created a folder and moved my file HelperFile.php into it and nothing changed. Everytime I tried to use the relative path with ./, ../ or /I received a warning.
Can someone explain me what's going on. I'm still learning and can'f figure out what's happening right now.
PHP isn't so great with relative paths, it generally prefers absolute paths. The easiest way around this is to use the DIR magic constant which returns the current directory of the file you're currently in.
So, for instance, you can do include(__DIR__ . '/HelperFile.php'); which would be in the current directory.
However say you had a file in a folder up you can do
include(__DIR__ . '/../MyOtherFile.php');
PHP Doc says
If a path is defined — whether absolute (starting with a drive letter
or \ on Windows, or / on Unix/Linux systems) or relative to the
current directory (starting with . or ..) — the include_path will be
ignored altogether. For example, if a filename begins with ../, the
parser will look in the parent directory to find the requested file.
If you use . or .. will ignored for relative path Also use ../ for parent directory.
Is this, for example, a good idea?
require_once($_SERVER['DOCUMENT_ROOT'].'/include.php');
If you have two virtual hosts on the same server, one for live and one for development, with different Apache DocumentRoots, this would avoid having to include absolute paths when the source of the include is unknown, and may be in any directory.
(Note: file paths in the following section are relative to the web root. They would in fact be like /var/www/app/core/init.php, where /var/www/app is the web root)
For instance: I have an /core/init.php which is called using relative paths from places all over the website (/file.php, /dir/file.php or /dir/dir/file.php).
This init.php then includes several function pages, in the fund directory, a subdir of /core (as in /core/func/userfunctions.php).
So, in init.php, I can use the $_SERVER method, because it breaks if I use a relative path and try to call functions from a page like /dir/file.php.
I can't see any problem with it, but in general what could go wrong?
I've seen cases where $_SERVER['DOCUMENT_ROOT'] is not set or is not what you would expect (i.e. not set in CLI or old IIS, or invalid in certain CGI setups).
For that reason you can use dirname(__FILE__) to obtain the path of the script that line is called in. You can then reference relative paths from there e.g.
include dirname(__FILE__) . '/../../other/file.php';
I go with the above method when the directory structure of the files is known and is not subject to change.
If DOCUMENT_ROOT is not available, the following is a suitable replacement:
substr($_SERVER['SCRIPT_FILENAME'], 0, -strlen($_SERVER['SCRIPT_NAME']));
You don't need to do this. PHP looks for the included file in the document root by default.
You can use set_include_path($new_include_path) to change this behaviour, or edit include_path in the php config file.
Also, from http://php.net/manual/en/reserved.variables.server.php:
'DOCUMENT_ROOT'
The document root directory under which the current script is executing, as defined in the server's configuration file.
For example, if you use URL rewriting, you will be very happy when you find out that the includes in your /there/are/so/many/paths/in/the/url/of/this/ page are still working!
What's the difference between
$_SERVER['DOCUMENT_ROOT'];
and
dirname(__FILE__);
I wonder what's the difference because when I 'echo' them, they're returning same path. Which do you prefer should I use and why?
Thanks!
Both are different
_FILE_
The full path and filename of the file. If used inside an include, the name of the included file is returned. Since PHP 4.0.2, FILE always contains an absolute path with symlinks resolved whereas in older versions it contained relative path under some circumstances.
source : PHP magic constants
Let's said, your document is /var/www,
and your index page is /var/www/index.php
dirname(__FILE__) == $_SERVER['DOCUMENT_ROOT'];
But if you drill-down to sub-folder like /var/www/posts/index.php
dirname(__FILE__) != $_SERVER['DOCUMENT_ROOT'];
/var/www/posts != /var/www
The use of $_SERVER['DOCUMENT_ROOT'] is more appropriate in this case.
__FILE__ always points to the current file path, and $_SERVER['DOCUMENT_ROOT'] points to the document root path ;-)
I prefer first one, as it is more semantic.
If you will try to compare the values of the files, that are located not in your docroot - then you'll get different values.
The former one is a root folder for the HTTP server (or VirtualHost) and it is a server setting.
The latter is the folder containing the current file.
The usage is entirely based on requirements in my opinion.
You would normally use $_SERVER['DOCUMENT_ROOT'] when you want to reference your website's root folder from any where within your website or web application.
You will find using dirname(__FILE__) handy if you were including a file, that then needed to include some more files from the same directory. I use this in my PHP wrapper for the Dribbble API
class Dribbble {
function __construct() {
require_once(dirname(__FILE__) . '/base.php');
require_once(dirname(__FILE__) . '/shot.php');
require_once(dirname(__FILE__) . '/player.php');
}
}
This means I can just include dribbble.php from any where in my website or web application and not worry about also including base.php, shot.php, and player.php at the same time.
I know this has to do with the path not being quite right but it has me baffled. I can run my script with no problems at all from the browser but when I do to the exact same spot from a shell, spl_autoload complains and dies:
Fatal error: spl_autoload(): Class db
could not be loaded in...
I am using the absolute path from the root directory, echoed to screen and pasted it into a shell and verified that it is good. Please... what am I missing??
Try using the __DIR__ constant to locate the files, CLI PHP doesn't uses the same working dir.
Use something like this:
function __autoload($class)
{
require_once(dirname(__FILE__) . '/path/to/libraries/' . $class . '.php');
}
you can usually grab your root directory for the project with something along the lines of :
// The file that defines this is 2 directories below root, hence the ../ changes.
define('PATH_ROOT', realpath(dirname(__FILE__) . '/../../'));
Once you have your root path you can modify your include path, using set_include_path. (remember to include get_include_path when you set it otherwise you'll lose the defaults)
once thats sorted, just setup your autoloader assuming against the root dir and you should be fine, since its a bit more concrete than relying on relative paths which can change according to the working dir.
I'm testing a website on my local machine and I'm wondering what would be the best way to write paths to make sure they work when I upload the site to its final location.
In general I'm a bit confused about paths, and in many cases I have to 'tweak' each path until it works, so wouldn't want to be forced to do the same on a production site!
I'm not clear when to use $_SERVER['DOCUMENT_ROOT'].
For example, I have a directory that I want to scan, which is just under the root. So why can't I just use "/dirname"?
$dir = $_SERVER['DOCUMENT_ROOT'] . '/uploads'; //this works
// $dir = "/uploads"; //this doesn't work
if (is_dir($dir)) {
//do something..
}
I'm not clear when to use
$_SERVER['DOCUMENT_ROOT']. For
example, I have a directory that I
want to scan, which is just under the
root. So why can't I just use
"/dirname"?
When you work with paths in the php file the root (/) is the root of the filesystem, not the root you get when you visit your website.
So $dir = "/uploads"; gives you the filesystem root.
To minify your problems I would declare a variable in a configuration file that specifies the root of your php application, and use that path+whatever more is needed.
As adamse mentioned, the reason you can't use the '/path' is because it points to the root of the filesystem.
However, instead of declaring a variable that defines the root, I recommend using dirname(__FILE__) to retrieve the full path to the directory that the calling file is in.
From there, append relative path information to the file you want and you end up with a complete path, fully dynamically.
For example, if you want to include the 'header.php' file in the directory above the file that you wish to include it in use:
include(dirname(__FILE__) . '/../header.php');
The beauty of that is that PHP will always automatically convert the forward slash to the directory separator required for the host OS.
I would define a variable/constant that describes the absolute filesystem path to the application. Something like this:
$appDir = rtrim(str_replace('\\', '/', realpath(dirname(__FILE__))), '/');
Then you have this base path you can address your application’s files from:
include $appDir.'/library/foo/bar.php';
Or you even change your include path to that directory:
set_include_path($appDir);