including files from different directories - php

So I set up my include files, such as header.php, nav.php, and footer.php in a /inc folder.
Then I include the files in my pages. But if I have another folder, for example wiki where i'd like to include those files onto the pages of wiki, the file paths for the includes break.
Example: I have included this in a page from the wiki directory.
<?php include_once('../inc/header.php'); ?>
I have two other includes in the header.php file, but since I'm including them in a different directory, both includes break, unless I go and append a ../ in the include path.
I'm wondering what is the best way to include files within different directories and not having to go back and fix the path?

Create constants using realpath in the initial file and then reference them using easy to read and manage but now absolute paths.
You can see an example here:
How can I get the "application root" of my URL from PHP?
I'd also suggest testing for the constant definition before defining.

The simplest solution? Use absolute paths.

If the files are in directories of the same level, the relative pathes (with ../) will be the same. If you have one within another, you will need to have the ../ on the beginning of the one in the sub-directory. The only way around changing the paths is to create a link as a sub-directory representing the main directory, although this can have dangerous consequences relating to recursive processes.
btw, include_once means that this operation is "optional", meaning the program will continue to execute. If you require the files included, use require_once, and the program will break if it's not there.

Include them like this
require_once(dirname(__FILE__).DIRECTORY_SEPARATOR.'inc'.DIRECTORY_SEPARATOR.'header.php');
This could work!

I like using this method:
define('ROOT_DIR', dirname(__FILE__) . '/'); // Defined on the index or in the bootstrap
include(ROOT_DIR . 'subfolder/fileName.php');

If you use PHP's native set_include_path to add an include folder you can then include files just by their name.
<?php
/**
* The path to your /inc/ folder.
*/
$path = '/absolute/path/to/inc/';
/**
* get_include_path retrieve's the current include path.
* It's a bad idea to over write the entire include path
* The PATH_SEPARATOR constant is set per operating system
*/
set_include_path(get_include_path() . PATH_SEPARATOR . $path);
/**
* You can now include any files in /inc/ from any directory with no path
*/
include_once('header.php');
?>

$_SERVER['DOCUMENT_ROOT'] gives you the DocumentRoot of your webserver, e.g. Apache. Then you can take that as a stable datum and map from there as that won't vary.
include_once($_SERVER['DOCUMENT_ROOT'].'/inc/header.php');

I found that I had to do str_replace("\\","/",$_SERVER['DOCUMENT_ROOT']) when running on IIS if that helps.

Related

Relative URLS across different sub folders

Looking for a way of allowing my links and include URLs etc to work on my local machine correctly as well as on my live site.
I have for example a common.php file which contains my DB connection.
I also have a init.php file which is included on every page and inside that includes the common.php file (among others)
For now, i have used
include './common.php';
However, if i am in a page e.g. web/settings
the ./ points to the settings folder.
What should i be using as a relative URL that will work across the whole site no matter what folder etc?
How about /? It refers to the base, and from there you can use the absolute path:
include "/absolute/path/to/file/common.php";
A relative URL is always affected by the current directory, and you can't make it the same no matter where you are on the site. You need to use absolute paths.
You could use $_SERVER['DOCUMENT_ROOT'] for this.
set_include_path( get_include_path() . PATH_SEPARATOR . $_SERVER['DOCUMENT_ROOT'] );
// Now, you can specify your path relative to your DOCUMENT_ROOT.
include('common.php'); // Assuming your common.php file is in your root path.
You'll find it alot more convenient using namespaces though, so you might want to go down that road.
the quick answer for a path is this.
__DIR__ = current working directory so If you have MVC type architecture ( single point of entry aka front controller, basically everything starts off in one file, typically index.php, and the rest are included ) you can just define a constant like this in that main file.
define( 'BASE_PATH', __DIR__.'/' );
So if you have like this
root
index.php //define basepath
includes :
other.php
template :
temp.php
in other you can just do
include BASE_PATH . 'template/temp.php';
everything will be tied by that one base set in the main index.php file, and as long as the folder i put above as root contains everything you can move that where ever you want because of the dynamic part __DIR__
The long answer is to use a PSR-0 autoloader but that might be a bit overkill.
As a side not if you are on PHP < 5.3 use this instead of __DIR__
dirname(__FILE__)

