Wondering if anyone can provide some help / tips for a problem we’ve encountered in WACT. Can imagine other people are having the same problem.
Basically we need a way to determine that path of the script where execution began from within WACT.
Typically when using WACT you’d begin a script like;
Code within WACT then needs to be able to determine where myscript.php is located in the filesystem, so that a users templates, for example, can be located relative to myscript.php’s path.
This may seem like a simple problem to solve, by simply using;
$myscript_path = dirname($_SERVER['SCRIPT_FILENAME']);
Unfortunately this only works on some PHP configurations - when PHP is used as a CGI executable (and probably the same for the CLI variant) contains the path to the PHP executable, not the PHP script where execution began.
An alternative option which seemed to look good for a short time was;
$myscript_path = dirname($_SERVER['PATH_TRANSLATED']);
Looking at the PHP bugs list though, there seem to have been issues with this variable, relating to the Apache version being used. Worse news is it’s been completely dropped from PHP5, mentioned here.
Any other ideas for how to reliably determine the path of the script where execution began? Beginning to wonder if PHP needs a predefined constant such as __MAIN__ which handles this independent of PHP install.
Jeff highlights the problem in more detail here.






June 8th, 2004 at 7:29 am
Just wondering: Are either of those techniques affected if you use mod_rewrite and the address they types into the browser isn’t necessarily the address they end up at?
June 8th, 2004 at 8:01 am
I use mod_rewrite heavily, which has a similar effect in that you can’t trust pathnames (although $_SERVER[PHP_SELF] may still work).
Anyway, my solution is to define a set of variables regarding paths (normally http path and file path, sometimes https), so the only known path necessary is the core included file; everything can use absolute paths using the core include’s defined vars. Example:
$path['http'] = /var/www/sitex;
include($path['http'].’/includes/x.php’);
June 8th, 2004 at 8:10 am
It’s not super elegant, but you could start every script with:
if (!defined(’MAIN_EXEC_DIR’)) define(’MAIN_EXEC_DIR’, dirname(__FILE__));
Then MAIN_EXEC_DIR would always contain the information you are looking for. Certainly, it’s a pain to have to put this in every file, though.
Another option is to actually make use of the include_path INI setting, which can also be altered at run time via ini_set().
June 8th, 2004 at 8:42 am
I don’t have php as cgi so cannot test it, but maybe this will work (only PHP 4 >= 4.3.0, PHP 5):
< ?php // common.inc.php if (function_exists('debug_backtrace')) { $tmp = debug_backtrace(); $_SERVER['PATH_TRANSLATED'] = $tmp[0]['file']; } ?>June 8th, 2004 at 9:06 am
Btw.
Why do you need $_SERVER['PATH_TRANSLATED'] for this ?
If the script is called like this: http://domain.foo/some/myscript.php, template is here: /some/templates/example.tpl, relative path to template: ‘templates/example.tpl’, why can’t you just do: require ‘templates/example.tpl’ ?
Or maybe this:
require $_SERVER['DOCUMENT_ROOT'] . dirname($_SERVER['PHP_SELF']) . “/templates/example.tpl”;
June 8th, 2004 at 9:46 am
Perhaps this is helpful - Seagull dynamically determines the the script location on the filesystem and the web root of the calling URL. To do this each page execution first loads an init file:
http://muse23.com/cgi-bin/cvsweb.cgi/seagull/init.php?rev=1.84&content-type=text/x-cvsweb-markup
cheers
Demian
June 8th, 2004 at 10:37 am
[QUOTE=cyngon]Just wondering: Are either of those techniques affected if you use mod_rewrite and the address they types into the browser isn’t necessarily the address they end up at?[/QUOTE]
Good question. Not sure. Will explore that shortly.
June 8th, 2004 at 10:46 am
I guess that will be the last resort. Would be a shame because it requires WACT users to define it (nice when it could happen automatically).
Good point. OK it’s PHP 4.3.0 only but perhaps we can use that inside some code which makes various guesses (using SCRIPT_FILENAME, PATH_TRANSLATED and any thing that might be useable).
That may be an option to explore. We need the path for various file operations (e.g. writing a “compiled” template script) but fopen also supports using the include_path - good point.
Possibly - think those are also somewhat subject to the PHP SAPI you’re using but may be useful if we’re doing some sort of detection.
June 8th, 2004 at 12:28 pm
whilst I was discussing the need for a __MAIN__ constant with Lukas Smith, Ilia chimed in with this little tid-bit:
array_shift(get_included_files());
Should work in any PHP version 4.0.0 up :)
- Davey
June 8th, 2004 at 12:30 pm
Whilst discussing the need for a __MAIN__ constant with Lukas Smith on IRC, Ilia chimed in with this little tid-bit:
array_shift(get_included_files());
Yay Ilia! This should work in PHP 4.0.0+ :)
- Davey
June 8th, 2004 at 2:43 pm
How about getcwd()? This returns the current working directory, and unlesse the user somewhere used chdir(), the cwd is the dir of the main entry point.
June 8th, 2004 at 3:13 pm
Phew! Nice one Davey - many thanks.
PS: __MAIN__ would still be cool.
June 8th, 2004 at 6:54 pm
I know that Ilia is pretty opposed to a __MAIN__ constant… so I guess the only way to do this is:
if (!defined('__MAIN__')) { define('__MAIN__', array_shift(get_included_files())); }- Davey
October 7th, 2004 at 9:46 pm
I have used the array_shift(get_included_files()) technique successfully until now. On a server with PHP version 4.1.2 using apache with mod_php, the main script was not in this array.
There is a bug where someone is complaining about the main file being in the array: http://bugs.php.net/bug.php?id=25658.
So unfortunately, this will not always work.
June 20th, 2006 at 6:30 am
I know at least one place where a programmer has used
eval(file_get_contents(’some_script.php’)) to include a file.
I don’t exactly remember why but it solved a nice security
problem.
The array_shift(get_included_files()) won’t work in this case
either.
July 19th, 2006 at 8:21 am
getcwd() is the solution I chose :)