I can set the PHP include path in the php.ini:
include_path = /path/to/site/includes/
But then other websites are affected so that is no good.
I can set the PHP include in the start of every file:
$path = '/path/to/site/includes/';
set_include_path(get_include_path() . PATH_SEPARATOR . $path);
But that seems like bad practice and clutters things up.
So I can make an include of that and then include it into every file:
include 'includes/config.php';
or
include '../includes/config.php';
This is what I'm doing right now, but the include path of config.php will change depending on what is including it.
Is there a better way? Does it matter?
If you're using apache as a webserver you can override (if you allow it) settings using .htaccess files. See the PHP manual for details.
Basically you put a file called .htaccess in your website root, which contains some PHP ini values. Provided you configured Apache to allow overrides, this site will use all values in your PHP config, + the values you specify in the .htaccess file.
Can be used only with PHP_INI_ALL and PHP_INI_PERDIR type directives
as stated in the page I linked. If you click through to the full listing, you see that the include path is a PHP_INI_ALL directive.
Erik Van Brakel gave, IMHO, one of the best answers.
More, if you're using Apache & Virtual hosts, you can set up includes directly in them. Using this method, you won't have to remember to leave php_admin commands in your .htaccess.
Use a php.ini file in website root, if your setup uses PHP as CGI (the most frequent case on shared hosts) with the same syntax as the server-wide php.ini; put it into .htaccess if you have PHP as an Apache module (do a phpinfo() if unsure):
php_value include_path "wherever"
Note that per-folder php.ini does not affects subfolders.
Why do you think append to include path is bad practice?
This code near top of root script shouldn't be that bad...
$path = '/path/to/site/includes/';
set_include_path($path . PATH_SEPARATOR . get_include_path());
IMHO the main advantage is that it's portable and compatible not only with Apache
EDIT: I saw a drawback of this method: small performance impact. see http://www.geeksengine.com/article/php-include-path.html
Depending on how your host is set up, you may be permitted to place a php.ini file in the root of your home directory with extra configuration directives.
Your application should have a config file written in PHP. Then include that with a relative page into every page in the program. That config file will have a variable for the path to the includes dir, templates dir, images dir, etc.
You can set include_path in your php.ini file too. I'm a perl guy, so I expect to be able to load includes and have include do the right thing. I have all my includes in a specific directory, which is added to include_path. I can do things like
require_once "ClassName.php";
I don't need to worry about relative paths or locations of files.
I've also written my own CustomRequire to do things like
function CustomRequire ($file) {
if(defined('MYINCLUDEPATH')) {
require_once MYINCLUDEPATH . "/$file";
} else {
require_once $file;
}
}
That way I can change how I do includes at a later date. Of course, you still need to find a way to include your include code :)
Related
tl;dr: How do I make PHP interpret relative paths in include/require statement from the perspective of the current file?
This is yet another question about that old issue in PHP about relative paths. Please bear with me, as I couldn't find any solution for what I am specifically trying to do.
Consider the following directory tree and files:
[www]:
index.php
config.php
[webroot]:
home.php
index.php requires home.php, found inside webroot:
require('webroot/home.php');
home.php requires config.php, found in the parent directory:
require('../config.php');
My problem is that this won't work in my local development environment (Ubuntu 14.04 LTS / 15.10), whereas it runs flawlessly in production. Every mentioned environment is running Apache 2 and PHP 5.
Strangely, this does run locally when I run it inside my Vagrant VM (Ubuntu 12.04 LTS), accessing it from the host machine. But, right now, I cannot run a VM here.
So, why do these environments behave so differently?
This makes me believe that there must be a way to change how PHP interprets relative paths. I am currently working with a 6GB+ PHP project that is written like the example above, and I really need to avoid the amount of effort that it'll take from me to rewrite every include/require statement (using dirname(__FILE__) or so), as well as the git merge conflicts this might cause.
EDIT: I've just remembered I actually had already asked this question here: PHP: include inside included file
The path used to resolve relative URLs like this is configured by the include_path configuration option which has a dedicated function for setting it at runtime: set_include_path.
Note that the set of paths to search may include ., representing the "current working directory", which can be set with chdir and read with getcwd. You may also need to change this to make explicitly relative paths like ./foo.php and ../foo.php to work.
(I was going to recommend you used __DIR__ or $_SERVER['DOCUMENT_ROOT'] instead, but you mention that you don't want to rewrite existing code. I would still recommend to anyone else reading this to make explicit in each include where paths are relative to, to avoid odd bugs and potential security holes with the dynamic base.)
If you want to override existing functionality in place you need to either install an external library or use namespaces. Both are extra work. I'm guessing that installing an extra library probably isn't even an option.
You could try adding the paths to those folders using set_include_path.
Or you could add a global variable and several global functions like below, for all the require and include overloads, but you would still have to do a find/replace through the whole project for instances of include, require, include_once, require_once... and replace them with "include_rel"...
$include_rel_path = '.';
function include_rel($path){
global $include_rel_path;
$my_path = $include_rel_path;
//TODO maybe need to check for drive letters?
if(strpos($path, '/') === 0) { //absolutepath
$include_rel_path = preg_replace('/\/[^\/]*$/','',$path);
include($path);
} else { //relative path
$include_rel_path .= preg_replace('/\/[^\/]*$/','',$path);
include($my_path.'/'.$path);
}
$include_rel_path = $my_path;
}
You have to use auto_prepend_file. if PHP is run as an Apache module then .htaccess file to the path to your config.php file and any PHP file accessed will automatically have the contents of the config file prepended to it.
For .htaccess:
php_value auto_prepend_file /full/path/to/file/config.php
If your server is using CGI then set this directive in your php.ini or Keep in mind this ONLY will work on a server where If PHP is run as a CGI you need to add edit it in your php.ini file or put it inside a .user.ini file just without the php_value part.
auto_prepend_file /full/path/to/file/config.php
In Nginx you could add this line to server configuration inside location ~ \.php$
fastcgi_param PHP_VALUE "auto_prepend_file=/full/path/to/file/config.php";
Let me know if doesn't resolve your problem.
<?php
$path = $_SERVER['DOCUMENT_ROOT'];
$path .= "/Folder/File.php";
include_once($path);
?>
That should do the trick :)
index.php:
chdir('webroot');
require_once('home.php');
I'm trying to include using require_once, however, I don't always know what the file structure will be relative to the DOCUMENT_ROOT...
it could be...
/config.php or /theapp/config.php or /dev/theapp/config.php or /something_else/theapp/config.php
I COULD path back from the file like require_once('../config.php') except in some cases the files may be in a symlink directory.
Basically I'm trying to find a way where NO MATTER the circumstance, any files that call the config.php file can find it.
This is what the include_path configuration setting is for. I usually set it in the Apache config for my site, or in a local .htaccess file. Use the php_value directive.
So, basically, in your Apache config file:
php_value include_path .:/var/www/where-your-site-is
Then, from your scripts, you just use:
<?php
require_once 'conf/config.php';
require_once 'views/template.php';
?>
No matter where in your sites directory structure you are.
If you have PHP 5.3+ use this:
// My page: /dir1/dir2/welcome.php
// My include: /inc/top.php
require_once(__DIR__.'/../../top.php');
From the docs: __DIR__ is the directory of the file. If used inside an include, the directory of the included file is returned.
You can use dirname(__FILE__)
It returns the complete path of your script.
example
require_once(dirname(__FILE__).'/../config/config.php');
Came up with a pretty simple solution that works when the app is running as one unit, as well as when the core system is linked in via symlink:
Instead of:
require_once('../../../config.php');
I use:
function changeDir($up_n){
$split = explode("/",$_SERVER['SCRIPT_FILENAME']);
array_pop($split); // Remove current file name
for ($i=1; $i<=$up_n; $i++){ array_pop($split); }
return implode("/",$split);
}
require_once(changeDir(3)."/config.php");
Just pop off
I am using xampp to develop my php application. Few days back I installed pear ti use DB abstraction. After that, I couldn't use include files from parent directory, however I can include from sub-driectories.
Here is what I see when I check my include path
.;E:\xampp\php\PEAR
I tried changed include path using set_include_path to the location where my files are stored, then the application failed to load Pear files.
Any help appreciated.
Easiest way to prepend to the include path stack is...
set_include_path(implode(PATH_SEPARATOR, array(
'path/to/app/includes',
'path/to/any/other/includes',
get_include_path()
)));
If you really want to use set_include_path, you can do it like this:
set_include_path(get_include_path().PATH_SEPARATOR.'path_to_parent');
Use the predefined constant DIRECTORY_SEPARATOR in case your code moves to a server that uses a different directory separator.
Personally if I needed to set the path specially for a particular site, I would try to set the path in the .htaccess file in the site's web root. It provides a more obvious place to look for site-wide configurations like the include_path. Here is the line you would put in the .htaccess file:
php_value include_path ".;E:\xampp\php\PEAR;path_to_parent"
or on a Linux server:
php_value include_path ".:some_path/PEAR:path_to_parent"
On my localhost, I tinker with php.ini to set the include_path. But, overtime the line for the include_path in my php.ini has grown and it looks, ummm, unsightly. I'm looking for a way to set include_path like, I can copy-paste a single include line, say <?php include("superfile.php");?> on all pages, regardless of where they are in the directory tree, where superfile contains all include_path directives.
I've already tried,
<?php
$include_path = $_SERVER["DOCUMENT_ROOT"] . "/more/directories/as/needed/";
ini_set("include_path", $include_path);
include("initialize.php");
?>
and saved it on the root folder as superfile.php. However if I want to set the include path of a file residing at, say root/sub, by way of superfile.php I need to do <?php include("../superfile.php"); ?> (with "directory up" dots), defeating my purpose of setting the include_path.
Any suggestions? Thanks!
It sounds like you've removed all of your custom include_path directives from the php.ini.
To allow all scripts to call <?php include("superfile.php");?> simply add the one entry to your php.ini include_path that will allow this, and your set.
I'm doing a little home computing project in PHP and am creating references like this...
Beer
This seems to pick up the right file. When I do includes, I seem to need a pathname.
include_once ("/var/www/common.php");
I'm sure this can't be right. Perhaps you could tell me what is the best practice for these things so that I can create scripts that aren't tied to a particular pathname (or operating system, come to that) and so that the file selected in the first example is known/can be controlled? Perhaps some settings in php.ini or apache?
Thank you.
You may use relative paths in PHP, too:
include_once './common.php';
This path now is relative to the script, which was intitially called.
If you leave out the dot
include_once 'common.php';
PHP will check all the paths in you include_path and if it doesn't find a file called common.php there, it will try to include common.php relative to the current file.
Many people have the practice of definining a constant like ROOT in the index.php which is used everywere else:
const ROOT = __DIR__; // as of PHP 5.3
define('ROOT', dirname(__FILE__)); // if you don't have PHP 5.3
Actually, you need an absolute path for both.
for the web resources it should start from the web root - /
for the files you need a point where virtual path meets a filesystem one.
$_SERVER['DOCUMENT_ROOT'] is for that purpose.
so
Beer
and
include_once ($_SERVER['DOCUMENT_ROOT']."/common.php");
will work as desired
You can:
Use relative pathnames. The paths should be relative to the directory where the script that is initially executed (unless the directory has been changed explicitly by the script).
Use $_SERVER['DOCUMENT_ROOT'].
The php ini file setting
include_path = var/www/includes
Means that you just forget all that crap about relative and absolute paths.
It matters not a wit where you call include/require.
Even in say:
/var/www/html/example.com/very/long/way/down/index.php
can contain the line;
include 'settings.php' ;
and if settings.php is in /var/www/includes/ then it will be included.
You can override the ini setting in a various places in apache too, even in .htaccess
This of course ties your application to your server settings, which some find unacceptable, but if you are not distributing your stuff, then read up on ini_get and ini_set too.
You can then go on and create natural directories in your include folder, such as /database and keep database settings in there too.