Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Konfiguracja frameworka w XML
Forum PHP.pl > Forum > PHP > Object-oriented programming
Stron: 1, 2
squid
Szukam sposobu na konfiguracje frameworka. stwierdzilem ze konfiguracji moze byc tak duzo ze sesnownie byloby wykorzystac plik xml to trzymania konfiguracji.
Tu meczy mnie kilka watpliwosci, ktroe mam nadzieje pomozecie mi rozwiac.

Jak czytac plik konfiguracyjny XML. Waham sie miedzy PEAR::Config a SimpleXML z php5 a mmoze warto siegnac po inne rozwiazanie.

Druga sprawa to wydajnosc. Oczywiscie szkoda by bylo zeby kazde wywolanie strony wizalo sie z przetworzeniem XML'a wiec wymyslilem sobie ze sprasuje plik tylko przy pierwszym ladowniau i umieszcze go w tablicy $_SESSION albo stworze obiekt do ktorego wrzuce konfiguracje i umieszcze calosc w zmiennej sesji.

Powiedzcie mi czy moje myslenie idzie w dobrym kierunku i jak Wy to robicie.
Bede tez wdzieczny za linki smile.gif
nospor
Co do wydajności. Przy pierwszym wczytaniu xml załaduj go do cache. Sesja będzie trzymala xml tylko dla danego gościa. Kolejny gostek bedzie musial znowu wczytywac xml. Cache będzie dzialal dla każdego. W przypadku zmiany konfiguracji wystarczy tylko cache usunąć.
Jest parę bibliotek do cache - poszukaj
squid
Cytat(nospor @ 2005-07-04 11:44:40)
Co do wydajności. Przy pierwszym wczytaniu xml załaduj go do cache. Sesja będzie trzymala xml tylko dla danego gościa. Kolejny gostek bedzie musial znowu wczytywac xml. Cache będzie dzialal dla każdego. W przypadku zmiany konfiguracji wystarczy tylko cache usunąć.

No ale cache tez gdzies trzeba zapisac i pewnie na dysku wiec i tak bede mial odczyt z dysku co zajmuje chwile tyle ze wydaje mi sie postac bedzie inna np. tablica php a skoro tak to moze wogole lepiej trzymac konfiguracje w tablicy i tak ja stworzyc na poczatku?
DeyV
heh - ale pamietaj o 2 rzeczach.

1. Sesja również jest trzymana na dysku - w serializowanej tablicy, któa jest ładowana do pamięci w trakcie uruchamiania skrytpu.
Twoje cache może byc ładowane w identyczny sposób.

2. możesz podzielić konfiguracje na grupy, i ładować odpowiednie tylko w razie potrzeb - co jeszcze bardziej podniesie wydajność cache.
nospor
Cytat
odczyt z dysku co zajmuje chwile tyle
Odczyt zawartości pliku jest i tak o wiele szybszy niż odczyt i parsowanie pliku xml
squid
Cytat(DeyV @ 2005-07-04 11:54:33)
1. Sesja również jest trzymana na dysku - w serializowanej tablicy, któa jest ładowana do pamięci w trakcie uruchamiania skrytpu.
Twoje cache może byc ładowane w identyczny sposób.

2. możesz podzielić konfiguracje na grupy, i ładować odpowiednie tylko w razie potrzeb - co jeszcze bardziej podniesie wydajność cache.

ad. 1 - jestem tego swiadom. wiec moze skrypt powinien sprawdzac czy istnieje plik z serializowana konfiguracja jesli tak to go czyta jesli nie to przetwarza XML i zapisuje taki plik. Do serializacji uzylbym po prostu f-cji serialize.
A wracajac do sesji jesli zamisat zwyklego pliku uzylbym bazy danych do przechowywania sesji to dla duzej konfiguracji moglbym osiagnac jakies zyski czasowe?


ad. 2
no powiedzmy ze podziele sobie konfigurace ja czesci:
a) baza danych
cool.gif istniejace w systemie modele (kozystam z MVC)
c) dopuszczalne wartosci dla tablic POST i GET
d) dane dodatkowe dla konkretnego modelu

nic wiecej na razie nie trzymam w konfiguracji wiec przy takim podziale punkty a-c laduje zawsze bo sa niezbede do odslugi zapytania i d zalaczam dopiero gdy odnaleziono model. Ale dochodza mi tu dodatkowe operacje odczytu w koncu zawsze jakis podel jest wywolywany wiec w takim przypadku odczytuje 2 pliki i jeszcze musze sprawdzic czy istnieja a to kolejne dwa ruchy glowicy. Moze otwieranie jednego duzego pliku z cala konfiguracja trwa nieco mnie? chyba to przetestuje winksmiley.jpg
NuLL
Cytat
A wracajac do sesji jesli zamisat zwyklego pliku uzylbym bazy danych do przechowywania sesji to dla duzej konfiguracji moglbym osiagnac jakies zyski czasowe?

Nie będzie takowych - odczyt z dysku jest szybszy niż zapytania do bazy.
Cytat
a) baza danych
istniejace w systemie modele (kozystam z MVC)
c) dopuszczalne wartosci dla tablic POST i GET
d) dane dodatkowe dla konkretnego modelu

