Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Włączanie plików + autoloader
Forum PHP.pl > Forum > PHP > Pro
Stron: 1, 2, 3, 4
hawk
@serafin: Trochę konsekwencji. Bardzo się starasz, żeby nie odpowiadać na moje pytania i nie podejmować merytorycznej dyskusji. Zamiast tego widzę, że bardzo lubisz młotki i wymyśloną przez siebie klasę String, bo już drugi post o tym piszesz, co nijak się ma do tematu. Możemy i tak...

@matid: IMHO nie da się przeskoczyć problemu zadeklarowanej już wcześniej "pustej" klasy. Bo za drugim razem po prostu nie uruchomi się autoloader. A tworzenie każdej klasy za pomocą specjalnej metody też jest możliwe, ale to już nie to samo.

Ale zastanawia mnie, w jaki sposób jesteś w stanie stwierdzić, czy pozwolić na utworzenie obiektu? Odpala się autoloader, klasa ma zasięg "directory". W jaki sposób stwierdzasz, czy wolno w tym miejscu utworzyć obiekt? Bo mi nic nie przychodzi do głowy sad.gif.
matid
Korzystam z debug_backtrace" title="Zobacz w manualu PHP" target="_manual
Nie sprawdzałem, na ile jest to wydajne, ale działa smile.gif
Innego pomysłu na razie nie mam.
Imperior
Cytat(matid @ 2005-06-17 06:42:50)
Chyba jednak skorzystam z opcji 1, ponieważ zasięgów nie chcę olewać, a tworzenie instancji przez proxy wyklucza takie przypadki jak dziedziczenie, implementowanie interfaców, itp.

W jaki sposób wyklucza? Nie rozumię...
matid
  1. <?php
  2. class Test1 extends Test2
  3. {
  4. }
  5. ?>

Jak wczytujesz ten plik i korzystasz z Autoloadera to skrypt automatycznie próbuje załadować plik z klasą Test2. Przez Proxy to nie przejdzie.
Poza tym, co z klasami zewnętrznymi? Też chciałbym, aby były obsługiwane przez autoloader, a przepisywać kod tak, aby korzystał z proxy jest bez sensu.
bela
Fajna bajeczka : http://groups.google.pl/groups?q=proxy&hl=....onet.pl&rnum=1 winksmiley.jpg
Imperior
Cytat(matid @ 2005-06-17 14:41:10)
Jak wczytujesz ten plik i korzystasz z Autoloadera to skrypt automatycznie próbuje załadować plik z klasą Test2. Przez Proxy to nie przejdzie.
Poza tym, co z klasami zewnętrznymi? Też chciałbym, aby były obsługiwane przez autoloader, a przepisywać kod tak, aby korzystał z proxy jest bez sensu.

Hm... też fakt. Nie zastanawiałem się nad tym zbytnio (ja wole autoloadera, proxy do tego nie używam). Zatem pozostaje jeszcze imitacja pakietów w nazwach klas. Czyli np. SQL_MySQL_Service.
squid
Jeszcze nie przeczytalem calego tematu wiec sory jesli odpowiedz juz padla ale czy nie mysleliscie o tym zeby wszystkie interfejsy trzymac w jednym lub kilku plikach pogrupowanych kategorie? Albo trzymac interfejs w pliku z klasa?
Moze to i troche malo eleganckie ale szkoda zapuszczac cala maszyne dla znalezienia i odczytania kilku linijek kodu a sa jeszcze klasy bez interfejsow
hawk
Tak naprawdę to wszystkie interfejsy powinno się wywalić przed oficjalnym wypuszczeniem kodu. Przecież są do niczego niepotrzebne... pomijając oczywiście type hinty i inne bzdety, które też w związku z tym powinno się wywalić. I pomijając kilka wrednych sytuacji, w których jednak nie da się wywalić, i dlatego pewnie automatyczny wywalacz interfejsów jeszcze nie powstał winksmiley.jpg.
Vengeance
Wywalić interfejsy? A niby z jakiej racji?
Przecież po to są by szuko móc dojść co klasa musi miec itd w przyszłości...
NuLL
@Hawk - napisać parser plików który będzie usuwał wszystko od słowa implements do napotkania słowa extends lub nawiasu klamrowego tongue.gif

