Tworze prosty szkielet aplikacji trojwarstwowej i chcialem Was zapytac juz na wstepie (i troche wykorzystac Wasze obycie z takimi schematami aplikacji), czy takie rozwiazanie bedzie mialo racje bytu, czy rozgrzebie jakikolwiek projekt i okaze sie w polowie, ze wszystko trzeba gruntowanie przebudowywac.
1. Sprawa kontrolera glownego, w mojej aplikacji jest to klasa MyApplication dziedzicaca po klasie Application oraz implementujaca interfejs Runnable. Klasa Application wywoluje metode init() na klasie potomka no i wymusza jej istnienie. Teraz pytanie, czy samo rozdzielenie takiego szkieletu na metode run() i init() wystarczy. Narazie nie widze wiekszych problemow, wszystko co trzeba zainicjowac na poczatku tworze w init() np. Registry, View itd.
2. Sprawa widoku. Moim zdaniem jezeli widok tworze w init() i wykonuje kolejne akcje to do momentu natrafienia na akcje o typie "widok" nie wiem na jakim widoku dokladnie bede pracowal. Stworzylem obiekt View, ktory przyjmuje dane i je udsotepnia. Obiekt widoku przekazuje do kontrolerow poszczegolnych akcji. Na samym koncu ustawiam odpowiedni obiekt renderuacy i wyswietlam widok, przekazujac do obiektu renderujacego pobrane wczesniej dane. Wyglada to mniej wiecej tak:
<?php class View { private $renderer; private $params; public function set($key, $value){} public function get($key, $value){} public function __set($key, $value){} public function __get($key, $value){} public function setRenderer(Renderer $renderer){} public function setTemplate($template){ $this->renderer->setTemplate($template); } public function render(){ $this->renderer->render(); } } abstract class Renderer { private $template; public function setTemplate(){} public function getTemplate(){} abstract public function render(); } class Renderer_Smarty extends Renderer { public function render(){ // pobieramy szablon $template->getTemplate(); // iniciujemy smarty // display(); } } class MyApplication extends Application implements Runnable { private $view; public function init(){ $this->view = new View; } public function run(){ $this->view->imie = 'Jan';// tak samo beda mialy dostep do widoku metody kontrolerow akcji $this->view->setRenderer(new Renderer_Smarty); $this->view->setTemplate('index.tpl'); $this->view->render(); } } ?>
Chodzilo mi glownie o to, ze raz akcja moze wyswietlac dane przez Smarty innym razem bede chcial te same dane pobract przez JSON. Wiec mysle, ze takie rozwiazanie sie sprawdzi, chociaz trudno mi dokladnie powiedziec.
3. Sprawa to kontroler akcji. Zbior akcji dot. danego zagadnienia bede ubieral w kontroler akcji np. News_Controller, Guestbook_Controller itd. Czy poszczegolne metody w kontrolerze akcji powinny zwracac do kontrolera glownego jakies dane np. obiekt Response przekierowujacy kontroler na dana akcje. Czy metody kontrolera akacji powinny "znac" nazwy kontrolerow innych akcji, ich metody itd. Czy powinno to byc konfigurowalne na poziomie kontrolera. Czyli np. kontroler dostaje zadanie wykonania akcji ShowNews akcja sie wykonuje i z konfigu kontroler sie dowiaduje ze ma wywolac akcje CountVisit w kontrolerze Statistics? Czy te metody powinny miec jakis wplyw na sterowanie aplikacja w tym sensie, ze klasa abstrakcyjna kontrolera akcji mialaby zaimplementowany mechanizm przenoszenia forward(), wysylania naglowkow header() itd.? Czy znow dostep do tego ma tylko kontroler glowny?
4. Czy metody kontrolerow akcji "znaja" nazwy parametrow, ktore dostana z zadania. Tzn. zakladamy, ze router przeparsuje mi URL i dostapne z tego: id(32), name(root), czy akcje moga odwolywac sie np. do obiektu Request->get('id'), Request->get('name') itd.? Czy powinny odwolywac sie do tego np. przez Request->get(0)?
5. Stworzylem sobie zgodnie ze wzorcem Registry klase, ktora udostepnia statyczne metody set, get itd. Czy to jest dobry sposob na przechowywanie danych np. o uchwytach do PDO, configu itd.? Czy dobrym pomyslem, jest tworzyc w takim rejestrze blokade, ze jezeli obiekt o podanym kluczu istnieje to wyrzucac wyjatek i tworzyc instancje obiektu polaczenia z baza danych w init(), czy np. pozwolic metodom kotrolera akcji na tworzenie polaczen wtedy kiedy bedzie taka potrzeba (przy czym jedna nie bedzie wiedziala o tym, czy poprzednia przypadkiem nie rejestrowala juz polaczenia z baza)?
6. Router - czy dobrze rozumiem, ze router ma mi parsowac adres url i wyciagac z niego nazwe kontrolera i akcji oraz skladac url w druga strone? Czy jest to po to, abym np. w pliku szablonu mogl sie odwolac w ten sposob w celu wygenerowania linku: $router->getUrl($mapper->getRule('news'), array('id' => 32, 'name' => 'Wzorce_projektowe'))? Czy widok ma dostep do routera i moze sobie skladac url'e, czy kontroler ma dostarczyc te dane do widoku?
7. Lancuchy akcji. Widze, ze sporo rozwiazan opiera sie na XML'u. Czy konfiguracja akcji nie zamula w ten sposob calej aplikacji? W jaki sposob ewentualnie moge to jakos zacacheowac?
8. Docelowo w tym schemacie bede chcial korzystac z cache'u. Czy dobrym rozwiazaniem bedzie, aby kontroler akcji dopiero sprawdzal, czy dane istnieja w cache i jezeli nie to dopiero pobieral je pracujac na modelu. Czy macie jakies inne sprawdzone rozwiazania? Jak to wyglada w praktyce? Czy do cachu mam tworzyc jakis obiekt o wspolnym interfejsie, ze w razie czego podmienie tylko obiekt cache'ujacy, czy mam pracowac w kontrolerach bezposrednio na funkcjach jakis memcache itd.?
9. Obiekt kontekstu - czy jest to poprawne, zeby do obiektu kontekstu mialy dostep wszystkie kontrolery akcji. Tzn. w przypadku wykonywania lancucha akcji jedna akcja zapisuje do kontekstu jakies dane, nastepna te dane pobiera. Czy to sie nie gryzie? Moze te akcje nie powinny nic o sobie wiedziec? Jak uwazacie? Jak w takim razie zapewnic komunikacje i dostarczyc dane przetworzone przez jedna akcje do drugiej?
10. Sprawa autoryzacji - czy jezeli bede wymagal autoryzacji do wykonania jeden akcji, to gdzie mam ja sprawdzic i skad mam wiedziec czy ja sprawdzac. Zakladam, ze sprawdzam to w kontrolerze. Czy podobnie jak przy mapowaniu urli mam miec konfig i liste ról jakie musi miec uzytkownik, wraz z nazwa sterownika autoryzacji i ladowac je w kontrolerze? Co jezeli, kazda akcja wymaga innych rol i np. w polowie wykonywania lancucha akcji okaze sie, ze uzytkownik nie ma uprawnien do wykonania czesci akcji? Jak wtedy cofnac wprowadzone dane. A moze od razu sprawdzac, czy uzytkownik bedzie mogl wykonac wszystkie akcje i dopiero pozniej je uruchamiac?
I to chyba narazie tyle pytan, moze jeszcze cos mi sie przypomni. Bede wdzieczny za odpowiedzi.