To wszystko można zcache'wac - pozatym podpunkt cool.gif - nie lepiej to dopisać do konfigu jakieś tam akcji i każda miała by przyporządkowane potrzebne jej zmienne :?:
squid
Zrobilem sobie przykladowy kod ale cos "dserializowanie" mi nie dziala, oto kod:

  1. <?php
  2. class configuration
  3. {
  4. public $conf = array ();
  5.  
  6. public function __construct ()
  7. {
  8. $cacheFile = './cache/configuration.ctmp';
  9. if ( file_exists ( $cacheFile ) )
  10. {
  11. $this->conf = unserialize ( readfile ( $cacheFile ) );
  12. var_dump ( $this->conf );
  13. echo '<p><p>';
  14. }
  15. else
  16. {
  17. $this->conf = simplexml_load_file('./xml/configuration.xml');
  18. var_dump ($this->conf);
  19. echo '<p><p>';
  20. file_put_contents ( $cacheFile, serialize ( $this->conf ) );
  21. }
  22. return true;
  23. }
  24. }
  25. ?>

a wywoluje to w innym pliku:


  1. <?
  2.  
  3. require ( './class/configuration.class.php' );
  4.  
  5. $c = new configuration();
  6. echo '<h1>test</h1>';
  7. var_dump ( $c->conf );
  8.  
  9. ?>


no ale po odczycie pliku cache i uzyciu unserialize ciagle dane sa zserializowane. Cos przeoczylem??
nospor
readfile wyrzuca ci plik na wyjscie a zwraca liczbe a nie zawartosc pliku. uzyj file_get_contents.

pozatym sprawdz czy ci wogole w chodzi w czytanie cache:

  1. <?php
  2.  
  3. class configuration
  4. {
  5. public $conf = array ();
  6.  
  7. public function __construct ()
  8. {
  9. $cacheFile = './cache/configuration.ctmp';
  10. if ( file_exists ( $cacheFile ) )
  11. {
  12. $this->conf = unserialize ( file_get_contents ( $cacheFile ) );
  13. var_dump ( $this->conf );
  14. echo '<p>z cache</p>';
  15. }
  16. else
  17. {
  18. $this->conf = simplexml_load_file('./xml/configuration.xml');
  19. var_dump ($this->conf);
  20. echo '<p>do cache</p>';
  21. file_put_contents ( $cacheFile, serialize ( $this->conf ) );
  22. }
  23. return true;
  24. }
  25. }
  26.  
  27. ?>
squid
Cytat(nospor @ 2005-07-04 14:24:35)
readfile wyrzuca ci plik na wyjscie a zwraca liczbe a nie zawartosc pliku. uzyj file_get_contents.

pozatym sprawdz czy ci wogole w chodzi w czytanie cache:

o tym zapomnialem winksmiley.jpg teraz mam tak:
  1. <?php
  2. class configuration
  3. {
  4. public $conf = array ();
  5.  
  6. public function __construct ()
  7. {
  8. $cacheFile = './cache/configuration.ctmp';
  9. if ( file_exists ( $cacheFile ) )
  10. {
  11. $string = file_get_contents ( $cacheFile );
  12. echo $string.'<p>';
  13. $this->conf = unserialize ( $string );
  14. var_dump ( $this->conf );
  15. echo '<p><p>';
  16. }
  17. else
  18. {
  19. $tmp = simplexml_load_file('./xml/configuration.xml');
  20. $this->conf = $tmp;
  21. var_dump ($this->conf);
  22. echo '<p><p>';
  23. file_put_contents ( $cacheFile, serialize ( $this->conf ) );
  24. }
  25. return true;
  26. }
  27. }
  28. ?>

czyta mi ladnie i zapisuje ale unserialize zwraca blad:
Warning: unserialize() [function.unserialize]: Node no longer exists in configuration.class.php on line 13
to samo dla lini 14
nospor
będę strzelal, gdyż nigdy nie uzywalme simplexml_load_file. Ty chyba serializujesz referencje do obiektów (nodów), które przy wczytywaniu z cache poprostu nie istnieją, czyli ze serialize dzialalo na referencjach a nie obiektach
squid
Cytat(nospor @ 2005-07-04 14:39:43)
będę strzelal, gdyż nigdy nie uzywalme simplexml_load_file. Ty chyba serializujesz referencje do obiektów (nodów), które przy wczytywaniu z cache poprostu nie istnieją, czyli ze serialize dzialalo na referencjach a nie obiektach

nie jestem pewien czy dobrze Cie rozumiem ale oto wartosc wczytana z cache:
Cytat
O:16:"SimpleXMLElement":3:{s:4:"lang";O:16:"SimpleXMLElement":1:{s:7:"default";s:2:"pl";}s:5:"ldata";a:2:{i:0;O:16:"SimpleXMLElement":3:{s:2:"id";s:2:"pl";s:6:"coding";s:10:"ISO 8859-2";s:4:"name";s:6:"Polski";}i:1;O:16:"SimpleXMLElement":3:{s:2:"id";s:2:"en";s:6:"coding";s:10:"ISO 8859-1";s:4:"name";s:7:"English";}}s:2:"db";O:16:"SimpleXMLElement":5:{s:2:"db";s:5:"mysql";s:4:"host";s:9:"localhost";s:5:"login";s:4:"user";s:4:"pass";s:4:"pass";s:8:"database";s:4:"data";}}

poza tym w manualu:
Cytat
object simplexml_load_file ( string filename [, string class_name [, int options]] )

i na stronie http://zend.com/php5/articles/php5-simplexml.php :
Cytat
With SimpleXML, element names are automatically mapped to properties on an object, and this happens recursively.

wiec wyglada to na obiekty wg mnie


EDIT:
napisalem podobna klase dla sesji:
  1. <?php
  2. class configuration2
  3. {
  4. //public $conf = array ();
  5.  
  6. public function __construct ()
  7. {
  8. $cacheFile = './cache/configuration.ctmp';
  9. if ( isset ( $_SESSION['configuration'] ) )
  10. {
  11. var_dump ( $_SESSION['configuration'] );
  12. echo '<p><p>';
  13. }
  14. else
  15. {
  16. $_SESSION['configuration'] =
  17. simplexml_load_file('./xml/configuration.xml');
  18. var_dump ( $_SESSION['configuration'] );
  19. echo '<p><p>';
  20. }
  21. return true;
  22. }
  23. }
  24. ?>

