mam własny skrypt zintegrowany z forum na phpBB3, postanowiłem przerobić go aby był bardziej przenośny i mógł posłużyć do tworzenia innych serwisów dopiętych do for tego typu.
Wszystko było na funkcjach i strukturalnie, postanowiłem zamknąć ile się da w OOP, przez przypadek wyszło że warto od razu wszystko odseparować.
Skrypt ma przyjazne adresy, lecz nie mam żadnego routera, bo faktycznie zajmuje się tym .htaccess. Nie mam zamiaru puszczać wszystkich żądań (np. takich, które zwracają 404) na jeden plik. Są określone moduły i nie ma problemu aby wypisać je w htaccesie, wszystkie wymienione będą jednak iść przez główny plik.
Wygląda on obecnie tak:
require_once 'core.php'; $module = request_var('module', ''); { $module = 'news'; } $view = loader::view($modules[$module]['view']); $view->model = loader::model($modules[$module]['model']); $view->model->db = $db; // obsluga bazy danych z phpbb3 $view->urls = new urls(true); // Osobna klasa sluzaca do budowy linkow przyjaznych lub zwyklych include DIR_MODULES . $module . '.php';
W pliku core.php są wykonywane takie operacje:
- includowanie głównych plików phpBB3
- start sesji (obiekt $user)
- dołączenie podstawowych stałych i klas
Jest to pierwsza moja zabawa w OOP+MVC i to chyba niestety widać.
Tworzony widok rozszerza klasę bazową, podobnie jest z modelem (klasy te posiadają metody, które są potrzebne we wszystkich modułach).
Sięgnąłem do odpowiedniej lektury i wynika z niej, że to widok ma odwoływać się do modelu. Uznałem więc, że najlepiej będzie zrobić właśnie tak - obiekt modelu jako część widoku.
Includowany na sam koniec moduł można by uznać za "pseudo-kontrolery", które mają np. taką zawartość:
$id = request_var('id', 0); if (!$id) { $view->urls->zeroDuplicate('index'); $countNews = $view->model->countNews(); $news = $view->model->getNewsByPage(); while ($row = $db->sql_fetchrow($news)) //#1 { $view->renderNews($row); } $db->sql_freeresult($news); $view->urls->generatePagination($page, $config['portal_news_display'], $countNews, 3, '', 'index'); } else { $news = $view->model->getNewsById($id); $view->urls->zeroDuplicate('news', $news); $view->model->updateNewsReadsById($id); $view->renderNews($news); } $view->renderPage();
Jak widać, tak naprawdę w nich z modelu do widoku trafiają dane, które są potrzebne. Wg. tego co czytałem, kontroler nie powinien zachowywać się jako taki pośrednik, więc coś tu nie gra. Poza tym fragment który zaznaczyłem jako #1 - czy to ma sens leżeć w takim miejscu? Nawet gdyby to było w widoku, jakoś nie pasuje. Wydaje mi się, że powinienem poprzez model zwrócić tutaj gotową tablicę z danymi a nie uchwyt do wyniku zapytania, no ale pewności nie mam.
Kolejna rzecz, w bazowej klasie modelu mam metodę getPanels, która ma za zadanie pobrać zawartość sidebara na stronie na potrzeby metody renderPage klasy bazowej widoku. Najlepiej aby pobrane dane od razu zostały zawartością widoku. Niestety przy takiej konstrukcji dostęp do jego właściwości mam dopiero po użyciu słowa kluczowego global, a to już jest chyba zupełnie bez sensu. Nie mam natomiast pojęcia jak metoda modelu mogłaby się odwołać do właściwości widoku (o ile to nie jest równie bez sensu, bo chyba powinien zwracać wyniki zamiast modyfikować widok, z tym że zastanawiam się nad tym po co 2 razy te same dane trzymać). Tak samo wygląda zresztą sprawa z obiektami które daje mi do dyspozycji phpBB3 - muszę używać global. No chyba że by je przypisać do tych moich obiektów, bo o ile dobrze rozumiem, bez użycia słowa clone nie będę tutaj niczego marnotrawił (tak z głównym pliku wygląda sprawa z $db).
Nie wiem również, czy zamykać i to i to w obiekcie kontrolera (tworzony z modułu + bazowy) czyli np.:
$controller->view = loader::view($modules[$module]['view']); $controller->model = loader::model($modules[$module]['model']);
Z tym, że jeżeli przeniosę zapytania z modelu do widoków, to albo używam global, albo będą one wyglądać raczej tak:
$news = parent::model->getNewsById($id);
Czyli znowu kontroler robi się pośrednikiem pomiędzy widokiem a modelem...