Joking winksmiley.jpg

Wg. mnie częśc interfejsów jest potrzebna. Jak chocby dla jakiegoś sterownika. Nóż, widelec ktoś będzie miał ochote napisać własny - od tego mam interfejs smile.gif
matid
Jeśli kod jest wydany na zasadach OpenSource to mimo wszystko nie wyrzucałbym interface'ów. Jak ktoś inny będzie chciał sobie dostosować ten kod, itd. to będzie miał ułatwione zadanie.

A co do oprogramowania z zamkniętym źródłem - na etapie pisania aplikacji - interface to bardzo przydatna rzecz, w release'ach to tylko zbędne przeciążenie aplikacji.
hawk
Ale ja mówię o dwóch wersjach kodu: debug i release. Debug = mamy wszystkie komentarze, interfejsy, tak jak napisaliśmy. Release = wyrzucamy interfejsy, usuwamy komentarze, pakujemy po kilka klas do jednego pliku.

Też z tego powodu, że - jak wykazało profilowanie - autoloadowanie jest strasznie wolne.
chmolu
No jakoś mi się nie widzi usuwanie w kodzie $obj instanceof interfejs oraz zmienianie deklaracji funkcji, w których używam typehintingu.
Wcale nie uważam, że interfejsy są zbędne. Autoładowanie może i jest wolne, ale z włączonym akceleratorem różnica jest niewielka. Wiem, że nie każdy ma dostęp do akceleratora, ale dalej uważam, że usuwanie interfejsów z kodu to bezsens.
squid
Cytat(chmolu @ 2005-08-09 15:59:17)
No jakoś mi się nie widzi usuwanie w kodzie $obj instanceof interfejs oraz zmienianie deklaracji funkcji, w których używam typehintingu.
Wcale nie uważam, że interfejsy są zbędne. Autoładowanie może i jest wolne, ale z włączonym akceleratorem różnica jest niewielka. Wiem, że nie każdy ma dostęp do akceleratora, ale dalej uważam, że usuwanie interfejsów z kodu to bezsens.

czesciowo sie zgadzam ja tez nie bede usuwal nic z kodu "recznie" bo latwo o pomylke ale moze napisac cos co taka zmiane przeprowadzi robiwac z calej aplikacji pakiet + instalator gotowe do wyslanai na serwer.

Co do akceleratora to on tu nie pomoze bo jego zadanie jest inne ale pewnie zasugerowales sie nazwa Zend Accelerator smile.gif

Autoloader wiekszac czesc czasu spedza na includowaniu (mam nadzeje ze nikt nie uzywa require w autoloaderze winksmiley.jpg ) kodu mam tu namusli jego analize i przeksztalcenie do postaci posredniej. Tu pomoze bufor kompilatora ktorym jest np. Zend Accelerator ktory jest komercyjny ale jest tez APC darmowy i open source dostepny przez PECL do tego kazdy teoretycznie ma dostep.

Faktycznie juz przy 10 plikach widac jak duzo czasy zajmuje analaiza kazdego kolejnego a bufor znaczaco tu pomaga pytanie tylko czy budujac framework czy juz gotowa aplikacje mozemy wymagac aby w srodowisku produkcyjnym byla zainstalowana taka biblioteka? w zasadzie to nic wielkiego a oszczedza czas serwera ale sprobujcie przekonac do czegos takiego admina. Z drufgiej strony zbudowanie czegos co pousuwa rozne obiektowe ozdobniki zkodu troche potrwa a bufor to gotowe rozwiazanie dajace nawet przyros 100% w wydajnosci za darmo i bez dodatkowego nakladu pracy!!
NuLL
Macie może jakiś pomysł co zrobić z autoloaderem kiedy jest w nim 300 plikow ? Wiem ze to troche duzo ale tyle sie nazbieralo kolejnych klas, wyjatkow oraz interfejsow. I nie wiem co z tym zrobic ?

Ja wpadłem na pomysl aby zaladowac tylko najpotrzebniejsze mapy : request, db oraz kilka innych. Natomiast inne mapy mozna by ladowac np rozbijajac nazwe klasy z niej wyciagac dwa pierwsze czlony zalozmy i czyli nazwa pakietu i wtedy zaladowac mape do ktorej nalezy ta konkretna klasa. Co w Wy na to ?

