Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [MVC] Rozne kontrolery i drobne zmiany w widoku.
Forum PHP.pl > Forum > PHP > Pro > Archiwum Pro
thornag
Witam...

Zastanawiam sie ostatnio i wymyslic nie moge jak zrealizowac dzialanie takie jak to.

Kontroler uruchamia akcje index ta ustawia widok no i mamy strone glowa. Ten sam kontroler pewnie bedzie sprawowal kontrole nad akcjami typu pokaz liste newsow, pokaz caly news itp. Jednak na co zrzucic odpowiedzialnosc na male zmiany wyswietlania na stronie glownej. Powiedzmy ze gdzies w lewym panelu strony (przyjmujac uklad logo, lewy panel, czesc glowna) mamy liste jakis kategori. Po kliknieciu w liste ta lista zamienia sie w spis rzeczy w kategori.
Efekt tego taki ze cala strona pozostaje bez zmian, zmienia sie tylko ten jeden fragment.

Czy pisac akcje dla takiego czegos i uruchamiac ja przez glowny kontroler ? No raczej nie, mozna by napisac taka akcje ktora by poprosila model o dane, ustawila odpowiedni widok, OK. No ale co z widokiem ? Trzeba by bylo zrobic osobny template w ktorym rozni sie tylko ten jeden element ? Wedlug mnie bezsensu, bo chcialbym aby czesc glowna niezaleznie od tego gdzie sie uzytkownik znajduje pozostala taka sama. Nie bede przeciez robil dodatkowych templatow dla kazdego instniejacego templatu tylko po to by zmienic jeden blok.

Spodziewam sie ze z pomoca przychodzi tutaj BlockController FrontController .