plik test.php:
  1. <?
  2.  
  3. require ( './class/configuration2.class.php' );
  4.  
  5. $c = new configuration2();
  6. echo '<h1>test</h1>';
  7. //var_dump ( $c->conf );
  8. var_dump ( $_SESSION['configuration'] );
  9.  
  10. ?>

i o dziwo tez mam problemy:
Cytat
Warning: session_start() [function.session-start]: Node no longer exists in test.php on line 5

Warning: var_dump() [function.var-dump]: Node no longer exists in class\configuration2.class.php on line 11
object(SimpleXMLElement)#1 (0) { }


sprawdzilem dla innych aplikacji ktore wczesniej dzialaly i przy wywolaniu session_start() jest tez ten problem, wyglada wiec na to ze to serwer zawodzi, zrestartowalem i nic, ktos ma pomysl jak emu zaradzic?
Uzywam php 5.0.3
bela
Eh, znany błąd, nie można serializować obiektów simplexml. Najpierw sobie to do tablicy przekonwertuj.
squid
Cytat(bela_666 @ 2005-07-04 16:47:11)
Eh, znany błąd, nie można serializować obiektów simplexml. Najpierw sobie to do tablicy przekonwertuj.

przegladalem changelog'a do 5.0.4 i zalatano tam kilka dziur odnosnie simpleXML ale czy zalatano i ten? bo ja niezauwazylem ale moze czytac nie umiem winksmiley.jpg

EDIT: a jak dokonac takiej konwersji z obiektu do tablicy??
hwao
Przenosze.
php pro -> PHP5
czemu, chyba nie musze tlumaczyc.
bela
Cytat(squid @ 2005-07-04 16:49:13)
Cytat(bela_666 @ 2005-07-04 16:47:11)
Eh, znany błąd, nie można serializować obiektów simplexml. Najpierw sobie to do tablicy przekonwertuj.

przegladalem changelog'a do 5.0.4 i zalatano tam kilka dziur odnosnie simpleXML ale czy zalatano i ten? bo ja niezauwazylem ale moze czytac nie umiem winksmiley.jpg

EDIT: a jak dokonac takiej konwersji z obiektu do tablicy??

Albo jakąś funkcją simplexml2array albo, co ja preferuje, wszystko po kolei parsujemy w foreach
squid
probowalem z foreachami ale tak latwo sie nie dalo, ostatecznie uzylem f-cji z manuala i wyglada to tak:
  1. <?php
  2. class configuration2
  3. {
  4. public $conf = array ();
  5.  
  6. public function __construct ()
  7. {
  8. $cacheFile = './cache/configuration.ctmp';
  9. if ( isset ( $_SESSION['configuration'] ) )
  10. {
  11. var_dump ( $_SESSION['configuration'] );
  12. echo '<p><p>';
  13. }
  14. else
  15. {
  16. $conf = simplexml_load_file('./xml/configuration.xml');
  17. //$tmp = array_values($conf);
  18. $_SESSION['configuration'] = $this->simplexml2array ( $conf );
  19. var_dump ( $_SESSION['configuration'] );
  20. echo '<p><p>';
  21. }
  22. return true;
  23. }
  24.  
  25. private function simplexml2array($xml)
  26. {
  27. if (get_class($xml) == 'SimpleXMLElement')
  28. {
  29. $attributes = $xml->attributes();
  30. foreach($attributes as $k=>$v)
  31. {
  32. if ($v) $a[$k] = (string) $v;
  33. }
  34. $x = $xml;
  35. $xml = get_object_vars($xml);
  36. }
  37. if (is_array($xml))
  38. {
  39. if (count($xml) == 0)
  40. {
  41. return (string) $x; // for CDATA
  42. }
  43. foreach($xml as $key=>$value)
  44. {
  45. $r[$key] = $this->simplexml2array($value);
  46. }
  47. if (isset($a))
  48. {
  49. $r['@'] = $a; // Attributes
  50. }
  51. return $r;
  52. }
  53. return (string) $xml;
  54. }
  55. }
  56. ?>
hawk
Całe to parsowanie XML do zserializowanej tablicy/obiektu simplexml/whatever ma na celu zwiększenie wydajności, więc simplexml2array jest IMHO błędnym rozwiązaniem.

Bo dostajesz dosyć skomplikowaną tablicę, odzwierciedlającą jakoś tam strukturę XMLa. A przecież nie potrzebujesz tablicy. Potrzebujesz obiektów skonfigurowanych za pomocą tej tablicy. Sama tablica nic nie robi. Szybciej jest zserializować gotowe do użycia obiekty, niż tworzyć je od nowa na podstawie tej tablicy za każdym razem.

Nie żebym się chwalił, ale patrz phiend2 winksmiley.jpg.
NuLL
@hawk - załóżmy, że ten config się zmienia bądź jest zależny od jakimś parametrów - np. z konfiga o stopień wyżej - tablica się zmieni a ty znowu będziesz cache'ował kilka czy kilkanaście obiektów :?:
hawk
A czemu nie? Jaka jest różnica (w sensie wydajności) pomiędzy parsowaniem XMLa do tablicy, a parsowaniem XMLa do skonfigurowanych obiektów?

Poza tym, nie wyobrażam sobie, żeby w środowisku produkcyjnym konfiguracja się co chwilę zmieniała...
NuLL
Cytat
Poza tym, nie wyobrażam sobie, żeby w środowisku produkcyjnym konfiguracja się co chwilę zmieniała...