Chetnie poslucham innych pomyslow.
bigZbig
Mozna zastosowac cos w rodzaju przestrzeni nazw. Wszystko zależy od tego jaki sie przyjelo sposob nazewnictwa. Ja wszystkie klasy z danego pakietu poprzedzam nazwa danego pakietu. W ten sposob moglbym latwo podzielic automape na kilka mniejszych czesci. Oczywiscie metoda ta nie nadaje sie do cudzych klas, ktore stosuja odmienna polityke nazewnictwa. Poza tym, na dobra sprawe jest to jedynie polowiczne rozwiazanie gdyz czesto np. na 20 klas z danego pakietu potrzebnych jest zaledwie 5.

Pozostaje rowniez problem odroznienia w nazwie klasy tego co jest przedrostkiem.

Jesli - mojPrzedrostek_wygladaTak.class.php - to nie ma problemu
Niestety - mojPrzedrostekWygladaTak.class.php - a to juz jest problem
NuLL
Ja cos takiego robie tzn mam ezcCacheStorageFileArray i rozbijam to po wielkosci znakow pomijajac pierwszy czlon pisany z malej litery i laduje mape to dla ezcCache.

Co do polowicznosci sie zgadzam m.in dlatego ostatnio twoje wiecej malych map winksmiley.jpg
bela
A po co rozbijac? Ja mam kilkaset linijek i smiga.
Poza tym zobacz do phienda 2, tam masz w kazdym komponencie osobną mape
squid
co nazywacie mapa? Czy jest to skojarzona z klasa sciezka dostepu (dla kazdej klasy)?
NuLL
Cytat
A po co rozbijac? Ja mam kilkaset linijek i smiga.
Poza tym zobacz do phienda 2, tam masz w kazdym komponencie osobną mape

W phiendzie komponentow jest nieduzo - u mnie jest ich okolo 30.

Rozbijam bo sie musze dostac do okreslonej mapy.

O co chodzi z tymi linijkami questionmark.gif
Ociu
Cytat(squid @ 2006-01-17 14:12:04)
co nazywacie mapa? Czy jest to skojarzona z klasa sciezka dostepu (dla kazdej klasy)?

Mapa to 'lista' scieżek i nazwy klas.

dajmy na to (posłuże się autoloaderem z phienda2):
  1. <?php
  2. $map = array (
  3. # przyklad: 'nazwa_klasy' => 'sciezka_do_pliku.php'
  4. 'Request' => './framework/request.class.php',
  5. 'Response' => './fremework/response.class.php'
  6. );
  7.  
  8. Autoloader::addMap($map);
  9. ?>


pozdrawiam
bela
NuLL, pytanie moje brzmi, czy każdy komponent może pracować oddzielnie? Tzn robisz ctrl c, v, wrzucasz do innego katalogu i działa.
Btw. co Ty masz w tych komponenach?
NuLL
bela_666 - moze, nie wszystkiego bo czesc jest zalezna od Db dla przykladu.

Co mam ? Db, Cache, Configuration, Template, Debug, Image itp itd. - Cala aplikacja krotko mowiac.
hawk
@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.
squid
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:
  1. <?php
  2. function __autoload ( $className )
  3. {
  4. $classDir = './class/';
  5. $separator = '_';
  6.  
  7. $path2Class = str_replace ( $separator, '/', $className );
  8.  
  9. require_once $classDir . $path2Class . '.class.php';
  10. }
  11. ?>


a.class.php:
  1. <?php
  2. // moze byc zaladowane duzo wczesniej np. przez kontroler
  3. require_once './autoload.lib.php';
  4.  
  5. class a
  6. {
  7. public function __construct ()
  8. {
  9. echo "<p>Zaraz zaladuje nowa klase </p>";
  10. new katalog_b ();
  11. }
  12. }
  13.  
  14. new a();
  15. ?>


