在不知道底层文件系统的情况下在PHP中加载文件

One of the ncie things about PHP is that if you do an include/require it works off the directory where the file is (or rather the URI of the request). That means that if you want to include further file you don't need to know from where the original script is running. All you need to know is where the current script is.

Now I want to load a text file and process it. file_get_contents() seems an obvioius way of loading it. The problem is I don't have that same luxury. I either need to specify the file path absolutely, which I don't want to do, or I have to know the location relative to the file that initiated the call, which I don't like either.

Require/include don't seem to work with non-PHP files and that would essentially echo the contents anyway (yes I know I could wrap that in an ob_start(), etc).

Suggestions?

You can get the directory associated with the current file using

dirname(__FILE__)

So you could do something like this:

file_get_contents(dirname(__FILE__) . '/foo.txt')

Define a constant with your desired path to the file, wherever you'd normally put configuration settings. Keeps it simple and customizable.

For one, note that the "relative path" will be from wherever the first php script's path was that is currently running (regardless of what file may be doing the including"). Not being able to specify a relative path sounds odd...

Having to know the path of things is common in the website world. You can store a part of the path, like the beginning in a config variable, something like $config['include_dir']; Specifying the path of a file is as easy as saying include($_SERVER['DOCUMENT_ROOT'] . '/includes/myinclude.inc.php');

I don't know how else you would know what file to include.

You're going to need the absolute path to open a file. You can use realpath() convert a relative url path to the absolute path.

If I understand the documentation for file_get_contents correctly, you can just pass true as a second parameter and the include_path will be used. So, on my system

echo file_get_contents('doc/DB/doc/STATUS', true);

will echo the STATUS document from my PEAR module, because the /usr/share/pear is in my include_path. And while we're at it, I'm not convinced that include() or require() will work on relative paths either unless '.' is part of the include_path. I'll check on that.

Update: Ok, I checked. As it turns out, include() will always consider the current directory as well, no matter what the include_path says.

Check out the $_SERVER properties. http://us2.php.net/manual/en/reserved.variables.server.php

You want

$_SERVER['DOCUMENT_ROOT'];

require/include are resolving the absolute path from both paths, the current script file’s and the initial executed script file’s:

Files for including are first looked for in each include_path entry relative to the current working directory, and then in the directory of current script. E.g. if your include_path is libraries, current working directory is /www/, you included include/a.php and there is include "b.php" in that file, b.php is first looked in /www/libraries/ and then in /www/include/. If filename begins with ./ or ../, it is looked only in the current working directory. — http://docs.php.net/include

But using absolute paths is better so PHP doesn’t need to “guess” which file is meant.

To answer your question it seems to me you'll need to write your own include equivalent to return file contents from any number of possible paths. Configure a series of paths in an array and have your function loop through it, use file_exists() and load file contents if the file is found.

Filesystem functions: http://us2.php.net/manual/en/ref.filesystem.php#73954

Also note there are php constants for filesystem path separator for example: DIRECTORY_SEPARATOR , however you don't really need it for portable file paths as forward slash "/" works on Windows.

Ps: A trick often used in Symfony to get absolute paths is:

$path = realpath(dirname(__FILE__)).'/whatever.txt';

I don't know if you have control over the contents of the file that you're trying to load, but if you do, you could try using smarty templating engine (http://www.smarty.net/)

You'll need to put '{include file="relative/file/path.ext"}' in the files that you're trying to load, but smarty will at least take care of dealing with all the relative paths and confusion for you.

PS: Documentation for the include tag is here:http://www.smarty.net/manual/en/language.function.include.php