PHP absolute path in requireonce

I'm using a simple pre-made authorisation tool to secure my site. The tool requires this line of code to be applied to the top of every .php page. Auth.php lives on the root level.
<?php ${(require_once('Auth.php'))}->protectme(); ?>
I need to be able to add this line of code to every file, including files in sub-folders. But I'm unsure of how to apply the method as shown in require_once in php to ensure it always is linked absolutely, alongside the protectme(); function.
Any enlightenment is appreciated.
Cheers.
Set a variable to the absolute path. $_SERVER['DOCUMENT_ROOT'] is a PHP global variable that stores the servers, root path. You just need to insert the rest of the path information to the script. For instance if your website exists on /var/www/ and your script exists at /var/www/scripts you would do the following.
$path = $_SERVER['DOCUMENT_ROOT'] . '/scripts/Auth.php';
require_once($path);
You can use a relative path to get to it.
One level up: ../Auth.php
Two levels up: ../../Auth.php
etc.
You should alter your php.ini to change the include path to the the path to that (all all your other) included files. Then you can include them without a path on every page regardless of their own location.
More Details
Add the root level directory to your include_path - PHP will do the rest for you. No complicated variables, constants or whatever.
In addition to everything that has been said already, I suggest centralizing all common functionality. Create a file, like common.php with all includes that you need for you application and then include that from all your scripts.
Also, a nice way to do relative includes is by using dirname() function in combination with __FILE__ magic constant. For example:
require_once dirname(__FILE__) . '/../lib/common.php';
If you do not have access to php.ini, I've used something like this before
include $_SERVER['DOCUMENT_ROOT']."/"."include_me.php";
The easiest way since it's a site wide change is to add its directory first in the include path in php.ini.
If you can't change php.ini, there are a few other options for adding it to the include path.

Trouble with / vs ./ vs ../ and absolute and relative paths

I have many PHP files in
/
/client/
/user/
/config/
etc...
I want all my files to include /user/codestart.php. (Lots of functions etc)
Therefore:
All files in / have include("./user/codestart.php");
All files in /user/ have include("codestart.php");
All files in /client/ have include("../user/codestart.php");
The problem is that /user/codestart.php has include("../config/config.php"); (The MySQL ID and password)
When a file in / runs, such as /index.php, it includes ./user/codestart.php.
Then /user/codestart.php includes ../config/config.php, but it cannot see it, because it thinks it is calling it from /, instead of from /user/.
If I change
include("../config/config.php") to be
include("./config/config.php")
that fixes it for / files, but breaks it for/user/ and/client/ files.
Bottom line is that when one PHP file includes another file, PHP thinks it is operating from the location of the original file, not the calling file.
I need to use relative paths, not absolute paths. Absolute paths will not work in my situation.
Is there any way to solve this?
One way to deal with this is this:
Have a central configuration file (e.g. /myproject/config/bootstrap.php
In that configuration file, define a global root for your application. E.g.
define("APP_ROOT", realpath(dirname(__FILE__)."/.."));
Include that configuration file in every PHP file. E.g.
include("../config/bootstrap.php");
Whenever you reference some other file, use
include APP_ROOT."/includes/somefile.php";
Voilá - you have a fixed point in space (APP_ROOT) and can reference everything relative to that, no matter which directory you are in.
If you want to do it this way I suggest you make a seperate file for all your includes which is in a fixed dir, the root for example.
Then you reliably include all the files from there using
include __DIR__.'path/relative/from/includefile.php'
If your php verion is lower than 5.3 you should use dirname(__FILE__) instead of __DIR__ as mentioned by RiaD
You might like this php.net page
You can use relative paths in conjuntion with dirname(__FILE__)
So in your codestart file write:
require_once dirname(__FILE__).'/../config/config.php';
You can set the path that PHP uses to look for files, so that it contains all your folders. In index.php:
$folders = implode(PATH_SEPARATOR, array('user', 'config'));
set_include_path(get_include_path().PATH_SEPARATOR.$folders);
Then you can just do:
include("codestart.php");
and:
include("config.php");
This will work for index.php and all files that index.php includes.
use absolute paths. to get path to your root directory use $_SERVER['DOCUMENT_ROOT'], ex.
include $_SERVER['DOCUMENT_ROOT'].'/user/codestart.php';
include $_SERVER['DOCUMENT_ROOT'].'/config/config.php';
It save you from absolute paths' problems.

PHP including files

What's the difference between
$_SERVER['DOCUMENT_ROOT'];
and
dirname(__FILE__);
I wonder what's the difference because when I 'echo' them, they're returning same path. Which do you prefer should I use and why?
Thanks!
Both are different
_FILE_
The full path and filename of the file. If used inside an include, the name of the included file is returned. Since PHP 4.0.2, FILE always contains an absolute path with symlinks resolved whereas in older versions it contained relative path under some circumstances.
source : PHP magic constants
Let's said, your document is /var/www,
and your index page is /var/www/index.php
dirname(__FILE__) == $_SERVER['DOCUMENT_ROOT'];
But if you drill-down to sub-folder like /var/www/posts/index.php
dirname(__FILE__) != $_SERVER['DOCUMENT_ROOT'];
/var/www/posts != /var/www
The use of $_SERVER['DOCUMENT_ROOT'] is more appropriate in this case.
__FILE__ always points to the current file path, and $_SERVER['DOCUMENT_ROOT'] points to the document root path ;-)
I prefer first one, as it is more semantic.
If you will try to compare the values of the files, that are located not in your docroot - then you'll get different values.
The former one is a root folder for the HTTP server (or VirtualHost) and it is a server setting.
The latter is the folder containing the current file.
The usage is entirely based on requirements in my opinion.
You would normally use $_SERVER['DOCUMENT_ROOT'] when you want to reference your website's root folder from any where within your website or web application.
You will find using dirname(__FILE__) handy if you were including a file, that then needed to include some more files from the same directory. I use this in my PHP wrapper for the Dribbble API
class Dribbble {
function __construct() {
require_once(dirname(__FILE__) . '/base.php');
require_once(dirname(__FILE__) . '/shot.php');
require_once(dirname(__FILE__) . '/player.php');
}
}
This means I can just include dribbble.php from any where in my website or web application and not worry about also including base.php, shot.php, and player.php at the same time.