katalog_b.class.php:
  1. <?php
  2. class katalog_b
  3. {
  4. public function __construct ()
  5. {
  6. echo "jestem w klasie b </ br>";
  7. }
  8. }
  9. ?>

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:
  1. <?php
  2.  
  3. function __autoload ( $className )
  4. {
  5. $classDir = './classes/';
  6. $classSuffix = '.class.php';
  7.  
  8. $interfaceDir = './interfaces/';
  9. $interfaceSuffix = '.php';
  10.  
  11. $exceptionDir = './exceptions/';
  12. $exceptionSuffix = '.php';
  13.  
  14. $separator = '_';
  15.  
  16. if ( $className[0] == 'i' )
  17. { // interfejs
  18. $file = $interfaceDir . str_replace ( $separator, '/', $className ) . $interfaceSuffix;
  19. }
  20. else if ( $className[0] == 'e' )
  21. { // wyjatek
  22. $file = $exceptionDir . str_replace ( $separator, '/', $className ) . $exceptionSuffix;
  23. }
  24. else 
  25. { // klasa
  26. $file = $classDir . str_replace ( $separator, '/', $className ) . $classSuffix;
  27. }
  28.  
  29. if ( !file_exists( $file) )
  30. {
  31. throw new eClassNotFound();
  32. }
  33.  
  34. require $file;
  35. }
  36. ?>


oczywiscie zmienne mozna ladowac z jakiegos configa ale mamy teraz wszystko co potrzeba nam do automatycznego ladowania klas
eMartio
Cytat(DeyV @ 2005-02-10 20:46:51)

Cytat
Takie mapy można nawet generować automatycznie przeszukując skryptem katalogi i parsując (tokenizując) pliki php.


Co oznacza pojęcie tokenizując w programowaniu? Token to symbol... w wolnym tłumaczeniu.

Cytat
Aby sprawę jeszcze bardziej skomplikować - warto pamietać o tym - że require_once i inlude_once jest w rzeczywistości bardzo wolne


A więc co polecasz? Najlepiej stosować samo: require i include? Czy może jeszcze coś innego?
matid
Cytat(eMartio @ 2006-03-31 19:40:31)
Co oznacza pojęcie tokenizując w programowaniu? Token to symbol... w wolnym tłumaczeniu.

Google dzisiaj nie działa?
http://google.com/search?q=define:tokenize
bela
Cytat(eMartio @ 2006-03-31 20:40:31)
Cytat
Takie mapy można nawet generować automatycznie przeszukując skryptem katalogi i parsując (tokenizując) pliki php.


Co oznacza pojęcie tokenizując w programowaniu? Token to symbol... w wolnym tłumaczeniu.

Sam tłumaczysz sobie winksmiley.jpg
To jest rozbicie pliku źródłowego na tablice symboli. Jest to pierwszy etap analizy kodu źródłowego.
Więcej, google: kompilator i interpretator
NuLL
Czy ktos moze wykonywal testy po jakims ciezkim obciazeniem aplikacji pracujacej na autoloaderze i bez niego ? Chetnie bym posluchal jakis opinii. Wiem ze jest to dosc wolne ale czy az tak questionmark.gif Zastanawia mnie tak kwiestia jakoze zalozmy Panowie z ez.no postanowili w eZ Components jechac na autoloadzie napewno zdajac sobie sprawe z problemu wydajnosci smile.gif

Co sadzicie o tym ? Pisac z __autoload() czy bez ? snitch.gif
Ludvik
Ja osobiście wszystko mam przygotowane pod autoloadera. Co z wydajnością? Przy cache mapy klas i włączonym xdebugu załadowanie wszystkich klas i systemu zajmuje ok. 35ms, a samo nawiązanie połączenia przez PDO z PostgreSQL na localhoście ok. 230, więc strata wydajności nie jest duża. Z tych 35ms połowa to require_once. Myślę, że nie jest to zbyt duża strata wydajności w porównaniu do ułatwienia pisania kodu.

