Cytat(hawk @ 2006-01-24 09:54:37)
@NULL: IMHO rozwiązaniem problemu ze zbyt dużą liczbą wpisów jest sklejenie tego we większe pliki. Autoloadowanie tego wszystkiego zajmuje jednak sporo czasu. Ideałem jest dla mnie rozwiązanie, gdy po ustaleniu, jakie komponenty są nam potrzebne, robimy z tego wersję release pakując automatycznie do jednego pliku i tak dystrybuujemy. Lokalnie mamy wersję dev z rozbiciem na małe pliki, a dzięki autoloaderowi cała operacja jest przezroczysta - mamy tylko inną mapę. Natomiast plików specyficznych dla konkretnego żądania, np. klas akcji, nie warto pakować do mapy, bo by się zbyt duża zrobiła.
takie rozwiazanie jest kosztowne o tyle ze trzeba napisac cos na ksztalt kompilatora i linkera, ktory zajmnie sie przerobieniem wersji dev na produkcyjna. Nie jest moze to duzy problem bo napisanie to operacja jednorazowal ale zawsze po bokonaniu zmian przeba bedzie uzyc czegos co na nowo zapakuje nam klasy w pliki i wydaje mi sie ze jest to duzo zbednej i nikomu niepotrzebnej roboty zwlaszcza ze narzut czasowy zwiazany z dolaczaniem kolejnych plikow da sie zniwelowac w sosobo o jakim mowilem. Jest to rozwiaznie darmowe wydajne i nie trzeba niczego zmieniac w istniejacych projekatach.
Abstrachujac od tego co powiedzialem wczesniej, mam tu prosty przyklad na wykorzystanie funkcji __autoload():
autoload.lib.php:
<?php
function __autoload ( $className )
{
$classDir = './class/';
$separator = '_';
$path2Class = str_replace ( $separator, '/', $className );
require_once $classDir . $path2Class . '.class.php';
}
?>
a.class.php:
<?php
// moze byc zaladowane duzo wczesniej np. przez kontroler
require_once './autoload.lib.php';
class a
{
public function __construct ()
{
echo "<p>Zaraz zaladuje nowa klase </p>"; new katalog_b ();
}
}
new a();
?>
katalog_b.class.php:
<?php
class katalog_b
{
public function __construct ()
{
echo "jestem w klasie b </ br>"; }
}
?>
proste i pozwala na zdefiniowanie jednej prostej f-cji kotra zajmie sie sama wlaczaniem klas jesli taki nie zostaly jeszcze dolaczone.
Sposob nazewnistwa jest oczywiscie umowny i mozna stosowac dla rozroznienia katalogow i plikow male i wielkie litery lub cokolwiek innego. Mozna tez trzymac tablice globalna z plikami ktore juz zaladowalismy i sprawdzac czy oplaca sie uzyc f-cji *_once (to juz bylo chyba wspomniane), chociaz nie wiem czy jest sens bo jesli plik jest juz zaladowany to f-cja __autoload() nie zostanie wywolana.
Co jest tu problemem? Zewnetrzne pakiety i klasy na ktorych nazewnictwo i polozenie nie mamy wplywu. Moze tutaj zwykly include_path rozwiazalby problem? Napewno wystarcza to do PEAR co do innych pakietow to chyba tak czy siak trzeba rozpatrywac to osobno bo napewno autorzy kody przewidzieli swoje sosoby dolaczania innych klas itp.
Co o tym myslicie?
EDIT:
idac dalej mozna zadbac rowniez o wlaczanie interfejsow i wyjatkow w podobny sposob:
<?php
function __autoload ( $className )
{
$classDir = './classes/';
$classSuffix = '.class.php';
$interfaceDir = './interfaces/';
$interfaceSuffix = '.php';
$exceptionDir = './exceptions/';
$exceptionSuffix = '.php';
$separator = '_';
if ( $className[0] == 'i' )
{ // interfejs
$file = $interfaceDir . str_replace ( $separator, '/', $className ) . $interfaceSuffix; }
else if ( $className[0] == 'e' )
{ // wyjatek
$file = $exceptionDir . str_replace ( $separator, '/', $className ) . $exceptionSuffix; }
else
{ // klasa
$file = $classDir . str_replace ( $separator, '/', $className ) . $classSuffix; }
{
throw new eClassNotFound();
}
require $file;
}
?>
oczywiscie zmienne mozna ladowac z jakiegos configa ale mamy teraz wszystko co potrzeba nam do automatycznego ladowania klas