All my PHP include files are in a single directory:
https://www.mywebsite.com/includes
Inserting these files in top level pages is easy enough:
<?php include 'includes/logo.php'; ?>
<?php include 'includes/main_nav.php'; ?>
<?php include 'includes/news.php'; ?>
etc.
For sub-directory pages I've been doing this:
<?php include '../includes/logo.php'; ?>
<?php include '../includes/main_nav.php'; ?>
<?php include '../includes/news.php'; ?>
and this:
<?php include '../../includes/logo.php'; ?>
<?php include '../../includes/main_nav.php'; ?>
<?php include '../../includes/news.php'; ?>
So far so good, but I suspected it wasn't going to continuing being this easy.
Now I need to include this file:
top_five_news_stories.php
in this:
news.php
At this point, my relative path strategy fails because the include in the include can have only one path structure.
I've read several posts recommending absolute paths using:
dirname(__FILE__)realpath(dirname(__FILE__)$_SERVER["DOCUMENT_ROOT"]
However, they all come with some kind of caveat relating to PHP configuration, server configuration or operating system. In other words, there's often a comment by somebody saying it didn't work in their case, or doesn't work in IIS, or doesn't work in UNIX, or something else.
A solution I haven't seen is one I thought would be most simple: Just set a variable:
$base = "https://www.mywebsite.com/includes";
then:
<?php include $base . "logo.php" ?>
Considering that I already use the HTML base element, which works in a similar way, this method strikes me as simple and efficient.
But since it wasn't mentioned in any of the posts I read, I'm wondering if I'm overlooking a potential problem.
Frankly, if I had to go to production to today, I would use this:
<?php include $_SERVER['DOCUMENT_ROOT'] . '/logo.php" ?>
which works for me and is commonly mentioned.
But I'm wondering if using a variable is a reliable, efficient method?
Don't
I would advise against using anything that needs something outside of PHP, like the $_SERVER variable.
$_SERVER['DOCUMENT_ROOT']is usually set by the webserver, which makes it unusable for scripts running from the command line. So don't use this.Also don't use url's. The path-part in a url is not the same as the path of the file on disk. In fact, that path can not even exist on disk (think Apache rewrites).
Including url's also needs you to turn
allow_url_includeon, which introduces (severe) security risks if used improperly.Do
If your minimal supported PHP version is 5.3 (I hope it is!), you can use the magic constant
__DIR__. 2 examples:If you need to support lower versions, use
dirname(__FILE__). 2 examples:Make sure
ROOT_DIRpoints to the root of you project, not some subdirectory inside it.You can then safely use
ROOT_DIRto include other files:Note that I'm defining a constant (
ROOT_DIR), not a variable. Variables can change, but the root directory of you project doesn't, so a constant fits better.realpath()
realpath() will resolve any relative parts and symlinks to the canonicalized absolute pathname.
So given the following files and symlink:
and
/path/to/file.phpcontains:then
ROOT_DIRwould become/path/to/another, because:__DIR__equals to/path/to/some(so we get/path/to/some/../symlink)..is 1 directory up (so we get/path/to/symlink)symlinkpoints to/path/to/anotherYou don't really need to use
realpath(), but it does tidy up the path if you're relying on relative parts or symlinks. It's also easier to debug.Autoloading
If you need to include files that contain classes, you'd best use autoloading. That way you won't need
includestatements at all.Use a framework
One last pease of advise: This problem has been solved many many times over. I suggest you go look into a framework like Symfony, Zend Framework, Laravel, etc. If you don't want a "full stack" solution, look into micro-frameworks like Silex, Slim, Lumen, etc.