问题
So basically, I'm writing a framework, and as part of it features, it's supposed to provide a set of well-established URIs/paths to the end-developer.
Some two of these paths make use of $_SERVER['DOCUMENT_ROOT']
:
/**
* Absolute filesystem path to web root install (aka docroot).
* @example "C:/wamp/www" OR "/home/visitgoz/public_html/"
*/
CFG::set('ABS_WWW',
str_replace(
$tmpseps,
DIRECTORY_SEPARATOR,
truepath($_SERVER['DOCUMENT_ROOT']).'/'
)
);
/**
* K2F path relative to web root.
* @example /K2F/
*/
CFG::set('REL_K2F',
str_replace(
array('//','\\'),
'/',
str_replace(CFG::get('ABS_WWW'),'/',CFG::get('ABS_K2F'))
)
);
The code has been fine-tuned to work on both Linux and Windows. Apparently, it works most of the time on Linux, quite seamless in fact on VPSes.
However, as of late, I tried it on an HG Reseller Account (shared hosting) and it all broke up. I've printed out data inside $_SERVER on the problematic machine:
Array
(
** [DOCUMENT_ROOT] => /usr/local/apache/htdocs
[GATEWAY_INTERFACE] => CGI/1.1
[HTTP_ACCEPT] => text/html,application/xhtml+xml,application/xml;q=0.9;q=0.8
[HTTP_ACCEPT_CHARSET] => ISO-8859-1,utf-8;q=0.7,*;q=0.7
[HTTP_ACCEPT_ENCODING] => gzip,deflate
[HTTP_ACCEPT_LANGUAGE] => en-gb,en;q=0.5
[HTTP_CONNECTION] => keep-alive
[HTTP_COOKIE] => <snip>
[HTTP_HOST] => <snip>
[HTTP_KEEP_ALIVE] => 115
[HTTP_USER_AGENT] => <snip>
[PATH] => /bin:/usr/bin
[QUERY_STRING] =>
[REDIRECT_STATUS] => 200
[REMOTE_ADDR] => <snip>
[REMOTE_PORT] => 49262
[REQUEST_METHOD] => GET
[REQUEST_URI] => /~sitename/
** [SCRIPT_FILENAME] => /home/sitename/public_html/index.php
[SCRIPT_NAME] => /~sitename/index.php
[SERVER_ADDR] => <snip>
[SERVER_ADMIN] => <snip>
[SERVER_NAME] => <snip>
[SERVER_PORT] => 80
[SERVER_PROTOCOL] => HTTP/1.1
[SERVER_SIGNATURE] =>
Apache mod_fcgid/2.3.5 mod_auth_passthrough/2.1 mod_bwlimited/1.4 FrontPage/5.0.2.2635 Server at <snip> Port 80
[SERVER_SOFTWARE] => Apache mod_fcgid/2.3.5 mod_auth_passthrough/2.1 mod_bwlimited/1.4 FrontPage/5.0.2.2635
[UNIQUE_ID] => TVox-Eo1Z8IAAG1kAh4AAAEZ
[PHP_SELF] => /~sitename/index.php
[REQUEST_TIME] => 1297756668
[argv] => Array
(
)
[argc] => 0
)
And my machine:
Array
(
[HTTP_AUTHORIZATION] =>
[HTTP_HOST] => <snip>
[HTTP_USER_AGENT] => <snip>
[HTTP_ACCEPT] => text/html,application/xhtml+xml,application/xml;q=0.9;q=0.8
[HTTP_ACCEPT_LANGUAGE] => en-gb,en;q=0.5
[HTTP_ACCEPT_ENCODING] => gzip,deflate
[HTTP_ACCEPT_CHARSET] => ISO-8859-1,utf-8;q=0.7,*;q=0.7
[HTTP_KEEP_ALIVE] => 115
[HTTP_CONNECTION] => keep-alive
[PATH] => <snip>
[SystemRoot] => C:\Windows
[COMSPEC] => C:\Windows\system32\cmd.exe
[PATHEXT] => .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
[WINDIR] => C:\Windows
[SERVER_SIGNATURE] =>
[SERVER_SOFTWARE] => Apache/2.2.11 (Win32) PHP/5.3.1
[SERVER_NAME] => <snip>
[SERVER_ADDR] => <snip>
[SERVER_PORT] => 80
[REMOTE_ADDR] => <snip>
** [DOCUMENT_ROOT] => C:/wamp/www/
[SERVER_ADMIN] => admin@localhost
** [SCRIPT_FILENAME] => C:/wamp/www/K2F/cms/cms-joomla-1.5/index.php
[REMOTE_PORT] => 49947
[GATEWAY_INTERFACE] => CGI/1.1
[SERVER_PROTOCOL] => HTTP/1.1
[REQUEST_METHOD] => GET
[QUERY_STRING] =>
[REQUEST_URI] => /K2F/cms/cms-joomla-1.5/
[SCRIPT_NAME] => /K2F/cms/cms-joomla-1.5/index.php
[PHP_SELF] => /K2F/cms/cms-joomla-1.5/index.php
[REQUEST_TIME] => 1297758541
)
** Parts you ought to read out, should explain my problem perfectly.
So basically, the expected DOCUMENT_ROOT
is /home/sitename/public_html/
, but instead I got /usr/local/apache/htdocs
.
Oh, and sorry if I've been a bit too verbose ;)
Edit:
getcwd()
=> /home/visitgoz/public_html
__FILE__
=> /home/visitgoz/public_html/K2F/config.php
回答1:
Those (cheap) Mass-Hosters quite often do some Apache URL-Rewriting tricks - which basically make THEIR Life easier, since there's only ONE Apache V-Host, with ONE Document-Root for all shared Websites.
To find the "real" document Root in this case:
- Compare DOCUMENT_ROOT to SCRIPT_FILENAME from left to right. If there are no matching Path-Components, it's such a shared host.
- If it's such a shared host, remove REQUEST_URI from SCRIPT_NAME => "index.php" in your example.
- Then: remove the result from above from the end of SCRIPT_FILENAME => your DOCUMENT_ROOT (/home/sitename/public_html/)
Edit (Christian Sciberras): This is the right answer, but it lacks code, which I had to write anyway, so here goes:
if(strpos($_SERVER['SCRIPT_FILENAME'],$_SERVER['DOCUMENT_ROOT'])===false){
// how it works on reseller accounts...
$path=str_common(getcwd(),__FILE__);
}else{
// how it normally works...
$path=truepath($_SERVER['DOCUMENT_ROOT']).'/';
}
回答2:
I would use dirname(__FILE__)
, dirname(dirname(__FILE__) . '/../..')
or something like that to create constant DOCUMENT_ROOT
which would then be used instead of $_SERVER['DOCUMENT_ROOT']
.
回答3:
The document root is per virtual host. But using UserDir (e.g. ~sitename
) tells the server to look elsewhere for the files to process. You will need to handle this difference if you want your script to work properly.
来源:https://stackoverflow.com/questions/5001326/php-strange-document-root