创建可在ajax和include中使用的全局可用的完全限定根URL和根目录路径的最佳方法

So I realize that there are many ways to go about this and although there are many answers on stack I can't find any that allow for a single global to be utilized for a site using ajax. Some files I have setup to allow both calls. So a if statement that checks for a $_POST['json'] and if it exists then it calls the function inside the file. Otherwise you can do an include in a file and call the function directly. The below is a quick example:

if (!empty($_POST['json'])) {echo json_encode(create_table());} 
function create_table(){}

The problem I'm having is you can't use an include ../ within the function because then if you include it that path may be invalid. I know that there is $_SERVER, $_SESSION, and of course define but they all have a down fall.

  • $_SERVER can't be trusted if your using this for multiple platforms since you can't always trust it.
  • $_SESSION timesout
  • define doesn't work for ajax which would require an include which then defeats the purpose since you would have to do a ../ to get to that file but would then error out if you called the original file with an include to another file.

Please let me know what you think of the validity of simply say sending a ROOT_URL and ROOT_DIR as part of the params within a function? This would allow you to use define in top level pages that call others and for files that can only be called through ajax you could just use ../ to call them.

A little back history I have an employment form and couldn't figure out why randomly people couldn't submit and I realized that my save.php and encryption.php files used session variables to call the database connection. The session timed out because of how long it took for them to submit and so nothing would work. I fixed the save.php by simply making it a ../ since you can only call it with AJAX but the encryption.php file is a class that requires a include and so i ended up just allowing whomever was calling it to send a $mysqli directly which also allows different db connections to hit it in the same site (not sure why you would do that but thought it was kinda cool.

Any suggestions are greatly appreciated.

EDIT: I am building this to work across both Windows and Linux simultaneously. (I run a local windows server for testing and I do my live testing on a linux box.

The below is what I currently use to allow both windows and linux to use the same setup.

$BASE_NAME = basename(__DIR__);
$PHP_SELF = str_replace($BASE_NAME . '/', '', $_SERVER['PHP_SELF']);
$REAL_PATH = str_replace($BASE_NAME, '', __DIR__);
$URL_CHECK = (count(array_slice(explode('/', $PHP_SELF), 1, -1))) ? join( '/', array_slice(explode('/', $PHP_SELF), 1, -1)) . '/' : '';
$URL_COUNT = count(array_slice(explode('/', $_SERVER['PHP_SELF']), 1, -1));
$ROOT_URL = 'http://' . $_SERVER['HTTP_HOST'] . '/' . $URL_CHECK;
$ROOT_DIR = (realpath(dirname(__DIR__))) ? str_replace('\\', '/', $REAL_PATH) : $REAL_PATH;
define("ROOT_URL", $ROOT_URL);
define("ROOT_DIR", $ROOT_DIR);

EDIT: Is there anything wrong with using the $_SERVER tags for all this? Or at least the files that are running ajax and don't have access to the unique?

If I understand correcty, you are having trouble translating relative paths in the page to an absolute file path on the server.

To fix this, your website will need one small piece of information, which is the document root of the site.

For instance, if your index.php is in 'C:\Sites\MySite\www\index.php', then 'C:\Sites\MySite\www\' is probably your root. You can store that value in a define in PHP. Then, when a user tells you to include 'admin/anyfile', you append that to your document root path, effectively including 'C:\Sites\MySite\www\admin/anyfile'.

If your site runs on Linux, you can still use the same trick.

That way, all your code will be cross platform, and could even be installed multiple times in separate directories on the same server. All you need to do is create a small piece of configuration that you change each time and include with each request. But that's not odd, almost every site has some kind of config.php which contains settings like this.

Don't worry about the difference between / and \. Both web and Linux use / and Windows is smart enough to understand both.

Ok, this is what I came up with that works in both linux and windows without any additional help. Also this can be set at the root level and will find the root path regardless of where you include it.

$URL_ROOT = array_shift(array_slice(explode('/', $_SERVER['PHP_SELF']), 1, -1));
$URL_CHECK = ($URL_ROOT == basename(__DIR__)) ? $URL_ROOT . '/' : '';
define("ROOT_URL", 'http://' . $_SERVER['HTTP_HOST'] . '/' . $URL_CHECK);
define("ROOT_DIR", (realpath(dirname(__DIR__))) ? str_replace('\\', '/', realpath(dirname(__FILE__))) . '/' : realpath(dirname(__FILE__)) . '/');