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()
{
}
}
}
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:
Core.Controls
is mapped to the physical directory /controls
.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. :)