Osztálybetöltési sorrend autoloader nélkül wildcard szabályokkal
Sziasztok!
Előre bocsájtom, hogy a projekt és ezzel a kérdés is meglehetősen kísérleti jellegű és önkényesen szűkre szabott peremfeltételekkel rendelkezik.
A kísérlet tárgya egy PHP-ban írt, FastCGI-t beszélni képes daemon. (Természetesen közelről sincs készen.) A probléma az osztály betöltéssel van, ugyanis azt a feltételt szabtam, hogy lehetőség szerint töltsön be minden osztályt, fájlt, stb. előre, tehát az autoloading kiesik a játékból.
Teremteni szeretnék egy lehetőséget, hogy ilyen szabályokat lehessen mondani:Ezzel viszont az a probléma, hogy a
Ötletek, amiket Tyr43ltől kaptam a probléma megoldására:
A projekt SVN repója itt található: http://svn.janoszen.com/repos/fw/trunk/framework/
A generált doksik pedig itt: http://svn.janoszen.com/docs/fw/framework/
(A kód egyelőre működésképtelen, proof-of-concept gyártása van folyamatban, pár demó kódot gyártottam benne.)
Köszönöm a segítséget.
■ Előre bocsájtom, hogy a projekt és ezzel a kérdés is meglehetősen kísérleti jellegű és önkényesen szűkre szabott peremfeltételekkel rendelkezik.
A kísérlet tárgya egy PHP-ban írt, FastCGI-t beszélni képes daemon. (Természetesen közelről sincs készen.) A probléma az osztály betöltéssel van, ugyanis azt a feltételt szabtam, hogy lehetőség szerint töltsön be minden osztályt, fájlt, stb. előre, tehát az autoloading kiesik a játékból.
Teremteni szeretnék egy lehetőséget, hogy ilyen szabályokat lehessen mondani:
\ClassLoader::import('PHP\Lang\*');
*
miatt betöltött fájlban is lehet ugyanilyen szabály. Hogyan tudnám megoldani, hogy a kötelező sorrendek be legyenek tartva a betöltésnél? (pl. szülőosztály betöltése)Ötletek, amiket Tyr43ltől kaptam a probléma megoldására:
- Reflectionnel nézzük végig betöltéskor az osztályt, hogy milyen függőségei vannak. Így csak az indulást lesz lassú.
- Induláskor húzzunk fel egy autoloadert a dependenciák feloldására.
A projekt SVN repója itt található: http://svn.janoszen.com/repos/fw/trunk/framework/
A generált doksik pedig itt: http://svn.janoszen.com/docs/fw/framework/
(A kód egyelőre működésképtelen, proof-of-concept gyártása van folyamatban, pár demó kódot gyártottam benne.)
Köszönöm a segítséget.
hogy idezzem magam: hat
hat futasidoben lehetne tokenizert vagy reflectiont hasznalni a dependenciak felderitesere, de az ***** lassu lenne, bar ha daemon, akkor az indulas lehetne lassu
de akkor meg mindig az a kevesbe gany megoldas, hogy felhuzod az autoloadert, betoltesz butan mindent, az autoloader feloldja a dependenciakat, majd ha felhuztal minden fajlt, akkor leszeded az autoloadert
utolag belegondolva a Reflection-os valszeg nem jo, ha nem tudod betolteni a class definiciot, akkor nem fogod tudni Reflection-nel lekerdezni sem hogy mibol van szarmaztatva, mit implemental, etc.
Tyrael
Egyszer régen... és egy jól működő
Egy lehetséges megoldás (csak elmélet):
Fejlesztés után egy scriptet ráeregetni a kódbázisra, ami meghatározza a függőségeket és azokat tárolja valahol (Az extends és implements alapján, valamint a ClassLoader::import hívások feldolgozásával). A probléma a változókkal lesz. Pl: ClassLoader::import('PHP/'.$module.'/*')
Betöltésnél ezen adatok alapján indulhat egy rekurzív csoda, ami elkezdi feltérképezni a függőségeket és betölti a fájlokat.
Ha jól strukturáltak a fájlok, akkor a * és egyebek szépen feldolgozhatók regexp-el, ezáltal a betöltendő osztályok listája is előállítható.
Az eredeti:
Régebben próbálkoztunk mi is hasonlóval, bár a megközelítés kicsit más volt.
Röviden az alap koncepció:
Mindig van autoloader a biztonság kedvéért.
Minden futásnál ellenőrizzük, hogy a kérés paraméterei alapján tárolunk-e infót.
Először semmilyen infó sem áll rendelkezésre a szükséges fájlokról. A futás végén a kérés adatai alapján egy azonosítót hozunk létre és ehhez tároljuk, hogy milyen fájlok lettek betöltve.
A következő futásnál már az azonosító alapján ismert a fájllista amit be kell tölteni.
Az autoloader mindig ott van, hogy ha valami olyan ágba kerülünk, ami eleddig nem szerepelt, akkor is beölthessük az osztályt.
Egy másik sokkal jobban működő (az ötlet nem az enyém, de itt a helye):
Maga a FW egy külön project / repó, amiben szépen struktúrált fájlok vannak. Módosítást ezekben kell végezni. Deploy-nál a fájlokat egy nagy fájlba fésüljük össze -> eredmény egy nagy fájl, ami a core-t tartalmazza.
Minden további project ezt a generált fájlt használja, valamint az autoloader a project specifikus osztályokat (helper, controller, view, stb) ez alapján tölti be.
Egy észrevétel a tiedhez:
A tokenizálás és a kód feldolgozása több erőforrást fog felemészteni, mint az autoloader. E nélkül pedig vagy tudnod kell, hogy milyen osztályokra van szükséged, amit nem tudsz a fájl betöltéséig.
Mindazonáltal kétségtelen, hogy remek fejtörő :)
Jó lenne.
Az erőforrások felemésztése egyébként nem gond, max a daemon indulása tart sokáig.
Miért nem preg_match?
Mivel a cél ha jól látom a java féle includeolás, ezért erre nagyon egyszerű regexpet írni. És erre akkor születhet egy rekurzív függvény, ami mielőtt includeolna egy filet, includeolja annak a depencenciáit. A körkörös hivatkozások feloldására esetleg lehet belerakni egy maximum rekurziós mélységet.
aki ert a regexhez, az
ugye lehetnek olyan hivatkozasok is, amiket a new szora kereses nem fed fel (fuggveny-re, valtozora, konstans-ra hivatkozas, indirekt hivatkozas (akar call_user_func* akar $variable() formaban)).
ezert tamogatnam azt, hogy a php parseolasat bizzuk a php-ra, es toltsuk be a hianyzo dependenciakat autoloaderrel, amit akar az indulas/minden class betoltese utan spl_autoload_unregister -rel le is lehet szedni, de ha ugyis felhuztunk minden class-t, akkor sosem fog meghivodni (ha megis, akkor igazabol jobb, hogy az autoloader szakitja meg a script futasat, mint ha a php dob egybol class not found hibat)
Tyrael
Megoldva