Myślę, że moje rozwiązanie pomoże Ci, jeśli wpadniesz na jakiś dobry pomysł, to daj znać:
(nawiasem mówiąc każda klasa przekłada się na lokalizację w ten sposób:
Projekt_Podgrupa_Costam -> /packages/projekt/podgrupa/projekt_podgrupa_costam.php
zdecydowałem się na to, aby każdy plik miał pełną nazwę klasy, a instalator tworzył pakiety klas.)
Plik poza_drzewkiem/packages/noname/noname_package.php
<?php
define('NN_SEP', DIRECTORY_SEPARATOR
);
function __autoload($sName) {
if (!(CORE :: Import($sName) || CORE :: ImportEx($sName))) {
echo 'Kaboooom! Reason? '.$sName.' not found!!!'; }
}
class CORE {
public static function Import
($sName, $sFind = null, $bSearch = true) { $sFind = $sName;
}
if ($bSearch && (class_exists($sFind, false) || interface_exists($sFind, false))) {
return true;
}
$sPath = NN_LIB
.implode(NN_SEP
, $aArr).NN_SEP
.$sName.'.php'; include_once ($sPath);
if ($bSearch && !(class_exists($sFind, false) || interface_exists($sFind, false)) ) {
return false;
}
return true;
}
return false;
}
public static function ImportEx
($sName) { if (CORE
:: Import
(implode('_', $aArr), $sName) || CORE
:: Import
($sName)) { return true;
}
return false;
}
}
?>
(zamiast kaboom w __autoload() będzie komunikat o tym, że strona nieczynna i próba poinformowania admina)
Pliki *_package.php zawierają zlepek klas najczęściej wykorzystywanych w danym pakiecie (noname_package.php zawiera noname_(core,timer,exception itp).php . )
ImportEx różni się tym, że najpierw spróbuje władować pakiet (czyli np. jak władowywyję jakąś usługę, dajmy SQL, to automatycznie mam wyjątki, klase do łączenia, klase do zapytań itp.)
Jeśli jestem pewien, że jakaś klasa/interfejs powinna być w systemie to poprostu z niej korzystam - jeśli nie jest władowana, to zrobi to autoload. (Klasa z pakietu nie musi sprawdzać innych z tego samego pakietu, najczęściej stosowana przeze mnie metoda)
Jeśli wgrywam usługę (auth, sql, cache...) to daję CORE::ImportEx, żeby wgrać pakiet.
Jeśli potrzebuję pojedynczą klasę to poprostu CORE::Import.
Obie funkcje Import i ImportEx zwracają true/false, czyli ustrzegają mnie przed wykorzystaniem nieistniejącej klasy, a co za tym idzie przed Fatal Error.
Przed próbą odczytania pliku oczywiście jest sprawdzenie, czy nie jest obecna już dana klasa/interfejs.