Na poważnych serwerach kod zenda jest i tak trzymany w pamięci, więc straty są jeszcze mniejsze.
squid
przy dobrym projekcie autoloadera mozna ominac f-cje *_once mozna podniesc wydajnosc tak ze autoloadowanie bedzie praktycznie niezauwazalne
NuLL
@Ludvik - dzieki za wiesci - o cos takiego mi chodzilo smile.gif Teraz tylko czekac na otwarty autoloader od eZ components i po bolu.
Vengeance
To ciekawe co mówicie, bo w mojej aplikacji autoload() zajmował 98% czasu wykonywania (tak, tak... i to już z cache mapy w pliku!). Wróciłem do require_once. Zresztą takie rozwiązanie jest dużo czytelniejsze przy późniejszej analizie kodu. Wiadomo gdzie co jest trzymane winksmiley.jpg
squid
Cytat(Vengeance @ 10.06.2006, 18:38 ) *
To ciekawe co mówicie, bo w mojej aplikacji autoload() zajmował 98% czasu wykonywania (tak, tak... i to już z cache mapy w pliku!). Wróciłem do require_once. Zresztą takie rozwiązanie jest dużo czytelniejsze przy późniejszej analizie kodu. Wiadomo gdzie co jest trzymane winksmiley.jpg

pewnie te 98% czasu zajmowalo wlaczenie analiza i interpretacja kodu co chyba nie jest rownowazne z narzutem czasu samego autoloadera.

P.S.
Obecnie nie mam czasu ale za klika tygodni postawie odizolowana maszyne i przeprowadze profilowanie zeby sprawdzis te teorie
bigZbig
Ja tez uzywam autoloadera, ale nie tworze jednej globalnej tablicy, a juz napewno nie generuje jej automatycznie. Staram się tworzyć pakiety. Kazdy pakiet ma swoj plik inicjalizacyjny, w ktorym jest m.in. mapa klas. Jesli dolaczam dany moduł (pakiet) do aplikacji poprzez includowanie jego pliku inicjalizujacego to juz mechanizm zawarty w tym pliku zajmuje się dołączeniem mapy klas danego pakietu do ogolnej mapy klas całej aplikacji na ktorej operuje funkcja __autoload. Dla wygody testowania zaimplementowalem tez mozliwosc ominiecia autoloadera. Tracę tym może nieznacznie na wydajności, ale znacznie zyskuję na wygodzie. Poniższy przykład ilustruje to o czym pisałem:

  1. <?php
  2. /**
  3.  * @author hawk
  4.  */
  5. class bigAutoloader {
  6. private static $aMap = array();
  7.  
  8. public static function load($sName) {
  9. if (array_key_exists($sName, self::$aMap)) {
  10. include self::$aMap[$sName];
  11. }
  12. if (!class_exists($sName) && !interface_exists($sName)) {
  13. eval("class $sName { 
  14. public function __construct() { 
  15. throw new ClassNotFoundException('$sName not found'); 
  16. }
  17. }");
  18. }
  19. }
  20.  
  21. public static function addMap($aMap) {
  22. self::$aMap = array_merge(self::$aMap, $aMap);
  23. }
  24. }
  25. ?>


  1. <?php
  2. /**
  3.  * bigLang inicjalizator
  4.  */
  5. if (!defined('BIGLANG_DIR')) define('BIGLANG_DIR',dirname(__FILE__));
  6. $aClassesMap = array(
  7. 'bigLang' => BIGLANG_DIR.'/bigLang.abstract.php',
  8. 'bigLangManager' => BIGLANG_DIR.'/bigLangManager.class.php',
  9. );
  10.  
  11. if (class_exists('bigAutoloader')) {
  12. bigAutoloader::addMap($aClassesMap);
  13. } else {
  14. foreach($aClassesMap as $sClassName) {
  15. include_once($sClassName);
  16. }
  17. }
  18.  
  19. ?>



@Vengeance - wybacz, ale wydaje mi sie, że jednak się mylisz. Bo jeśli używając funkcji __autoload dołączam potrzemne pliki przy pomocy instrukcji include, lub require, a Ty posługujesz się require_once lub include_once to zadaj sobie pytanie co jest bardziej wydajne. Czy narzut czasowy potrzebny dla samego wywołania funkcji autoladujacej jest faktycznie tak duży? Poza tym autoloader dolancza jedynie te pliki, ktore sa wymagane, a zastosowanie bezposrednio *_once dołącza zawsze wszystkie pliki - nawet jesli ich zawartość nie jest w danym wywołaniu potrzebna.
Vengeance
Jakie argumenty by tu nie padały, i tak nic nie zmieni mojego "self experience" gdzie Zend pokazywał 98% dla samego autoloadu.

Ja nie twierdze, że ta metoda jest cool, albo że jest do dupy. Mówię tylko, że z początku stosowałem ją ale zrezygnowałem.