Chodzi mi bardziej oto iż konfiguracja czegoś tam tongue.gif może być tworzona dynamicznie na podstawie dostarczonych danych.

Ale nie oto chodzi - z twojego poprzedniego posta wywniskowałem, że tworzysz różne obiekty potrzebne do wykonania jakieś akcji - natomiast ty mówiłeś o obiekcie konfigu - my bad winksmiley.jpg
hawk
Nie, nie, tworzę obiekty. Intercepting Filter. Jak mam parsować XML do tablicy, zapisywać tablicę, potem tworzyć te filtry, które na podstawie zawartości tablicy coś tam zrobią, to wolę zapisać do pliku gotowy do użycia filtr.

A jeżeli konfiguracja czegoś tam ma być tworzona dynamicznie, to i tak nie będziemy zapisywać tego w XML, prawda? Chociaż nie przychodzi mi do głowy zastosowanie tego.
Nievinny
To może powiedzmy co to konfiguracja? Bo, według mnie to podstawowe i naprawdę podstawowe dane dotyczące uruchomienia systemu, np informacje o tabeli, użytkownik i haśle w DB, domena i domyślna akcja. Tyle wystarczy, więc popierwam @hawka bo zamiast komplikować sobie życie i kod wczytujesz XML do obiektów i masz gotowe do uzycia obiekty, które cachujesz, potem tylko sprawdzasz czy konfig nie uległmodyfikacji (np za pomocą checksumy).
serafin
Jedyne co mi sie nasuwa - lol, rotfl, omg!

Przeciez XML jest po to by ulatwic komus z "zewnatrz" edycje konfigow, prawda?

Wiec zalozmy ze plik xml jest forma pierwotna, ktora nastepnie transformujemy do tablicy php, cachuj'emy i korzystamy z tablicy a nie z user-readable XML.

Wiec imho simplexml2array to bardzo dobry pomysl, o ile zawsze korzystac bedziemy z tablicy php a nie obiektow SimpleXML.

Takie moje zdanie (btw. korzystanie z obiektow wiaze sie z pewnym narzutem czasowym, wiec skoro mozna korzystac z o niebo szybszej tablicy to czemu nie?)
squid
@ hawk - szczerze mowiac jeszcze nie rozgryzlem zrodelek phiend2 ale pomysly sa calkiem intrygujace smile.gif
@ Nievinny - taka konfiguracja o jakiej ty mowisz moze sie zawrzec w kilku stalych ja potrzebuje znacznie potezniejszego narzedzia, trzymam w konfiguracji wszystkie akcje i modele zeby controler przed wywolaniem sprawdzil czy takie cos intnieje, trzymam oczekiwane wartosci wszystkich danych post i get zeby moc je zweryfikowac, trzymam cala mase innych konfiguracyjnych rzeczy jak pomyslne sortowanie, ile ma. moze byc sztuk jednego towaru w koszyku i wiele takich drobiazgow.

Nie wiem czy dobrze rozumiem ale zalozmy ze mam taka klase

  1. <?php
  2.  
  3. class basket 
  4. {
  5. // ogolnie jest to koszyk z zakupami
  6. ...
  7. public $maxQuantity;
  8. ...
  9.  
  10. }
  11. ?>


I powiedzmy ze wlasciwosc $maxQuantity chcem ustawic z konfiguracji, moze controler podczas wywyolania zapytania skro jest w stanie stwierdzic jakie obiekty beda potrzebne tworzy je ustawiajac odpowiednie wlasciwosci z konfiguracji nastepnie serializuje i zapisuje w pliku tak zeby nastepne wywolanie nie wiazalo sie z czytaniem XML i zeby dla nastepnego uzytkownika czy wywolania konfiguracja nie byla czytana. Po prostu zczytujemy serializowana skonfigurowana klase.

Herezje?
Nievinny
Herezje? -> niekoniecznie; To jest możliwe, ale jeżeli właściwość jest publiczna to załamanie oop (ale o tym nie będe psioczył). W każdym razie jaki jest sesn powiedzmy trzymania 30 klas w postaci zserializowanej i wczytywanie inaczej niż z bazowych plików? Nie będą one już potrzebne? Jeżeli konfiguracja zmienia się powiedzmy raz na miesiąc i masz uruchomiony tokenizer to można zrobić ustawienie wartości do stałych klasy (const) jako wartości i wczytywanie z pliku klasy. Jezeli nie to zrobić 1-2 klasy konfiguracyjne konfigurujące inne klasy.
squid
Cytat(Nievinny @ 2005-07-11 13:57:52)
Herezje? -> niekoniecznie; To jest możliwe, ale jeżeli właściwość jest publiczna to załamanie oop (ale o tym nie będe psioczył). W każdym razie jaki jest sesn powiedzmy trzymania 30 klas w postaci zserializowanej i wczytywanie inaczej niż z bazowych plików? Nie będą one już potrzebne? Jeżeli konfiguracja zmienia się powiedzmy raz na miesiąc i masz uruchomiony tokenizer to można zrobić ustawienie wartości do stałych klasy (const) jako wartości i wczytywanie z pliku klasy. Jezeli nie to zrobić 1-2 klasy konfiguracyjne konfigurujące inne klasy.

Jezeli chodzi o publiczne wlasciwosci to byl tylko przyklad ale przeciez tez sie przydaja.
A taka klasa konfiguracyjna jak wg Ciebie mialaby dzialac?
Vengeance
Ja robie to tak, iż za każdym razem wczytuje XML poprzez SimpleXML (jak ktoś chce to cache dorobić nie problem) i mam podstawowe metody do wyciągania danych: Config->GetParam(<xml-path>)