php include, all paths get messed up

When i use php include to include a page in my website all the paths in the file i include get messed up. The included page acts like it is in the same folder as the page im including from.
Is there way to avoid/fix this problem?
One way I try to get around this problem is by always including from where the file that is including the other file is based:
$here = dirname(__FILE__);
include($here."/../include.php");
// will include a file *allways* one level up from where *this* file is located
// and not the file that started the execution of the script.
I sometimes have files that are accessed from several different places and so the includes file path can become a bit hard to manage. So I usually try to include a configuration file at a known point then define paths to common include points.
// from a common config file
define("PATH_TO_CLASS", dirname(__FILE__)."/../class");
define("PATH_TO_MEDIA", dirname(__FILE__)."/../assets/media");
Then you can use in the file you've included the config file like:
include dirname(__FILE__)."/../config.php";
include PATH_TO_CLASS."/snassy.class.php";
What is your include path set to? If included.php is not the same directory as page.html, you can append to you existing include path.
<?php
$path = '/path/to/includes';
set_include_path(get_include_path() . PATH_SEPARATOR . $path);
?>
Try the PHP manual
You might need to set the include path correctly, for example via:
set_include_path(get_include_path() . PATH_SEPARATOR . 'YourPath');
Then you just need to include as if it were is the same directory:
include 'FileName.php';
No, that is the default behaviour of the php include function: It basically copies the contents of the included file into the including file. That way the instructions in the included file behave as if they were in the including file (because they are in a way).
You either have to refactor the instructions in you included file so they can operate from the folder of the including file, or add the folder of the included file to the include path.
You could use absolute paths? 'http://www.site.com/the/full/url/image.jpg'
Or even
$path = 'http://www.site.com';
and $path.'images/image.jpg' or whatever it is
Another answer for you. If things are unchangeable for some reason I've used chdir() to some success.
For example I had mobile users come from and use a different directory than the main site, but wanted to use all of the functions and classes of the main site, so I would chdir(/to/the/main/site/folder); right before calling the common code, which required different include paths. I would use sparingly though... as things can get confusing.

Categories