PHP Class: AutoLoader

Oricine a adoptat metodologia OOP in lucrul cu PHP cu siguranta s-a bucurat la implementarea functiei __autoload in PHP 5, ce permite incarcarea automata a fisierului corespunzator unei clase la momentul invocarii acesteia.

Probleme

In ciuda potentialului imens adus de aceasta functionalitate, majoritatea cartilor de specialitate prezinta doar cel mai elementar exemplu pentru exploatarea acestei functii, si anume simpla incarcare a fisierului cu numele identic sau asemanator cu cel al clasei necesare:

1
2
3
function __autoload($class_name) {
    require_once $class_name . '.php';
    }

Imediat dupa trecerea entuziasmului, incepem sa observam minusurile acestei abordari:

Cerinte

Una din marile frumuseti ale programarii este ca permite transpunerea logicii gandirii umane intr-un limbaj “inteles” de catre tehnologiile disponibile. La fel este si cazul procesului decizional ce urmeaza:

Solutie

Dupa ce a trecut prin mai multe iteratii si versiuni (si probabil va mai trece), va invit sa descarcati si folositi versiunea actuala a clasei AutoLoader. Modul de utilizare este simplu, doar incarcati fisierul in care se afla aceasta, si folositi urmatoarea varianta a functiei __autoload:

1
2
3
4
5
6
7
8
9
function __autoload($class) {
	$class_dirs = array("./"); // array ce va contine directoarele in care vom cauta (inclusiv subdirectoarele acestora, recursiv)
	$autoloader = new AutoLoader($class_dirs, 'autoloader-cache.php');
	try {
		$autoloader->loadClass($class);
		} catch (Exception $e) {
			exit($e->getMessage());
			}
	}

Puteti vedea output-ul unui scurt exemplu aici, ce contine urmatorul cod PHP:

1
2
3
include("AutoLoader.class.php");
include("autoload.func.php");
new Test;

Avantaje

Dezavantaje

Unul din dezavantajele minore ale acestui sistem este imposibilitatea existentei a doua clase cu acelasi nume. In cazul in care numele a doua clase coincid, locatia primei intalnite la scanarea fisierelor va fi suprascrisa in fisierul de cache de catre cea de-a doua.

Cu toate ca in mod normal nu ar trebui sa existe doua clase denumite la fel, se impune in acest fel o atentie sporita in momentul utilizarilor de clase / plugin-uri “3rd party”, deoarece numele uneia din acestea poate coincide cu cel al unei clase deja existente.

Download

Puteti downloada atat clasa AutoLoader, cat si toate fisierele corespunzatoare exemplului anterior:

Download AutoLoader.class.php
Download exemplu

Ca de obicei, sunt foarte interesat de eventualele imbunatatiri / modificari pe care le-ati propune. De asemenea, daca depistati bug-uri, as fi recunoscator daca mi le-ati indica.

Comments

11 Responses to “PHP Class: AutoLoader”

  1. Florin
    on April 2nd, 2008 07:46

    file_exists este o functie destul de costisitoare ca timp/resurse, ca dealtfel orice incercare de acces pe hard.
    Daca ai un server mai incarcat, nu e prea recomandat sa folosesti sistemul asta de autoload, si ingeneral cea mai buna masura de otimizare in orice site este sa reduci interactiunea cu hard-ul.

  2. Victor Stanciu
    on April 2nd, 2008 08:37

    Salut Florin,

    Good point, orice metoda de autoload vei folosi se va lovi de o problema de acest gen la un moment dat. Nu poti sari peste toate verificarile.

    In orice caz, am actualizat atat sursa cat si arhiva. Avand in vedere ca oricum se verifica daca fisierul de cache poate fi inclus, verificarea daca acesta exista este oarecum redundanta.

    Prin urmare, inainte de Exception-ul corespunzator cazului in care nu poate include fisierul, acum se face o reincercare (inclusiv a recreeri lui).

    Multumesc :)

  3. aurelian
    on April 2nd, 2008 20:43

    folosesc de ceva timp functiile spl_autoload* pentru a adauga functionalitati similare plugin-urilor, sau configuratii de autoload per folder/”pachet”. mi se pare o metoda bunicica daca nu vrei sa folosesti nume urate pentru clase cu _ sau alte conventii.

  4. Victor Stanciu
    on April 2nd, 2008 20:54

    Salut Aurelian, foarte interesanta abordare. Voi cerceta in directia asta.

    Intr-adevar daca faci uz de foarte multe “pachete” cum le-ai numit tu externe, la un moment dat te vei vedea in situatia de a avea dificultati in alegerea unui nume cat mai descriptiv si natural pentru o clasa.

    Orice pas in directia rezolvarii acestei probleme clar merita studiat indeaproape. Pacat ca documentatia functiilor din SPL este cel putin lacunara. Poate vei gasi la un moment dat un scurt timp si pentru o exemplificare :)

  5. aurelian
    on April 2nd, 2008 23:51

    M-am apucat sa imi refac “frameworku’” si acum am pus niste fisiere init.php pentru fiecare “pachet” in parte.
    De exemplu asta: http://svn.berlios.de/svnroot/repos/medick/exp/medick2/vendor/medick/lib/context/init.php cu un document “draft” “aici”:http://svn.berlios.de/svnroot/repos/medick/exp/medick2/AUTOLOAD.
    Codul prezentat acolo este experimental / netestat si scris prin avion, acum l-am pus si in svn ca exemplu :)

  6. Dragos
    on May 11th, 2008 11:03

    Eu fac un scan recursiv la directoarele din include_path si fac un cache intr-un array in format php cu var_export(). Daca o clasa exista in mai multe path-uri, va fi pastrata cea din prima locatie gasita.

    Deci conteaza ordinea din include_path – intai pun librariile mai “mici” si apoi cele “mai mari”.

    (Side note: asta e util si pentru ca poti sa “override” anumite clase daca ai vrea sa faci asta, desi nu stiu cat de buna ar fi aceasta practica.)

    Daca atunci cand se autoincarca o clasa incluziunea esueaza (nu fac verificarea file_exists pentru ca e scumpa, doar include()), se regenereaza cache-ul. Daca nici dupa regenerare nu se poate include, atunci “Class not found” :)

    Sper ca are sens.

  7. Dragos
    on May 11th, 2008 11:57

    Sorry, am comentat inainte sa ma uit la codul tau. That’s it.

  8. Victor Stanciu
    on May 11th, 2008 15:57

    Salut Dragos,

    Citeam comentariul tau si ma tot intrebam unde vrei sa ajungi si care e diferenta fundamentala :)). Intr-adevar asta e si sistemul propus de mine.

    Multumesc oricum :)

  9. gion
    on October 21st, 2008 22:53

    Salve,

    Dar de ce ai vrea sa faci asta in primul rand, de ce ai vrea sa incarci o clasa de oriunde ?

    Orice cache ai face tot e nasol, cel mai bine e eventual sa-ti “compilezi” fiserele dintr-un “package” intr-unul singur, gen Doctrine compiled …

    Dar si asta e nasol, ce castigi pe disk queries, pierzi pe disk access.

    TF with it … probabil ca intr-o buna zi v-a avea si “asta”, php “asta” … un bytecode compiler de la “tatal” lui (bcompiler :P)

  10. Liviu
    on February 12th, 2010 16:47

    Salut Victor,

    Vre-o șansă să mai găsesc pe undeva sursele de mai sus ?

    Mulțam.

  11. misu
    on May 19th, 2010 21:26

    Poti repune sursele? ca nu iti merg linkurile

Leave a Reply