Potem, już w ciele aplikacji, np. podczas tworzenia obiektu Basket
wywołuje Basket->SetMaxQuantity(Config->GetParam('/app/basket/maxQuantity'));
DaNTe
A może ktoś mi powie jak sensownie wyszukiwać po takim XMLu:

<team>
<name>Diggers</name>
<members>
<member>Adrea</member>
<member>Joe</member>
</members>
<tool>hammer</tool>
<tool>nail</tool>
</team>
<team>
<name>Miners</name>
<members>
<member>Koel</member>
</members>
<tool>Lamp</tool>
</team>

I teraz interesuje mnie czy Joe pracuje jako Digger i jesli tak to jakich potrzebuje narzędzi.

Mnie do glowy przychodzą jedynie nieelastyczne partyzanki w stylu zmiany na tablice asocjacyjne (Miners=>Joe=>tool('hammer'.'nail'))

Bo foreachem z breakem tez za cholere nie wiem jak sie po tym poruszac sad.gif
serafin
Ja uzywam DomXML z php5 winksmiley.jpg
hawk
@dante: Jak wyszukiwać? Najprościej xpath. Jak chcesz tylko wyszukiwać po XMLu, to nie zamieniaj go na tablice/obiekty.
squid
Cytat(hawk @ 2005-07-15 21:01:41)
@dante: Jak wyszukiwać? Najprościej xpath. Jak chcesz tylko wyszukiwać po XMLu, to nie zamieniaj go na tablice/obiekty.

ale jak go nie zamienie na tablice to bede musal za kazdym razem kiedy wywoluje skrypt czytac xml'a. Poniewaz obiektu simpleXML nie da sie zserializowac to mozna zamienic go tylko na tablice (albo inny obiekt) ale jak juz mowilismy jest to spory narzut czasowy.

A mozna powiedzmy caly plik zczytac do zmiennej i zserializowac ja i potem ew. chodzic xPath po tym pliku zmiennek? czy taie rozwiazanie jest dobre?
Vengeance
A moze zrezygnowac z XML na rzecz kilku .ini ? ;p
Ociu
Ja zaczynam zabawe w mvc i mape pierwotnie miałem w xml, potem przeszła do pliku ini, aż w koncu zatrzymało się na talbicy pliku autoloadera :-)
Vengeance
To tak jakby cofnołeś się w rozwoju snitch.gif
Zazwyczaj wszyscy idą ścieżką php>txt>xml tongue.gif
squid
Pogubilem sie troche w roznych rozwiazaniach. Mam sobie jakis tam obiekt ktory czyta dwolny format pliku konfiguracyjnego po czym, no wlasnie co zrobic po zczytaniu takiego pliku.
1. Stworzyc tablice ze zmiennymi konfiguracyjnymi i serializowac ja miedzy wywolaniami?
2. Stworzyc obiekt ktory bedzie przetrzymywal cala konfiguracje we wlasciwosciach i udostepnial je przy pomocy metody/metod
3. Stworzyc obiekt ktory podczas wywolania akc ji bedzie ja konfigurowal np. tak ze przez okreslopna metoda w akcji ustawi jej wlasciwosci wykorzystywanie podczas pracy tej akcji
4. Jeszcze cos innego?

POMOCY!
Ociu
Vengeance: zawsze się wyróżniałem... winksmiley.jpg A co do wyboru, to wróciłem to pliku ini smile.gif
squid
Cytat(Ociu @ 2005-08-04 12:57:38)
Vengeance: zawsze się wyróżniałem... winksmiley.jpg A co do wyboru, to wróciłem to pliku ini smile.gif

wasze prywatne potyczki bardzo mi pomagaja w rozwiazaniu problemu ;p
Vengeance
@squid: Po pierwsze, jakie potyczki? Po drugie nie tylko twoje problemy są na forum... skoro nie otrzymałeś odpowiedzi to przypominanie się wiele nie da.
squid
Cytat(Vengeance @ 2005-08-08 13:30:11)
@squid: Po pierwsze, jakie potyczki? Po drugie nie tylko twoje problemy są na forum... skoro nie otrzymałeś odpowiedzi to przypominanie się wiele nie da.

inaczej to odbieram i nie oczekuje ze wszyscy zechca cos tu mi napisa bo ja chce ale skoro juz to wyjasnilismy to zrobilem test simpleXML kontra DOM.
Wiadomo obiektu simpleXML nie da sie zserializowac wiec trzeba go zamienic na tablice i poznie ew. obiekt. W moim przykladzie zamieniam na tablice.
Hawk twierdzi ze zabawa w zamieniania simpleXML na cokolwiek jest zbyt kosztowna.
oto plik testowy:
  1. <?php
  2. require_once 'Benchmark/Iterate.php';
  3. $benchmark = new Benchmark_Iterate;
  4. $file = "./xml/test.xml";
  5.  
  6. function simple_xml ($file)
  7. {
  8. $xmlObject = simplexml_load_file ( $file );
  9. $xmlArray = simplexml2array ($xmlObject);
  10. }
  11.  
  12. function simplexml2array($xml)
  13. {
  14. if (get_class($xml) == 'SimpleXMLElement')
  15. {
  16. $attributes = $xml->attributes();
  17. foreach($attributes as $k=>$v)
  18. {
  19. if ($v) $a[$k] = (string) $v;
  20. }
  21. $x = $xml;
  22. $xml = get_object_vars($xml);
  23. }
  24. if (is_array($xml))
  25. {
  26. // - poprawione - //
  27. if(count($xml) == 0)
  28. {
  29. if(count($a) <> 0)
  30. {
  31. return $a;
  32. }
  33. return (string) $x;
  34. }
  35. // - koniec poprawki - //
  36. foreach($xml as $key=>$value)
  37. {
  38. $r[$key] = simplexml2array($value);
  39. }
  40. if (isset($a))
  41. {
  42. $r['@'] = $a; // Attributes
  43. }
  44. return $r;
  45. }
  46. return (string) $xml;
  47. }
  48.  
  49.  
  50.  
  51. $benchmark->run(1000, 'simple_xml', $file);
  52. $result = $benchmark->get();
  53. echo '<pre>';
  54. //var_dump ( $result );
  55. echo '</pre>';
  56. unset ($result['iterations']);
  57. echo array_sum ($result).'<br />';
  58.  
  59.  
  60. function DOM ( $file )
  61. {
  62. $dom = new DOMDocument('1.0', 'iso-8859-1');
  63. $dom->load($file);
  64.  
  65. }
  66.  
  67. $benchmark->run(1000, 'DOM', $file);
  68. $result = $benchmark->get();
  69. unset ($result['iterations']);
  70. echo array_sum ($result).'<br />';
  71. ?>


