poniedziałek, 4 września 2006

Z persystencją rozterki

Mój frejmłork webowy, zastosowany w pdaclub działa sposób nieco odmienny od MVC, ale gdyby się tam spróbować tej metodyki doszukać, to pewnie by się dało. Nie mam jednak jednego, wspólnego kontrolera frontowego. Różnymi funkcjami frameworka zajmują się różne skrypty, odseparowałem do osobnego katalogu skrypty akcji typu cynk, kontakt, wysyłanie komentarza.

Konsola administracyjna z kolei to nieco inny twór - te kwestie rozwiązuje na swój sposób, chyba bardziej zbliżony do MVC, gdyż wszystkim zajmuje się jeden skrypt, który zależnie od modułu i akcji wywołuje odpowiedzialne za nie skrypty, wykorzystując też podane parametry.

Wszędzie mam przynajmniej dobrą separację logiki od prezentacji, jednak dopiero porządnie jest to wykonane w nowej wersji Content Managera, który zadebiutuje najpierw jako intranet Urzędu Gminy Granowo, później rozbuduję o stronę internetową dla interesantów, która pozwoli załatwiać różnorakie sprawy urzędowe, sprawdzać ich stan, poczytać najnowsze wpisy do BIPu, jak i ponarzekać na gminę na forum.

Otóż kwestia samej prezentacji jest rozwiązana na zasadzie javowych resourców. Mam osobne pliczki językowe, które zawierają klucze i wartości różnych elementów interfejsu użytkownika. W szablonach stron wywołuję je tagami a'la {@zmienna}, gdzie owa zmienna jest wyszukiwana w zasobach i wybierana z pliku odpowiedniego dla aktualnego wybranego w przeglądarce. Jeśli chodzi o kwestię kontrolera i akcji, nadal występują różne skrypty dla różnych stron, jest jeden skrypt zajmujący się wywoływaniem odpowiednich metod modyfikujących informacje w portalu. Ponieważ zazwyczaj takie informacje modyfikuje się przez POST lub GET, zestaw tych klas to form-processors. Każda akcja obsługiwana jest przez osobny skrypcik, rozszerzający podstawową klasę, zawierającą metody odbierania z formularza/urla informacje, których się skrypt spodziewa, oczyszczenia ich z niebezpiecznych treści (XSS), udostępniającą też możliwość stworzenia redirecta http w razie potrzeby (akcja wymaga zalogowania lub wyższych uprawnień). Całość napisana jest w pełni obiektowo, choć muszę jeszcze wszystko dostosować do obiektowości PHP5, gdzie widać już oznaki cywilizacji.

Widok, kontroler – ok. A co z modelem? A tutaj są na razie dwie, właściwie trzy warstwy. Pierwsza to konkretne funkcje obsługi baz danych w PHP. Druga to warstwa abstrakcji - wspólny interfejs dla poszczególnych baz danych. Klasy dają możliwość zabezpieczania zapytań przez stosowne dla danej bazy ocytowywanie (quotowanie ;) ) wartości, dobierają też do zapytań ograniczanych albo LIMIT, albo TOP, zależnie czy to baza ANSI, czy MS. Nie wiem czy jednak pomysłu Microsoftu nie zbojkotować i zupełnie porzucić obsługe SQL Servera. Bo niby jak wygodnie wybrać z bazy dane stronicowane, np. drugie 20 najnowszych newsów? A jeśli chcę 20 od końca wybrać? A jak takie coś dla tabel łączonych zrobić? W MySQL czy od niedawna w PostgreSQL to jest prawie zawsze po prostu tak:

SELECT

 * FROM news ORDER BY date DESC LIMIT 10 OFFSET 10

Aż boję się próbować wymyślić, jak to zrobić w bazach bardziej "czystych", zgodnych z ANSI SQL, szczególnie z joinami. Może ktoś ma pomysły? Brzydactw typu zagnieżdżone SELECTy w zagnieżdżonych SELECTach nie akceptuję. ;)

Trzecia warstwa to coś a'la DAO. Są obiekty reprezentujące odpowiednie tabele w bazie i obiekty zajmujące się manipulacją na bazie za ich pomocą. Obawiałem się tutaj pewnego problemu od początku, ale chciałem sprawdzić, czy może da się to rozwiązać jakoś cywilizowanie. Co z joinami? Co jeśli dane o użytkowniku w systemie mam podzielonego między różne tabele, zawierające różne szczegóły? W jednej te podstawowe, jak login, data rejestracji, hasło, email. W drugiej szczegóły, jak nazwisko, data urodzenia, płeć. W trzeciej dane obywatela, tj. miejsce urodzenia, pesel, adres pocztowy, adres zameldowania stałego, tymczasowego, a w innej tabeli dane pracownika urzędu - biuro, telefon, stanowisko, fotka, wymiary (no, tu się zapędziłem). Do tego tabela z różnego typu własnościami uzytkownika - strona WWW, dodatkowe adresy email, komunikatory, preferencje w portalu, forum, połączona ze słownikiem wiele-do-wielu (można mieć np. kilka komunikatorów). I co teraz? Otóż to.

Postanowiłem zmienić nieco podejście i uczynić dla takiego zestawu tabel jeden obiekt, reprezentujący użytkownika. Zawierałby on dane na temat tabel "uczestniczących", byłby świadomy takich zagadnień jak klucze obce, klucze główne, a pobieranie informacji by polegało na deklarowaniu, które pola zechcę otrzymać i w zależności od tego generowałby odpowiednie zapytanie, razem z tworzeniem joinów i uwzględnianiem istnienia wielokolumnowych kluczy głównych. Do tego dochodziłaby możliwość keszowania słowników w pamięci lub w plikach na dysku, co by pozwoliło nieco zapytania odchudzić w czasie pracy systemu. Taka klasa zawierałaby zatem także informacje, która tabela to słownik, czy ów słownik może być przechowywany w pamięci podręcznej. Zbędne by było sprawdzanie w bazie daty modyfikacji słownika, bo już sama modyfikacja by przechodziła przez klasę. Co na to jury?

Brak komentarzy:

Prześlij komentarz