5

I'm currently developping a PHP web application and I would like to know what is the best manner to include files (include_once) in a way where the code it is still maintanable. By maintanable I mean that if I want to move a file, It'd be easy to refactor my application to make it work properly.

I have a lot of files since I try to have good OOP practices (one class = one file).

Here's a typical class structure for my application:

namespace Controls
{
use Drawing\Color;

include_once '/../Control.php';

class GridView extends Control
{
    public $evenRowColor;

    public $oddRowColor;

    public function __construct()
    {
    }

    public function draw()
    {
    }

    protected function generateStyle()
    {
    }

    private function drawColumns()
    {
    }
}
}
Jean-Philippe Leclerc
  • 6,713
  • 5
  • 43
  • 66
  • I've had this question too, and I've come to the result that PHP really doesn't have a very good package system. Netbeans does help though. – Dhaivat Pandya Mar 23 '11 at 02:10

2 Answers2

6

I used to start all my php file with:

include_once('init.php');

Then in that file I would require_once all the other files that needed to be required, like functions.php for example, or globals.php where I would declare all global variables, or constants. That way you only have to edit all your setting at one place.

nana
  • 4,426
  • 1
  • 34
  • 48
  • 3
    to make this even more maintainable, you could define the path to the init (or config, as i usually call them) file as an environment variable. No matter how deep the directory structure of the app gets, every file can just import `$_ENV['my_app_config']` and not have to worry about stuff like `include_once('../../../init.php')`. –  Mar 23 '11 at 02:12
4

It depends on what you are trying to accomplish exactly.

If you want to have a configurable mapping between files and the directories in which they reside you need to work out a path abstraction and implement some loader functions to work with that. I 'll do an example.

Let's say we will use a notation like Core.Controls.Control to refer to the (physical) file Control.php which will be found in the (logical) directory Core.Controls. We 'll need to do a two-part implementation:

  1. Instruct our loader that Core.Controls is mapped to the physical directory /controls.
  2. Search for Control.php in that directory.

So here's a start:

class Loader {
    private static $dirMap = array();

    public static function Register($virtual, $physical) {
        self::$dirMap[$virtual] = $physical;
    }

    public static function Include($file) {
        $pos = strrpos($file, '.');
        if ($pos === false) {
            die('Error: expected at least one dot.');
        }

        $path = substr($file, 0, $pos);
        $file = substr($file, $pos + 1);

        if (!isset(self::$dirMap[$path])) {
            die('Unknown virtual directory: '.$path);
        }

        include (self::$dirMap[$path].'/'.$file.'.php');
    }
}

You would use the loader like this:

// This will probably be done on application startup.
// We need to use an absolute path here, but this is not hard to get with
// e.g. dirname(_FILE_) from your setup script or some such.
// Hardcoded for the example.
Loader::Register('Core.Controls', '/controls');

// And then at some other point:
Loader::Include('Core.Controls.Control');

Of course this example is the bare minimum that does something useful, but you can see what it allows you to do.

Apologies if I have made any small mistakes, I 'm typing this as I go. :)

Jon
  • 428,835
  • 81
  • 738
  • 806