na moim sprzecie odczytanie i zamana obiektu simpleXML na tablice zajmuje ok 0.65s a zabawa z DOM ok 1s. Wszytko to dla 1000 wywolan. Jaki wplyw na wynik ma sama zamiana simpleXML na tablice mozna zobaczyc komentujac linie:
  1. <?php
  2.  
  3. $xmlArray = simplexml2array ($xmlObject);
  4. ?>
w pierwszej f-cji
Nie jestem sepem od DOM'a ale jest jeden jako rozszerzenie i jeden wbudowany w jadro (tego uzylem), moze wiecie jaka jest roznica? jesli nie ma zbyt wielkiej to moze w phiend2 trzeba zamienic DOM na cos innego?

To wszytko dla przykladowego pliku:
  1. <?xml version="1.0" encoding="utf-8" ?>
  2.  
  3. <rss version="0.91">
  4.  
  5. <channel>
  6.  
  7.  <title>What's For Dinner</title>
  8.  
  9.  <link>http://menu.example.com/</link>
  10.  
  11.  <description>These are your choices of what to eat tonight.</description>
  12.  
  13.  <item>
  14.  
  15.   <title>Braised Sea Cucumber</title>
  16.  
  17.   <link>http://menu.example.com/dishes.php?dish=cuke</link>
  18.  
  19.   <description>Gentle flavors of the sea that nourish and refresh you.</description>
  20.  
  21.  </item>
  22.  
  23.  <item>
  24.  
  25.   <title>Baked Giblets with Salt</title>
  26.  
  27.   <link>http://menu.example.com/dishes.php?dish=giblets</link>
  28.  
  29.   <description>Rich giblet flavor infused with salt and spice.</description>
  30.  
  31.  </item>
  32.  
  33.  <item>
  34.  
  35.   <title>Abalone with Marrow and Duck Feet</title>
  36.  
  37.   <link>http://menu.example.com/dishes.php?dish=abalone</link>
  38.  
  39.   <description>There's no mistaking the special pleasure of abalone.</description>
  40.  
  41.  </item>
  42.  
  43. </channel>
  44.  
  45. </rss>
Vengeance
squid: istniejące funkcje xml2array nie pozwalają na używanie wielu możlwiości XML jak np argumenty.

Dla mnie też zrzucanie do arraya nie ma sensu. Już albo zrobić sobie gotowe do użycia obiekty (wygenerować odpowiednie pliki), lub pobierać przez xpath()
squid
Cytat(Vengeance @ 2005-08-08 18:28:22)
squid: istniejące funkcje xml2array nie pozwalają na używanie wielu możlwiości XML jak np argumenty.

Dla mnie też zrzucanie do arraya nie ma sensu. Już albo zrobić sobie gotowe do użycia obiekty (wygenerować odpowiednie pliki), lub pobierać przez xpath()

mowiac argumenty masz na imie atrybuty?? np:
  1. <znacznik atrybut="wartosc"></znacznik>


Oczywiscie chce miec obiekt z konfiguracja tak zebym na niej mogl operowac (na poczatek tylko czytac) ale tak czy siak zeby dalej uzywac tego co odczytam z pliku to uzywajac simpleXML musze to zrzucic do jakies tablicy ktora w rzeczywistosci bedzie chroniona wlasciwosci na ktorej bedzie operowal obiekt konfiguracji.

XPATH, jeszcze za malo wiem o tej technologi ale postaram sie to przetestowac pod wzgledem wydajnosci i powiadomie Was o wynikach

dzieki za uwagi
hawk
Przede wszystkim, nie twierdzę, że zamiana simplexml na tablice jest kosztowna. Po prostu w moim przypadku przejście z xml bezpośrednio na obiekty było krótsze (w znaczeniu linii kodu). A i już po zapisaniu wyniku np. do gotowego pliku php kod wykorzystujący obiekty jest prostszy niż kod pakujący tablice do obiektów.

Że DOM jest wolny, to wiadomo. To cena, którą się płaci za możliwość dowolnej edycji struktury XMLa. Ale ile razy będzie parsowany taki XML? Jeżeli to konfiguracja frameworka, to naprawdę bardzo rzadko, więc nie ma to znaczenia.

A ja się ostatnio zastanawiałem nad inną rzeczą. Czy da się uwolnić od ograniczenia, że dane wejściowe są w XML? Mamy jeszcze .ini, YAML, M3, php winksmiley.jpg ... Gdyby był format pośredni, to można tylko wymieniać "driver". Tylko że formatem pośrednim znowu byłyby tablice sadsmiley02.gif. A tablice do XML kiepsko pasują. Przykład:
  1. <items>
  2.  <item>foo</item>
  3.  <item>bar</item>
  4. </items>