Przyznam szczerze nie bardzo potrafie sobie wyobrazic jak to wszystko ma dzialac na dwoch kontrolerach. Jak wy rozwiazujecie takie wyswietlania ?
bim2
Ja mam coś takiego. Mam setAll('akcja', 'metoda'); i dajesz np setAll('forum $_GET['metoda']); i daj ta osobna akcje. Nie rozumiem Cię z tym templatem. Jak osobny? Ja bym do listy kategorii zrobił osobny i wywołał go w templatce. Pewnie nie zrozumiałeś. Powiedzmy mam blok menu. Jak go wywołujesz? No własnie. Wywołaj tą liste tak samo. Mi setAll() zwraca to co zwróciła akcja, a kacja to co widok. Więc mam $menu = setAction('menu') (to jest jak setAll ale zmienia tylko akcję)

Mam nadzieję że coś poradziłem smile.gif
thornag
Cytat(bim2 @ 28.08.2006, 10:22 ) *
Ja mam coś takiego. Mam setAll('akcja', 'metoda'); i dajesz np setAll('forum $_GET['metoda']); i daj ta osobna akcje. Nie rozumiem Cię z tym templatem. Jak osobny? Ja bym do listy kategorii zrobił osobny i wywołał go w templatce. Pewnie nie zrozumiałeś. Powiedzmy mam blok menu. Jak go wywołujesz? No własnie. Wywołaj tą liste tak samo. Mi setAll() zwraca to co zwróciła akcja, a kacja to co widok. Więc mam $menu = setAction('menu') (to jest jak setAll ale zmienia tylko akcję)

Mam nadzieję że coś poradziłem smile.gif

Niebardzo poradziles, ja moze poradze. Zanim przycisniesz "wyslij" przeczytaj swojego posta dwa razy, sformatuj go jakos, i zastanow sie czy to ma sens, bo ja takowego nie potrafiue odnalezdc tak tam napackales. Jakokolwiek dzieki za dobre checi.
bim2
Tak myślałem laugh.gif No dobra, pisze od nowa. Powiedzmy że bloki menu pobierasz z bazy i je evalujesz. Ja tak mam. I w bazie trzymam.
  1. <?
  2. $ctrlert = Controller::getInstance();
  3. $list = (!empty($_GET['zmiana_listy'])) ? $_GET['zmiana_listy'] : 'list_kategories';
  4. $ctrlert->setAll('index', $list);
  5. ?>

u mnie SetAction poprostu wywołuje akcję Index i metode $list smile.gif I kiedy klikniesz w link kategorii to wysyłasz zmiana_listy=list_news&id_listy=1 winksmiley.jpg Żeby nie kolidowało się to np. z newsami na stronie głownej, to nesyw wywołuje
$view = (!empty($_GEt['view'])) ? $_GET['view'] : 'defaults';
setAction($view);

Mam nadzieję że ten post coś Ci pomoże? Jak nie zrozumiałes może lepiej będzie pogadać przez skypa? biggrin.gif

Pozdrawia Bim.
Denver
Tym, czy wyświetlić listę kategorii, czy spis podkategorii, powinien się zajmować - moim zdaniem - sam szablon. Ja obecnie korzystam z OPT i w takim przypadku, jak twój, nie miałbym żadnego problemu. Lista kategorii to jakaśtam tablica przekazana szablonowi. Szablon sprawdza, czy zostały przekazane też zagnieżdżone tablice (które reprezentują podkategorie), i jeśli tak, to je wyświetla.

Podsumowując: akcje odpowiedzialne za pobieranie kategorii z np. bazy tworzą odpowiednią strukturę tablic i przekazują ją do szablonu. Szablon sam odpowiada za wykrycie, czy zostały mu przekazane także podkategorie, i je odpowiednio wyświetla.
bim2
Też dobro, ale ja mam osobną templatke i wywołuje inny model poprostu smile.gif
thornag
@bim2 Nie podoba mi sie trzymanie logiki w bazie danych tak zeby pozniej wyswietlac to uzywajac eval()

@Denver - to rozwiazanie juz mi bardziej pasuje, jednak znow razi mnie tylko to ze w szablonie zaszywam jakas logike smile.gif Przymysle bo poki co bardziej sensowne niz te bima

Pozdrawiam
bim2
@thornag ja dąłme przykład :| Nie musisz trzymac tego w bazie. Mozna to wywołać wszędzie. A jeszcze jak dasz return to dasz $list = setAll('index', 'list_news'); $tpl->setVar('list', $list); Rozumiesz? Mi to działa ładnie smile.gif
thornag
@bim2 Zrozumialem Twoje rozwiazanie spokojnie, napisalem dlaczego mi sie nie podoba i dlaczego nie zastosuje, nie muszisz odpowiadac trzy razy piszac to samo smile.gif

Ja jedna dalej czekam na jakies dalesze sugestie. Chyba wezme przyklad z kolegi Javowca i uruchomie drugi kontroler a moze nawet trzeci i czwarty tongue.gif Tylko z tym drugim kontrolerem to troche tez mi sie to nie podoba smile.gif

Zalozmy ze mam ten nieszczescliwy FrontController i BlockController (o ile wogole dobrze pojmuje abydwa stwierdzenia tongue.gif). FrontController zajmuje sie czescia glowna i na nim spoczywa odpowiedzialnosc za lwia czesc aplikacji. I teraz BlocController. Myslalem zeby jesli trzeba przekazac mu odpowiednia uzywajac innej nazwy zmiennej w URLu a stara akcjeglownego kontrollera pamietac w sesji. W trakcie dzialania FrontControllera ustawia on akcje taka sama jak poprzednio (biorac jej nazwe z sesji) pozniej inicjalizuje mniejszy kontroler. Ten mniejszy juz sobie sam radzi ustawia, w swoim zakresie kontaktuje sie z modelem ustawia szablon i dane dla bloku, przekazuje to do glownego widoku no i wio Display().

Co myslicie o takim rozwiazaniu ?
Denver
Nie do końca rozumiem do czego Ci inne kontrolery, i po co chcesz do wyświetlania zwykłych kategorii i podkategorii zaprzęgać sesje. Ja nadal twierdzę, że część logiki można zrzucić na szablony - ale tylko tą najprostszą.

Jeśli znasz wzorzec MVC i chcesz się do niego stosować to pamiętaj, że w kontrolerze nie powinien być generowany żaden kod HTML, w modelu też. Pętla {for} czy {foreach} stosowana w szablonie nie powinna być problematyczna, a niezwykle ułatwia pracę, np. w połączeniu z obiektami.
bim2
Dobra jak popierasz Denvera to trochę rozwine jeog myśl. Ja bym zrobił to tak. Miał 2 szablony spis_kategori.tpl i spis_podkategori.tpl, a w widoku wybierał który to ma być tpl smile.gif Nie zaprzegajmy templatek do tego ponieważ grafik ma miec jak najprostrze zadanie smile.gif
thornag
Przeciez nie o szablony tutaj chodzi.

Jednak pokombinuje z wieksza iloscia kontrollerow. W aplikacji Javowej ktora sie tworzy i kumpla kontrolerow jest 80 tongue.gif Wiec moze u mnie jeden wiecej nie zaszkodzi tongue.gif
bim2
Nie rozumie Cię. Po co ci kilka kontrollerów? Co ty chcesz osiągnąć? :roll2:
Prph
Cytat(thornag @ 27.08.2006, 19:06:32 ) *
Powiedzmy ze gdzies w lewym panelu strony (przyjmujac uklad logo, lewy panel, czesc glowna) mamy liste jakis kategori. Po kliknieciu w liste ta lista zamienia sie w spis rzeczy w kategori.
Efekt tego taki ze cala strona pozostaje bez zmian, zmienia sie tylko ten jeden fragment.


Witam,

Ja realizuje to w nastepujacy sposob:

Mam obiekty zwane Apletami. Aptel w zalozeniu powinien posiadac funkcjoinalnosc zblizona do normalnego kontrolera - powinien miec dostep do danych post, get, session - do wszystkiego. Do modelu takze.

W szablonie php, jezeli chce uzyc menu z lewej strony, w odpowiednim miejscu pisze:

  1. <?php
  2. $this->applet('BoczneMenu');
  3. ?>


Widok wczytuje i uruchamia applet BoczneMenu. Ten z kolei moze sprawdzic, jakie parametry get przekazano do akcji i w zaleznosci od nich, moze wczytac menu takie, albo inne.

Uwzam ze rozwiazanie bardzo wygodne. Nie dam sobie reki uciac, ale chyba w symphony tez jest podobne rozwiazanie (przynajmniej ktos na forum tak wczesniej mowil).

Adrian.
bim2
@Prph ja mam podobnie, tyle że wywołuje akcję, np list_news smile.gif I wtedy w zalezności od danych z GET zwraca co innego. Aplet, fajne to, dopisze taką funkcję (przyda się, bedzie user mógł wyłączać neiktóre aplety biggrin.gif)

Pozdrawiam Bim.
Prph
Dokladmie tam to tak zrobione, ze w widoku mam helpery. JEzeli pisze:

  1. <?php
  2. $this->applet('nazwaApletu');
  3. ?>


widok laduje obiekt helpera Applet. Wykonuje metode execute i przekazuje jej parametry (w tym przypadku nazwe apletu). Helper Applet laduje klase wybranewgo apletu, wykonuje go i zwraca wynik smile.gif

Adrian.
thornag
Dzieki, jak mowilem osobny kontroller smile.gif Jak zwal tak zwal BlockController, Applet no ale dodatkowy tongue.gif

Ide do koodu.
bim2
Nie osobny kotroller. class Controller { function execute() {} function aplet($aplet) { $this->action=aplet; $this->execute(); } } I mówiłem Ci to od początku tyle że nie miałem (ładnego słowa) aplet a setAction(); jak zwał tak zwał ;]
Ociu
Może podzieliłem kontroler na FrontController i BlockController i też jest fajny winksmiley.jpg
thornag
@bim2 Ty chyba nie dokladnie czytasz to co ja pisze. Zdecydowalem ze chce to podzielic na osobne kontrollery !

@Ociu moglbys jakos przyblizyc jak to zrealizowales ?
Apo
Cytat(Prph @ 29.08.2006, 12:27:41 ) *
W szablonie php, jezeli chce uzyc menu z lewej strony, w odpowiednim miejscu pisze:

  1. <?php
  2. $this->applet('BoczneMenu');
  3. ?>


Widok wczytuje i uruchamia applet BoczneMenu. Ten z kolei moze sprawdzic, jakie parametry get przekazano do akcji i w zaleznosci od nich, moze wczytac menu takie, albo inne.

hmm nie wiem czy dobrze zrozumiałem ale to oznacza że w każdym szablonie php np 'dodajNewsa', 'komentujNewsa' musisz dać:

  1. <?php
  2. $this->applet('Logo');
  3. $this->applet('BoczneMenu');
  4. // tresc szablonu
  5. $this->applet('stopka');
  6. ?>


:?:
Ociu
Mamy kontroller główny, który odpala Front Controller i Block Controller.
Front odpowiada za content, a Block za bloki (lewe i prawe menu).
W zależnośći od tego jak mamy zbudowane menu (wyciągamy info z configu o blokach menu) i odpalamy odpowiednie akcje (np. getLastestPost()).
Apo
Cytat(Ociu @ 3.09.2006, 18:55:08 ) *
Mamy kontroller główny, który odpala Front Controller i Block Controller.
Front odpowiada za content, a Block za bloki (lewe i prawe menu).
W zależnośći od tego jak mamy zbudowane menu (wyciągamy info z configu o blokach menu) i odpalamy odpowiednie akcje (np. getLastestPost()).


A co jeśli np chcemy zmienic logo strony lub stopke :?:
Następnym problemem jest kolejność wywołania tych bloków: logo->lewe menu->tresc->prawe->stopka.
Myślałem nad dodaniem do kazdej akcji w konfiguracji nazwy poszczegolnych 'Apletów' które zostaną wykonane w określonej kolejności, jeśli takowego by nie było zostanie wczytany domyślny 'aplet' dla strony, tylko troche mało elestyczne rozwiązanie.
thornag
Logo i stopke mozna inlcudiwac w samym szablonie przeciez. Co do kolejnosci to mozna to zapisac dla odpowiednich stron w jakis plikach z lancuchami. Jesli nie potrzebujemy na danej stronie bloku wybieramy inny lacuch. Czy tak ?
Ociu
Cytat(Apo @ 3.09.2006, 21:27:11 ) *
A co jeśli np chcemy zmienic logo strony lub stopke :?:
Następnym problemem jest kolejność wywołania tych bloków: logo->lewe menu->tresc->prawe->stopka.
Myślałem nad dodaniem do kazdej akcji w konfiguracji nazwy poszczegolnych 'Apletów' które zostaną wykonane w określonej kolejności, jeśli takowego by nie było zostanie wczytany domyślny 'aplet' dla strony, tylko troche mało elestyczne rozwiązanie.


Jeśli chcesz zmienić coś w szablonie, to po prostu zmieniasz szablon.

Masz index.tpl i assignujesz tam prawe menu i lewe menu (wynik działania BlockControllera).
Prph
Cytat(Apo @ 2.09.2006, 10:15:19 ) *
hmm nie wiem czy dobrze zrozumiałem ale to oznacza że w każdym szablonie php np 'dodajNewsa', 'komentujNewsa' musisz dać:

  1. <?php
  2. $this->applet('Logo');
  3. $this->applet('BoczneMenu');
  4. // tresc szablonu
  5. $this->applet('stopka');
  6. ?>


:?:


Teoretycznie tak, ale mam widok dekorujacy i jeden szablon Main.php i to w nim ustawiam elementy stale jak menu. Wszystkie inne widoki dziedzicza z tego dekorujacego.

Adrian.
bim2
To ja mam tak, mam cos ala aplett(); i mam coś takieog jak index.php tam ustawiam BOCZNE MENU. A środek mam aplett($_GET['action']); a jak get action puste to np index tongue.gif Proste
Prph
Przedstawilem moje rozwiazanie, ale mam obecnie z nim problem... W zasadzie rzecz tyczy klasy Language.

Do tej pory mialem singletona Language. Za pomoca init('Jezyk') inicjalizowalo sie obiekt i Language wiedzial z jakiego jezyka korzystac.

Pozniej mialem metode load($Controller, $Action) - wczytujaca plik jezykowy dla danej akcji.
Pliki te trzymalem w katalogu: Language/English/Controller/Action.php.

W kontrolerze mialem metode getLanguage(), ktora zwracala mi instancje obiektu Language.

W szablonie odwolywalem sie do jezyka w stosob nastepujacy:

  1. <?= $this->lang('Nowosci', 'Pokaz', 'Naglowek') ?>


Problem pojawia sie z apletami. Nie wiem teraz jak wczytac plik jezykowy dla apletu? Klasa Language wymagalaby albo metody loadForApplet albo calkowitego przebudowania. Tylko na co?

Moze macie jakies pomysly?

Adrian.
bim2
A nie mozesz poprostu wywołacz getLanguage()? Ja mam to tak, ze do tego wszystkeigo (blockKontrollera, jak wy to nazywacie) używam jednej metody. A applte() zaweira np $this->action=$action; $this->execute();
Prph
No tak tam winksmiley.jpg
Ale chodzilo mi o wczytanie jezyka. Obecnie metoda load wyglada tak: load($sDirectory, $sFile, $sSection);

Dla kontrolera wczytam z parametrami: Controller, MojKontroler, MojaAkcja, zakladajac, ze plik jezykowy dla kontrolera zawiera wszystkie akcje.

Dla apletu zrobie: Applet, MojAplet, null.

Tylko musze teraz zrobic odwolania typu:

  1. <?php
  2. $oLang->get('Applet', 'User, 'Loggedin');
  3. ?>


Jest to konieczne, bo musze przeciez miec takze mozliwosc stworzenia apletu i kontrolera o tej samej nazwie winksmiley.jpg

Adrian.
MMP
Ja obsługe języków przeniosłem na język szablonów i nie mam problemów z wyborem języka.

{#Standard.Welcome@MMP}
Ładuje plik Standard.php, wywołuje sprintf( $aLang[ 'Standard' ][ 'Welcome' ], 'MMP' );
Prph
No a co z jezykiem w kontrolerach/akcjach?

W ogole, jak rozwiazaujecie problem informowania o zlych danych podanych w formularzu. Moj kod Przykladowy:

  1. <?php
  2. // akcja logowania w kontrolerze Auth:
  3.  
  4. public function LoginAction()
  5. {
  6. $oForm = new Rapide_Form;
  7.  
  8. if(!$oForm->isSubmitted()) // jezeli wyslano formularza, wyswietl go
  9. {
  10. return $this->getView('AuthLogin');
  11. }
  12.  
  13. $sLogin = $oForm->get('login');
  14. $sPassword = $oForm->get('password');
  15.  
  16.  // sprawdzamy czy podano dane.
  17.  // jezelie, wyswietlamy komunikat.
  18.  
  19. if(empty($sLogin) || empty($sPassword))
  20. {
  21. $aErrors[] = $this->getLanguage()->get('Auth', 'Login', 'Errors', 'Empty');
  22.  
  23. $oView = $this->getView('AuthLogin');
  24. $oView->errors = $aErrors;
  25.  
  26. return $oView;
  27. }
  28.  
  29. // model uzytkownika
  30. $oUserModel = $this->getModel('User');
  31.  
  32.  
  33. // sprawdzamy czy login i haslo pasuja
  34.  
  35. if(!$iUser = $oUserModel->getIdByLogin($sLogin, $sPassword))
  36. {
  37. $aErrors[] = $this->getLanguage()->get('Auth', 'Login', 'Errors', 'Data');
  38.  
  39. $oView = $this->getView('AuthLogin');
  40. $oView->errors = $aErrors;
  41.  
  42. return $oView;
  43. }
  44.  
  45. $aGroups = $oUserModel->getGroups($iUser);
  46.  
  47. // wszystko jest OK, ustawiamy dane uzytkownika. Od tej chwili jest on zalogowany.
  48.  
  49. $oUser = $this->getUser();
  50. $oUser->setAuthenticated();
  51. $oUser->setGroups($aGroups);
  52.  
  53.  
  54. // forwardujemy. w tym wypadku na domyslna strone.
  55. $this->forward();
  56. }
  57. ?>


Jak widac, uzylem jezyka w kontrolerze. Dziala to znakomicie i co wazne, zamiana jezyka to tylko zamiana tresci w pliku jezykowy. Niby wszystko ok, a jednak troche pracy bylo. nawet w glupim logowaniu.

Adrian.

Tak jak pisalem - Temat: Framework Rapide Framework Zapraszam do oceny. Polecam osobom, ktore tworza wlasny framework. Niestety nieudokumentowany kod (nie wyrobilem sobie nawyku dokumentowania w czasie pisania). Na pocieszenie powiem, ze kod jest przynajmniej bardzo czytelny.
Ociu
Nic nie przeszkadza, żeby przenieść langi do szablonów.
Nic nie stoi na przeszkodzie zrobić:
$smarty->assign('SystemMessage', $lang->get('System', 'Admin', 'Errors');
;-)

Można dopisać osobny system zarządzania językami do szablonów np. jako plugin ;-)
Prph
Ale to nie rozwiazuje problemu winksmiley.jpg
Obecnie mam tak, ze aplet i kontroler moga korzystac z jezyka. Takze widok moze z niego korzystac. Bledy ustawiam w kontrolerze, w widoku je wyswietlam. Widok ponadto moze korzystac z jezyka, np do wyswietlania naglowkow, linkow, tytulu strony itd, itd.
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-2024 Invision Power Services, Inc.