Jednym z argumentów przeciw jest choćby czytelność kodu (z mojego punktu widzenia).

Że już nie wspomne o np. umiejetnośći podpowiadania składni w edytorach :] Które bardzo mocno wspierają się na include i require w kodzie... a autoload powoduje oduczenie ich umiejętności poprawnego podpowiadania.
bigZbig
Argument o czytelności kodu do mnie nie przemawia bo wszystkie pliki dolanczam (dokladam do mapy klas) w scisle okreslonych miejscach. W plikach poszczegolnych klas nie ma miejsca na dolanczanie zaleznosci jak np. definicje wyjatkow. Od tego mam plik inicjalizujacy dany pakiet i jest to wygodne. W zasadzie przy takim podejsciu to nie ma znaczenia czy uzyjesz autoloadera, czy bezposrednio require.

Wada tego rozwiazania jest oczywiscie to, ze chcac uzyc tylko jednej klasy z calego pakietu musisz sie upewnic czy do jej dzialania nie jest wymagana obecnosc jakiegos innego pliku.

Co do edytorow i podpowiadania skladni - argument wart przemyslenia. Tak swoja droga jakiego edytora uzywasz?
NuLL
Cytat
Że już nie wspomne o np. umiejetnośći podpowiadania składni w edytorach :] Które bardzo mocno wspierają się na include i require w kodzie... a autoload powoduje oduczenie ich umiejętności poprawnego podpowiadania.

W Zendzie nie ma z tym problemu.
orson
witam

eclipse przechowuje informacje o wszystkich klasach w cache ... więc w nim nie ma problemu z używaniem metod z obiektów nie włączonych jawnie do kodu ...

używam autoloadera z mapą i uważam że jest to bardzo wydajne i wygodne rozwiązanie ... jak mi się uda to włączę xdebuga na jakimś serwerze u mnie w pracy i zrobię testy i profilowanie na żywej aplikacji (ale to po długim weekendzie dopiero)

pozdrawiam
eai
Ja generuje sobie mapę przy instalacji aplikacji. Zapisuje w pliku tekstowym z zakodowanym serialize();

Mapa wyglada tak:
Kod
Array
(
    [Action] => Array
        (
            [Dir] => Actions/
            [Elements] => Array
                (
                    [ImageFunctions] => Array
                        (
                            [Dir] => Image/
                            [Class] => Array
                                (
                                    [ImageHandler] => Array
                                        (
                                            [file] => Img.Handler.php
                                            [SubDir] =>
                                        )

                                    [ImageDraw] => Array
                                        (
                                            [file] => Img.Handler.php
                                            [SubDir] =>
                                        )

                                )

                        )

                    [SessionHandler] => Array
                        (
                            [Dir] => Session/
                            [Class] => Array
                                (
                                    [Session] => Array
                                        (
                                            [file] => Session.Handler.php
                                            [SubDir] =>
                                        )

                                )

                        )

                )

        )

    [Core] => Array
        (
            [Dir] => Core/
            [Elements] => Array
                (
                    [View] => Array
                        (
                            [Dir] => View/
                            [Class] => Array
                                (
                                    [view] => Array
                                        (
                                            [file] => view.php
                                        )

                                    [View] => Array
                                        (
                                            [SubDir] =>
                                        )

                                )

                        )

                )

        )

    [Plugin] => Array
        (
            [Dir] => Plugins/
            [Elements] => Array
                (
                    [DBHandler] => Array
                        (
                            [Dir] => DbHandler/
                            [Class] => Array
                                (
                                    [mySQL] => Array
                                        (
                                            [file] => Db.MySql.php
                                            [SubDir] =>
                                        )

                                    [pgSQL] => Array
                                        (
                                            [file] => Db.pgSql.php
                                            [SubDir] =>
                                        )

                                )

                        )

                )

        )

)


AutoLoader robie na 2 sposoby.
1. Szukam klasy w mapie i includuje ja sprawdzajac czy taki plik istnieje
2. Szukam Calego modulu Np ImageFunctions i includuje wszystkie klasy [nie Classy] z tej mapy.