Tak na oko, chciałbym w wyniku mieć:
  1. <?php
  2. $items = array(
  3. 'foo',
  4. 'bar',
  5. );
  6. ?>

... a nie ...
  1. <?php
  2. $items = array(
  3. 'item' => array(
  4. 'foo',
  5. 'bar',
  6. ),
  7. );
  8. ?>

Chyba że ja za bardzo kombinuję...
squid
DOM jest dobry ale to kombajn, czy trzeba zapuszczac kombajn do jednego klosa?
DOM daje duzo mozliwosci jest dopracowany bo w php juz istnieje jakis czas ale zajmuje duzo pamieci i nei ejst najszybszy.
Jest tez SAX ale nie za bardzo mi odpowiada, trzeba pisac jakies handlery itp.
SimpleXML bylby idealny gdyby nie to ze jest dosc niedopracowany. Wspomniany blad z serializacja sprawia ze trzeba kombinowac.
Mimo wszystko wole simpleXML bo do czytania konfiguracji powinien wystarczyc i nawet jakbym z panelu admina chcial cos napisac do pliku z configiem to tez moge.
Mialem porownac bardziej realistycznie wydajnosc SimpleXML i DOM i nawet Xpath ale sie nie da przynajmniej takim nakladem pracy jakim moge dysponowac.

To jest taki szkic klasy uzywajacej SimpleXML:
  1. <?php
  2. class Configuration
  3. {
  4. protected $configuration = array ();
  5. protected $cachedConfigurationFile = './cache/configuration.ctmp';
  6.  
  7. public function __construct ()
  8. {  
  9. if ( isset ( $_SESSION['configuration'] ) )
  10. {
  11. $this->configuration = $_SESSION['configuration'];
  12. } 
  13. else if ( file_exists ( $this->cachedConfigurationFile ) )
  14. {
  15. $cachedConfigurationString = file_get_contents ( $this->cachedConfigurationFile );
  16. $this->configuration = unserialize ( $cachedConfigurationString );
  17. $_SESSION['configuration'] = $this->configuration;
  18. }
  19. else
  20. {
  21. $simpleXmlObject = simplexml_load_file('./xml/test.xml');
  22. $this->configuration = $this->simplexml2array ( $simpleXmlObject );
  23. file_put_contents ( $this->cachedConfigurationFile, serialize ( $this->configuration ) );
  24. $_SESSION['configuration'] = $this->configuration;
  25. }
  26. return true;
  27. }
  28.  
  29. public function getConfiguration ( $node )
  30. {
  31. return $this->configuration[$node];
  32. }
  33.  
  34. protected function simplexml2array ( $xml )
  35. {
  36. if (get_class($xml) == 'SimpleXMLElement')
  37. {
  38. $attributes = $xml->attributes();
  39. foreach($attributes as $k=>$v)
  40. {
  41. if ($v) $a[$k] = (string) $v;
  42. }
  43. $x = $xml;
  44. $xml = get_object_vars($xml);
  45. }
  46. if (is_array($xml))
  47. {
  48. // - poprawione - //
  49. if(count($xml) == 0)
  50. {
  51. if(count($a) <> 0)
  52. {
  53. return $a;
  54. }
  55. return (string) $x;
  56. }
  57. // - koniec poprawki - //
  58. foreach($xml as $key=>$value)
  59. {
  60. $r[$key] = $this->simplexml2array($value);
  61. }
  62. if (isset($a))
  63. {
  64. $r['@'] = $a; // Attributes
  65. }
  66. return $r;
  67. }
  68. return (string) $xml;
  69. }
  70.  
  71. }
  72. ?>

Zasadnicza wada jest to ze ciezko przez metode uzyskac dostpe do dowolnego poziomu zagniezdzenia tablicy dlatego na razie mozna pobrac tylko jeden z korzeni.
Macie jakis pomysl co z tym zrobic?
Vengeance
Cytat(squid @ 2005-08-08 20:46:07)
ale tak czy siak zeby dalej uzywac tego co odczytam z pliku to uzywajac simpleXML musze to zrzucic do jakies tablicy

Nie prawda. Ja w poprzedniej wersji swojego Framework robiłem po prostu:

Config::GetParam('/framework/db/user');

Gdzie GetParam() przerabial to na zapytanie xpath. zainteresuj sie nim bo na prawde pomaga. A mozna przy jego użyciu cuda robić.
NuLL
Cuda - ciekawe jak z szybkością jeśli trzeba wczytywać cały dokument :?: snitch.gif
Vengeance
Już nie cuda... bo stwierdziłem że XML jest zbędny i z niego nie korzystam. W ogóle staram się pisać tak by unikać konfiguracji.

No ale kolega chciał sposobów to podałem stare :]
squid
@NuLL z moich testow wynika ze wszystko jest szybsze od DOM, nie testowalem zajetosci pamieci ale DOM pewnie tez zajmowalby najwiecej.

@Vengeance nie uparlem sie na XML, testuje tez inne rozwiazania ale najwiecej problemu sprawia mi wlasnie XML stad ten temat.
Pliki ini oferuja zbyt mala fukcjonalnosc, przeszkadza mi glownie brak zagniezdzen ktore z latwoscia uzyskam przez xml np:
  1. <znacznik_1>
  2.  <znacznik_2>
  3.    <znacznik_3>bla</znacznik_3>
  4.  </znacznik_2>
  5.  <znacznik_4> bla bla </znacznik_4>
  6. </znacznik_1>


