skip to Main Content

I cant for the life of me get PHP’s ‘include’ statement to work on any files other than files in the same directory as the file using the ‘include’ statement. When I try to include any file from another directory the whole app breaks and nothing loads.

I dump that script in, say:

/var/www/html/fooA/testClass.php

and try to include it using:

/var/www/html/different_than_fooA/include_testClass.php

and the app breaks. However, if I include:

/html/foo_1.php

in:

/html/foo_2.php

everything works fine…

I promise this is not a simple syntax issue, I’ve tried writing it every way possible, using slashes in front, or no slash in front, whole directories and partial directories, IP addresses, even tried loading from other servers. My guess is it has to do with the way PHP or Apache is configured. Almost nothing hits on this matter that I can find floating around the internet, any advice would be great.

<?php
    // THIS FILE IS TEST/TEST02.php

    require 'TEST01.php';
    $V = new X();
    $V->Z();
?>

2

Answers


  1. You can always use PHP’s magic constants and that way you can be sure that it will figure out the correct path for you.

    /* lets say we have a folder structure like below
     *
     * - FolderA
     *  -- fileA.php
     * - FolderB
     *  -- fileB.php
     */
    
     // We require fileA.php in fileB.php, here is how we can do it
    
     require __DIR__.'/../FolderA/fileA.php';
    

    Here is the link to documentation. https://www.php.net/manual/en/language.constants.predefined.php

    Login or Signup to reply.
  2. By default PHP sets the include_path as follows:

    On *nix systems

    include_path=".:/php/includes"
    

    On Widows systems

    include_path=".;c:phpincludes"
    

    You can, and should, override these defaults to suit your environment as it is unlikely that you will have placed all the relevant files in these locations.

    Using a . in the include path allows for relative includes as it means
    the current directory. However, it is more efficient to explicitly use
    include ‘./file’ than having PHP always check the current directory
    for every include.

    In order to override the default locations use set_include_path("/path/to/includes/") etc which then allows a simple call to include the files like this:

    set_include_path("/path/to/includes/");
    include 'class.foobar.php';
    require 'functions.php'; // etc
    

    If you need to load class files one alternative would be to use the __autoload method equivalent and write your own callback to handle loading of files. The original __autoload method is deprecated but an improved spl_autoload class exists to facillitate this.

    The following references ALIASED_SITE_ROOT and ROOT_PATH which are globally defined constants on my system and point to particular directories so will not be relevant to you and will need editing if you decide to adopt this approach to loading classes.

    More info on “spl_autoload_register”

    function autoloader( $classname=false ){
    
        $included=get_included_files();
        $classname=rtrim( $classname, '.php' );
    
        $dirs = array(
            '/path/to/includes/',
            ALIASED_SITE_ROOT . '/inc/',
            ALIASED_SITE_ROOT . '/inc/forms/',
            ALIASED_SITE_ROOT . '/inc/lib/',
            ROOT_PATH . '/inc/',
            ROOT_PATH . '/'
        );
        /* add other locations to the above array */
        foreach( $dirs as $dir ) {
            $fullpath = $dir . $classname . '.php';
    
            if ( file_exists( $fullpath ) ) {
                if( !in_array( $fullpath, $included ) ) {
                    require_once( $fullpath );
                    clearstatcache();
                    break;
                }
            }
        }
        set_include_path( $dirs[ 0 ] );
    }
    spl_autoload_register( 'autoloader' );
    

    With the above registered in a common include file when you need to load a class you no longer need to do require '/path/to/includes/foobar.php'; when you need to work with the file you could simply do:

    $foo=new foobar(); // no need to use `require` or `include` as it has been autoloaded
    

    So the above works well with classes – a consistent naming strategy will help immensely if you adopt this approach! For example, I tend to locate all classes in what is shown above as ALIASED_SITE_ROOT . '/inc/' and use a naming convention of class.foobar.php so in the autoload function

    $fullpath = $dir . $classname . '.php';
    

    is actually

    $fullpath = $dir . 'class.' . $classname . '.php';
    

    It follows that the class name must match the name given by $classname, for example:

    class foobar{
        public function __construct(){
           /* etc */
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search