--
"klasy"
dr_bonzo
squid
"bigZbig dla kaydego pakietu musisy kopiowac inicjaliyator cyz autoloade
mtod
Przepraszam, ale nie doczytałem tego wątku od deski do deski - limit czasu.
Kiedyś pisałem i niedawno też opisałem taką klasę autoloadera. Link. Wszelkie sugestie/komentarze wezmę chętnie pod uwagę =)
lukir
Mógłby ktoś z was podsumować wszystkie te rozważania jakimś zgrabnym kodem autoloader'a? Taki najbardziej wydajny i uniwersalny?


@mtod: Fajna ta klasa, ale możnaby dla większej elastyczności dodać możliwość ładowania również nowych klas...
mtod
@lukir: nie rozumiem, jak to: "nowych"?
lukir
@mtod: na podanej przez Ciebie stronce jest napisane coś takiego:



Cytat
Oczywiście cache należy stosować tylko w środowisku tzw. produkcyjnym, ponieważ w przeciwnym wypadku nowo dodane klasy będą poza zasięgiem autoloadera.




...,więc stąd moja propozycja, by rozszerzyć ten skrypt o możliwość automatycznego ładowania klas bez definiowania katalogu "produkcyjnego". Wtedy ten autoloader byłby wygodniejszy smile.gif
Ludvik
Wtedy ten autoloader straci na wydajności. Każdorazowe sprawdzanie całego drzewa katalogów jest czynnością zajmującą masę czasu. W moim systemie odświeżenie cache jest równe skasowaniu jednego pliku, więc nie wiem czy to takie męczące.
squid
wracajac do wydajnosci __autoload() to wspomniane wczesniej 90% czasu wykonania to jaka bzdura. Ponizej przedstawiam Wam wynik szybkiego profilowania mojej przykladowej aplikacji programem PECL APD
Kod
Total Elapsed Time = 0.27
Total System Time  = 0.05
Total User Time    = 0.06


         Real         User        System             secs/    cumm
%Time (excl/cumm)  (excl/cumm)  (excl/cumm) Calls    call    s/call  Memory Usage Name
--------------------------------------------------------------------------------------
28.6 0.01 0.01  0.02 0.02  0.02 0.02   242  0.0001   0.0001            0 is_array
14.3 0.06 0.08  0.02 0.03  0.00 0.00     9  0.0017   0.0035            0 require_once
14.3 0.00 0.08  0.02 0.06  0.00 0.00     5  0.0031   0.0125            0 include
14.3 0.01 0.01  0.00 0.00  0.02 0.02     4  0.0039   0.0039            0 defined
14.3 0.02 0.02  0.02 0.02  0.00 0.00    36  0.0004   0.0004            0 define
14.3 0.05 0.06  0.00 0.00  0.02 0.03    10  0.0016   0.0031            0 require
0.0 0.00 0.00  0.00 0.00  0.00 0.00     1  0.0000   0.0000            0 Forms_Register->_recursiveFilter
0.0 0.00 0.00  0.00 0.00  0.00 0.00     2  0.0000   0.0000            0 Forms_Register->_updateAttrArray
0.0 0.00 0.06  0.00 0.02  0.00 0.02     1  0.0000   0.0313            0 Forms_Register->registrationForm
0.0 0.00 0.00  0.00 0.00  0.00 0.00     2  0.0000   0.0000            0 Forms_Register->updateAttributes
0.0 0.00 0.04  0.00 0.00  0.00 0.02    11  0.0000   0.0014            0 Forms_Register->_loadElement
0.0 0.00 0.04  0.00 0.00  0.00 0.02    11  0.0000   0.0014            0 Forms_Register->addElement
0.0 0.00 0.00  0.00 0.00  0.00 0.00    11  0.0000   0.0000            0 Forms_Register->isTypeRegistered
0.0 0.00 0.00  0.00 0.00  0.00 0.00     4  0.0000   0.0000            0 Forms_Register->_parseAttributes
0.0 0.00 0.08  0.00 0.02  0.00 0.02     1  0.0000   0.0313            0 Registrations_RegistrationsOps->register
0.0 0.00 0.00  0.00 0.00  0.00 0.00     4  0.0000   0.0000            0 array_merge
0.0 0.00 0.00  0.00 0.00  0.00 0.00     2  0.0000   0.0000            0 View->setOutputData
0.0 0.00 0.02  0.00 0.00  0.00 0.00     2  0.0000   0.0000            0 Forms_Register->HTML_QuickForm
0.0 0.00 0.00  0.00 0.00  0.00 0.00     2  0.0000   0.0000            0 Forms_Register->HTML_Common
0.0 0.00 0.00  0.00 0.00  0.00 0.00     2  0.0000   0.0000            0 HTML_QuickForm_hidden->HTML_QuickForm_hidden