pliki ini sa dobre do trzymania konfiguracji typu ile mam wyswietlic rekordow na stronie itp. ale gdybym chcial trzymac mape plikow lub cos bardziej skomplikowanego to sie nie sprawdzaja choc nie wykluczylem do konca plikow ini. Jesli nie bede zadowolony z obslugi XML przez php to pewnie wybiore te rozwiazanie.

Trzymanie konfiguracji w stalych jest jeszcze bardziej ograniczone.
Obecnie konfiguracje trzymam w statycznej wlasciwosci kontrolera ale malo eleganckie to jest.
Mozna trzymac tez w bazie danych, ja w ten sposob przetrzymuje mape akcji, w ten sposob latwo sprzegam to z systemem uprawnien do wykonania akcji przez uzytkownika.

ale Vengeance jesli potrafisz pisac kod nie wymagajacy konfiguracji to albo lubisz pisac wiecej kodu niz potrzeba albo jestes zaje...genialny.
matid
Cytat(squid @ 2005-08-09 21:45:42)
ale Vengeance esli potrafisz pisac kod nie wymagajacy konfiguracji to albo lubisz pisac wiecej kodu niz potrzeba alebo jest zaje...genialny.

Kilka algorytmów konfigurujących skrypt na podstawie działań użytkownika/administratora i jest git ;P

U mnie konfig to dość rozbudowany moduł, na razie 13 klas i do tego jeszcze kilka interface'ów. Jak na razie mam:
ConfigCache, ConfigCacheCreator, ConfigCacheGenerator, ConfigCacheLoader, ConfigCacheWriter, ConfigContainer, ConfigEntry, ConfigSection, INIConfigParser, PHPConfigParser, SerializedConfigCacheLoader, SerializedConfigCacheWriter, XMLConfigParser.

A używanie samego configu wygląda tak:
  1. <?php
  2.  
  3. class OpenConfig
  4. {
  5. private static $OpenConfig;
  6.  
  7. private static $aConfigArray;
  8.  
  9. public static function getConfig( String $FilePathname )
  10. {
  11. if( isset( self::$aConfigArray[ $FilePathname->toString() ] ) )
  12. {
  13. return self::$aConfigArray[ $FilePathname->toString() ];
  14. }
  15. else
  16. {
  17. return self::loadConfig( $FilePathname );
  18. }
  19. }
  20.  
  21. public static function addConfig( String $FilePathname, ConfigContainer $Config )
  22. {
  23. self::$aConfigArray[ $FilePathname->toString() ] = $Config;
  24. }
  25.  
  26. public static function loadConfig( String $FilePathname )
  27. {
  28. if( file_exists( $FilePathname->toString() ) )
  29. {
  30. if( !file_exists( OF_CACHE_DIR . md5( $FilePathname->toString() ) . '.php' ) || ( filemtime( $FilePathname->toString() ) > filemtime( OF_CACHE_DIR . md5( $FilePathname->toString() ) . '.php' ) ) )
  31. {
  32. $ConfigCacheGenerator = new ConfigCacheGenerator;
  33.  
  34. $FileExtension = clone $FilePathname;
  35. $FileExtension->replace( new String( '/(.*?).([^.]+)?$/i' ), new String( '2' ) );
  36. $FileExtension->toLowerCase();
  37.  
  38. switch( $FileExtension->toString() )
  39. {
  40. case 'xml':
  41. $ConfigParser = new XMLConfigParser;
  42. break;
  43. case 'php':
  44. $ConfigParser = new PHPConfigParser;
  45. break;
  46. case 'ini':
  47. $ConfigParser = new INIConfigParser;
  48. break;  
  49. }
  50.  
  51. $Config = $ConfigParser->parseFile( $FilePathname );
  52. $ConfigCacheGenerator->setProvider( $Config );
  53.  
  54. $ConfigCacheCreator = new ConfigCacheCreator( $Config );
  55. $ConfigCacheGenerator->setCreator( $ConfigCacheCreator );
  56.  
  57. $ConfigCacheWriter = new SerializedConfigCacheWriter( new String( OF_CACHE_DIR . md5( $FilePathname->toString() ) . '.php' ) );
  58. $ConfigCacheGenerator->setWriter( $ConfigCacheWriter );
  59.  
  60. $ConfigCacheGenerator->generateCache();
  61. }
  62. else
  63. {
  64. $ConfigCacheLoader = new SerializedConfigCacheLoader;
  65. $Config = $ConfigCacheLoader->loadCache( new String( OF_CACHE_DIR . md5( $FilePathname->toString() ) . '.php' ) );
  66. }
  67.  
  68. self::addConfig( $FilePathname, $Config );
  69.  
  70. return $Config;
  71. }
  72. else
  73. {
  74. throw new FileNotExistsException( 'Config file (' . $FilePathname->toString() . ') does not exist' );
  75. }
  76. }
  77. }
  78.  
  79. ?>


A to przykład pobierania danych z konfiguracji:
  1. <?php
  2. $ControllerConfig = OpenConfig::getConfig( new String( 'config.xml' ) )->getSection( new String( 'Controller' ) );
  3. $ModuleName = $ControllerConfig->getEntry( new String( 'Error404Module' ) )->getValue();
  4. $ActionName = $ControllerConfig->getEntry( new String( 'Error404Action' ) )->getValue();
  5. ?>


Na razie dość niewygodne, bo przy każdym odwołaniu do konfiguracji z innego miejsca aplikacji trzeba podać plik z jakiego się chce skorzystać, ale to tylko dla potrzeb mojego testowania (tak wygodniej mi się pisze ;P)
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.