To enable my PHP scripts to access my MySQL database, I have a configuration file containing the name of the MySQL database, usernames, etc.
In order to keep that information secure, I'm storing it outside of the web root on the server. I WAS setting an environment variable in httpd.conf to the file path of the .ini file so that PHP could access it and then parse the config file.
However, for the purposes of demonstration I'm deploying this database and front end on a shared server which will not give me access to httpd.conf. This is the alternative I worked out:
<?php
if(!isset($GLOBALS['config'])){
$nonPublic = explode("/",$_SERVER['DOCUMENT_ROOT']);
array_pop($nonPublic);
$nonPublic = implode("/",$nonPublic);
$GLOBALS['config'] = parse_ini_file($nonPublic."/configs/JCDBconfig.ini");
}
?>
The theory is that I make sure the 'configs' folder is just above DOCUMENT_ROOT, grab all but the last part of the DOCUMENT_ROOT path, and the PHP script should be able to find the config file stored there.
My question is: Is this a good idea, or sloppy? Is $_SERVER['DOCUMENT_ROOT']
reliable enough that, should I deploy this on a dedicated server in the future, it will still work?
1 Answer 1
I am assuming that you have a directory structure something like this, which can be common in shared hosting environments:
/path/to/your/directory => your customer directory on the host
/path/to/your/directory/public => the web server document root
Or, if you had full control over your environment it might look like:
/some/nonpublic/directory => non-public directory (possibly in include path)
/var/www => web server document root
So ideally, your application should be able to seamlessly handle both without custom code that changes based on where you deploy the application.
Typically, this is done by configuring constants for file paths in a config file, not by relying on values derived from $_SERVER['DOCUMENT_ROOT']
as this has absolutely no connection to where on a server you may have the ability to place your non-public application code. You may be able to count on this behavior for some specific shared host environment, but this gives you no guarantee that this same behavior would exist in another environment.
So an approach of defining path constants may look like:
define('WEB_ROOT', $_SERVER['DOCUMENT_ROOT']);
define('INCLUDE_DIR', {path to one of non-public directories shown above});
define('CONFIG_DIR', INCLUDE_DIR . '/config');
Then if you wanted to check if your config is set for JCDB, it might look more like:
if(!isset($GLOBALS['config'])){
$GLOBALS['config'] = parse_ini_file(CONFIG_DIR . '/JCDBconfig.ini');
}
This reduces your problem to only having to figure out how to populate the value into INCLUDE_DIR
, not trying to determine this directory when you are at the point of trying to conditionally load configurations for various components in the application.
This could be hard-coded (not ideal) which is quick and dirty, but you might consider an approach that allows you to conditionally determine the include path.
For example, if you control the environment, you could modify your Apache config to inject an environmental variable holding the include path or, if missing, perhaps looks into a file that you specifically deploy onto your shared host to determine how to get to that include path for the host you are on.
So perhaps something like this near the beginning of your application bootstrap process.
define('WEB_ROOT', $_SERVER['DOCUMENT_ROOT']);
if(!empty($_SERVER['APP_INCLUDE_PATH']) {
define('INCLUDE_DIR', $_SERVER['APP_INCLUDE_PATH']);
} else {
define('INCLUDE_DIR', require WEB_ROOT . '/appIncludeConfig.php');
}
Where in Apache you have
SetEnv APP_INCLUDE_PATH /some/nonpublic/directory
Or for shared host, appIncludeConfig.php
has a single line of code like:
<?php
return '/path/to/your/directory';
I question why you would want to put a critical dependency like a config setting into a mutable variable in global scope vs. something immutable (like a constant). So perhaps something like this is more appropriate:
if(!defined('JCDB_CONFIG')){
define('JCDB_CONFIG', parse_ini_file(CONFIG_DIR . '/JCDBconfig.ini'));
}
Note I also changed the naming of the config setting to be something less generic than just config
such that it is clear that this value is specific only to this particular configuration value.
Explore related questions
See similar questions with these tags.
DOCUMENT_ROOT
. \$\endgroup\$