Including a File that Includes a File

The Problem

Include and Require behave in the same way in relation to the discussion here.

A particular problem arises when you include a file that itself includes another file. Let us say we have a file called index.php which includes a file called file1.php and that file1.php includes a file called file2.php. If a relative file path is given in the include statement in file1.php which includes file2.php then when file1.php actually is executed this will be happening in whichever directory index.php is in. PHP will make the file path to file2.php relative to the directory index.php is in. One solution to this is to write the include statement in file1.php for file2.php such that the path is relative to the directory that index.php is in. That approach will not work if file1.php is required not only by index.php but by another file(s) in a different directory(s) as now you would need two or more paths to be written for including file2 in file1.

An example of this situation is discussed below. First of all a tree view of the files and directories is shown below together with the key include or in this case require statements:


  dir0      
  ├── dir1
  │   ├── file1.php // require '../dir2/file2.php';
  │   └── index.php // require 'file1.php';
  ├── dir2
  │   └── file2.php
  └── index.php // require 'dir1/file1.php';
    

The relative path in the require statement in file1.php describes correctly the path to file2.php from file1.php. However if dir0/index.php is run (ie. accessed by a browser) then when the require statement in file1.php is executed it will be considered by PHP to be in the directory that dir0/index.php is in and so the relative path to file2 will now be wrong and PHP will throw an error. If dir1/index.php is run there will be no problem because the path to file2.php from dir1/index.php is the same as the path to file2.php from file1.php.

A Solution

Let us look at the output of this statement:


  echo "<p>".__DIR__."</p>";
    

/srv/stevespages.org.uk/public/htdocs/code-examples/paths/include

__DIR__ is a "magic" constant that contains the path to a file that the constant is in. In particular the value of this path constant does not change when a file is included by another file which is in a different directory. This means that __DIR__ can be used to supply the path to an included file in a file that may be included by another file in a different directory. In the example given above where file1.php used the statement: require '../dir2/file2.php'; we can change this statement to require __DIR__ . '/../dir2/file2.php';. Now, both dir0/index.php and dir1/index.php.

We have prepended __DIR__, which gives us the absolute path to file1.php, to the relative path from file1.php to file2.php and so we have ended up with the absolute path to file2.php. This raises the question, why not just use an absolute path to file2.php n the include statement in file1.php?

Use Absolute Paths

The method of linking to a file from a file that is linked to itself that uses __DIR__ is an example of using an absolute path to a file. It may be better that simply writing out the absolute path as a string because if the whole project is moved the absolute paths's document root or one or two directories above and below it might change. __DIR__ will automatically adjust to reflect the new path and so some work may be saved adjusting paths after the change to, for example, a new server.

Conclusion

A version of file1.php with 1 relative and 3 different absolute paths to file2.php is shown below. Take your pick so long as it isnt the relative path which doesn't work for one of the index.php files...


  <?php
  require '../dir2/file2.php'; // only works for dir1/index.php
  require __DIR__ . '/../dir2/file2.php';
  require '/var/www/html/steve/code-examples/paths/r-directory/r4/dir2/file2.php';
  require $_SERVER['DOCUMENT_ROOT'] . '/steve/code-examples/paths/r-directory/r4/dir2/file2.php';
  $f1 = 'file1';
    

And what about using a URL? In this case it would presumably be: require 'stevespages.org.uk/code-examples/paths/r-directory/r4/dir2/file2.php';. Aghhhhhhh!!!!