Widac ze samej f-cji autolad nie ma w zestawieniu pozeraczy czasu, czas zabiera wykonanie includow a to czy sa wywolywane bezposrednio czy w autoladerze nie ma znaczneia jest tylko roznica w wygodzie bo uwazam lepiej jest napisac
  1. <?php
  2. new JakasKlasa();
  3. ?>

niz
  1. <?php
  2. include 'JakasKlasa.php';
  3. new jakasKlasa();
  4. ?>
Denver
Ja, wykorzystując ujednolicone nazewnictwo klas, korzystam z autoloadera w taki sposób:

  1. <?php
  2. function __autoload ($strClass)
  3. {
  4. if ($strClass == 'Actions')
  5. {
  6. require_once ('./modules/class.Actions.php');
  7. }
  8. elseif (preg_match ('/Admin$/', $strClass))
  9. {
  10. require_once ('./modules/admin/lib/class.'.$strClass.'.php');
  11. }
  12. elseif (preg_match ('/Exception$/', $strClass))
  13. {
  14. require_once ('./lib/exceptions/class.'.$strClass.'.php');
  15. }
  16. else
  17. {
  18. require_once ('./modules/lib/class.'.$strClass.'.php');
  19. }
  20. }
  21. ?>


Żadne niepotrzebne klasy nie spowalniają mojego kodu - są wczytywane dopiero wtedy, gdy naprawdę są potrzebne. Świetnym przykładem mogą być klasy wyjątków. Możemy mieć 1000 różnych klas dziedziczących po Exception, które w żaden sposób nie spowalniają kodu, gdyż są ładowane dopiero po wyrzuceniu danego wyjątku.

Powyższe, bardzo proste rozwiązanie, jest raczej przeznaczone do małych projektów z maksymalnie kilkunastoma klasami działającymi podczas jednego żądania ze względu na użycie wyrażeń regularnych. Dla większych projektów zalecane jest oczywiście mapowanie wszystkich klas opisane w tym temacie chyba wystarczająco obszernie winksmiley.jpg
LBO
Bardzo przydatne przy pisaniu autoloadera mogą być funkcje get_declared_classes" title="Zobacz w manualu php" target="_manual i get_declared_interfaces" title="Zobacz w manualu php" target="_manual. Niestety wiążą się z tym pewne problemy:
  • W przeciwieństwie rozwiązań tutaj przedstawionych, powyższe funkcje muszą załadować plik i zarejestrować klasę, czyli przy dużym projekcie autoloader mógłby się wysypać w związku z ograniczeniami wielkości pamięci.
  • Strukturalny kod zawarty w pliku zostaje wykonany przy załadowaniu np.
    1. <?php
    2. ?>
Jakieś pomysły?
edit:
Po zastanowieniu drugi problem, chyba nie jest jednak taki ważny. Skoro autoloader w zamierzeniu istnieje dla ładowania klas, nie wyobrażam sobie sytuacji w której ktoś miałby dołączać do deklaracji klasy jakieś instrukcje strukturalne. Chociaż, fakt-faktem jest to możliwe, a autoloader powinien być na to odporny.
Co do wspomnianego limitu pamięci - testów nie robiłem i te standardowe 8M wbrew pozorom może pomieścić chyba dużo. A przecież klasy nie będą instancjonowane, z zasobów korzystać powinien tylko autoloader.
dr_bonzo
Cytat
Skoro autoloader w zamierzeniu istnieje dla ładowania klas, nie wyobrażam sobie sytuacji w której ktoś miałby dołączać do deklaracji klasy jakieś instrukcje strukturalne. Chociaż, fakt-faktem jest to możliwe, a autoloader powinien być na to odporny.

Taki exit to blad (w OOP), a bledy nalezy usuwac a nie hackowac (obchodzic) w autoloaderze.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.