Drukowana wersja tematu

Kliknij tu, aby zobaczyć temat w orginalnym formacie

Forum PHP.pl _ Archiwum Pro _ [MVC] Pytań kilka...

Napisany przez: Zepco 27.01.2004, 23:49:48

Ponieważ nie mam dostępu do forum DEV, a wiem, że tam po części problem MVC był poruszany, postanowiłem zadać kilka pytań.

Coraz więcej mówi/pisze się na temat MVC (Model-View-Controller) ale pomimo usilnych starań nie mogę zrozumieć pewnych mechanizmów, tymbardziej, że większość przykładów podawanych jest w Java'ie.

Może zacznę od tego co już wiem, jeśli się mylę, proszę poprawcie mnie. smile.gif
Cała aplikacja składa się z trzech części:

:arrow: Kontrolera, który odbiera operacje z zewnątrz (input) i odpowiednio je przetwarza, wywołując konkretny model (modułu) i metodę tegoż modelu. Może również odwoływać się bezpośrednio do widoku.

:arrow: Modelu, który jest niejako modułem odpowiedzialnym za jakiś ułamek pracy aplikacji (menu, news, sonda itp, itd.). Także jak widać w przeciwieństwie do kontrollera istnieje wiele modeli. Jak wcześniej wspomniałem model odbiera od kontrolera odpowiednie rządania, przetwarza je i wynik może przesłać do widoku.

:arrow: Widok natomiast wszystkie dane wysłane z modelu lub kontrolera wysyła na zewnątrz (wyświetla wynik na WWW, tworzy dokument XML, PDF itp.). Tak więc może być kilka podwidoków, które wywołane przez widok głowny tworzą efekt końcowy widoczny dla użytkownika.

A teraz czas na pytania:
* w jaki sposób elementy te komunikują się?
* wiem, że najbardziej naturalnie będzie zastosować programowanie obiektowe, ale czy da się to zrobić strukutralnie?
* co jest w przypadku gdy jeden model jest zależny (potrzebuje danych) od drugiego modelu?
* czym są akcje (actions) i łańcuchy (chains)?

Jeśli coś pominąłem, proszę dopiszcie, Myślę, że dyskusja na ten temat wpłynie w jakimś stopniu na rozpowrzechnienie tego rozwiązania, a chyba na tym nam zależy, aby łatwiej tworzyć aplikacje webowe i w przyszłości korzystać z już napisanego kodu...

Napisany przez: rzseattle 28.01.2004, 06:44:34

No wiec tak sorry ale odpowiem nie po kolei :

ad 4

Akcje sa to logicznie podzieone operacje tzn ze w akcji starasz sie zawrzec najbardziej niepodzielna operacje jaka sie da. Czyli na przyklad akcje : zaloguj, usun artykul, dodaj artykul, pokaz menu itd. Akcje dzielimy naa logiczne i widoki. Akcje logiczne sa odpowiedzialne za realizacje zadan takich jak dodaj, usun, powiarz, sprawdz itd. podczas gdy akcje widoki maja za zadanie zwrocic dane do przegladarki.
Łancuch akcji polega na tym ze jezeli wciskasz przycisk usun artykul to najpierw wlacza sie akcja potwierdzajaca wybor potem ta akcja uruchamia akcje usuwajaca artykul ktora z kolei wywluje widok pokazujacy liste artykulow, taki lancuszek.

ad 1

Kontroler dostajac odpowiednie dane uruchamia odpowiednia akcje ktora uruchamia odpowiedni model. Mozna ten schemat komplikowac ale generalnie tak to wyglada.

ad 2

Jesli udalo by ci sie to oprogramowac strukturalnie to ja chcialbym taki silnik zobaczyc winksmiley.jpg

ad3

Wlasniesie spotkalem z takim problemem. No coz poprostu w akcji uruchamiam dwa modele.

ps Dodamtylko ze zadaniem modelu jest tylko i wylacznie stworzenie abstrakcji na dane tak aby jezeli sie cos zmieni np. w bazie to grzebiesz tylko w modelu a nie we wszystkich akcjach.

Napisany przez: radziel 28.01.2004, 09:45:57

Cytat
[...] Modelu, który jest niejako modułem odpowiedzialnym za jakiś ułamek pracy aplikacji[...]


Mylisz dwa pojęcia,
model ma za zadanie komunikację z bazą i zwracanie danych.

moduł to zbiór akcji które sąodpowiedzialne za "przetwarzanie" danych z modelu.

Mam nadzięję że dobrze wytłumaczyłem winksmiley.jpg

Napisany przez: rzseattle 28.01.2004, 13:51:40

Cytat(radziel)
Mylisz dwa pojęcia, 
model ma za zadanie komunikację z bazą i zwracanie danych.

moduł to zbiór akcji które sąodpowiedzialne za "przetwarzanie" danych z modelu.

Mam nadzięję że dobrze wytłumaczyłem winksmiley.jpg


No nie do konca winksmiley.jpg. To nie musi byc koniecznie baza danych, moga byc pliki, xml czy jeszcze jakies inne zrodlo danych.

Napisany przez: radziel 28.01.2004, 14:11:11

Cytat
No nie do konca winksmiley.jpg. To nie musi byc koniecznie baza danych, moga byc pliki, xml czy jeszcze jakies inne zrodlo danych.


No tak, ale wkażdym razie model zwraca dane do obróbki winksmiley.jpg

Napisany przez: Zepco 28.01.2004, 15:50:32

Cytat
No wiec tak sorry ale odpowiem nie po kolei :
ad3

Wlasniesie spotkalem z takim problemem. No coz poprostu w akcji uruchamiam dwa modele.


Nie wiem czy dobrze rozumiem, ale w pliku konfiguracyjnym mógłby być wpis o zależności (dependencies) od innego modelu.

A jak sprawa ma sie z widokiem i podwidokami?
Czy widok jest tą klasą główną, która wysyła dane do odpowiedniego podwidoku, a ten wysyła go na wyjście, czy też wyborem widoku zajmuje się kontroler?

Napisany przez: rzseattle 28.01.2004, 16:03:04

Cytat
Nie wiem czy dobrze rozumiem, ale w pliku konfiguracyjnym mógłby być wpis o zależności (dependencies) od innego modelu.

A jak sprawa ma sie z widokiem i podwidokami?
Czy widok jest tą klasą główną, która wysyła dane do odpowiedniego podwidoku, a ten wysyła go na wyjście, czy też wyborem widoku zajmuje się kontroler?


Jak juz wspomnialem model jest klasa tworzaca abstrakcje na zrodla danych, wiec jesli potrzebuje w danej akcji dwoch modelow to poprostu includuje oba i kozystam z dwoch przy czym jeden o drugim nie musi nic "wiedziec".

Nie rozumie co rozumiesz przez polwidok?? Akcje logiczna?

Lancuszek akcji jest tworzony w ten sposob:

1) Router "dekoduje" url i wysyla do kontrolera jak akcje ma uruchomic
2) Kontroler sprawdza czy akcja potrzebuje zalogowania , czy jest plik akcji itd...
3) Kontroler uruchamia akcje.
4) Akcja wykonuje sie i po zakonczeniu wywoluje inna akcje
5) Na koncu jest zawsze akcja - widok ktora wysyla dane do przegladarki i nie wywoluje juz innej akcji
6) Wykonywany jest destruktor kontrolera

THE END winksmiley.jpg

Przedstawilem to w sporym uproszczeniu, ten schemat tez mozna komplikowac, ale mniej wiecej tak to dziala.

Napisany przez: Zepco 28.01.2004, 18:20:48

Specyfikacja URLa oczywiście nie ma znaczenia i zależy jedynie od wyobraźni twórcy?
Czy dane wysłane przez POST i GET oraz te, które są zawarte w SESSIONS wyciągane są bezpośrednio przez modele, czy też tym też zajmuje się kontroler?

Napisany przez: radziel 28.01.2004, 18:32:24

Cytat
Specyfikacja URLa oczywiście nie ma znaczenia i zależy jedynie od wyobraźni twórcy?
Czy dane wysłane przez POST i GET oraz te, które są zawarte w SESSIONS wyciągane są bezpośrednio przez modele, czy też tym też zajmuje się kontroler?

Zajmuje się tym kontroler - najlepiej napisz klasę / funcję (zależy jak programujesz winksmiley.jpg ), która będzie zajmować się danymi z input'a.

Napisany przez: rzseattle 28.01.2004, 18:39:50

Cytat
Specyfikacja URLa oczywiście nie ma znaczenia i zależy jedynie od wyobraźni twórcy?


I od konfiguracji serwera winksmiley.jpg

Cytat
Czy dane wysłane przez POST i GET oraz te, które są zawarte w SESSIONS wyciągane są bezpośrednio przez modele, czy też tym też zajmuje się kontroler?


Nie trzeba MVC zeby wiedziec ze w pozadnym silniku nie uzywa sie tych tablic ( bezpieczenstwo). Tak na wstepie konstruktor kontrolera powinien wywolywac obiekt input ktory zajmie sie skladowaniem danych zewnetrznych. Sesje tez najlepiej zamaskowac pod jakas metoda kontrolera. Pamietaj tez ze zmienna z jednej akcji nie bedzie widoczna w drugiej wiec tez musisz pomyslec nad sposobem przekazywania tych zmiennych. Najlepiej wtedy dodac opcjonalny argument dla metody zapisujacej zmienna ktory powie "umiesc mnie w sesji" smile.gif.

ps Nie przesadzaj z tym Pomogl Mi

Napisany przez: kubatron 28.01.2004, 21:10:05

A mógłbym zapytać gdzie to można ściagnąć jak zainstalować,jakis kurs/manual i co to jest rolleyes.gif

Napisany przez: scanner 28.01.2004, 21:48:24

Jeden z dostępnych: http://phiend.sourceforge.net

Napisany przez: Nalfein][WR 29.01.2004, 13:49:18

Cytat
Nie wiem czy dobrze rozumiem, ale w pliku konfiguracyjnym mógłby być wpis o zależności (dependencies) od innego modelu.


Mógłby być, ale po co. Możesz po prostu includować (bezpośrednio przez include() lub przez inny obiekt - menedżera klas aplikacji) plik z klasą odpowiedniego modelu z poziomu innego modelu.

Cytat
A jak sprawa ma sie z widokiem i podwidokami?
Czy widok jest tą klasą główną, która wysyła dane do odpowiedniego podwidoku, a ten wysyła go na wyjście, czy też wyborem widoku zajmuje się kontroler?


Wyborem widoku zajmuje się kontroler, a raczej (przeważnie) ostatnia akcja w łańcuszku, tutaj nazywamy ją akcją widoku, gdzieniegdzie możesz ją znaleźć pod nazwą kontrolera widoku (ViewController). W niej ładujesz i wypełniasz szablon. Akcja widoku wypełnia sam widok, czyli przeważnie szablon Smarty, arkusz XSLT. Sam widok przeważnie nie jest klasą, chyba, że zastosujesz technikę kompilacji szablonów do klas. Na razie takiego engine-u pod php nie ma, ale już się robi (u mnie tongue.gif). Do widoku przekazujesz dane, porcję danych, możesz ją przechowywać w osobnej warstwie obiektów typu DataSpace/DataProvider, wtedy akcja widoku po prostu wybiera obiekty "dostawców danych" i obiekt(y) "widoku". Podwidoków w php nie ma wyodrębnionych jako tako, gdyż jak już wspomniałem widok jest płaski, inne widoki po prostu {include}-ujesz przez Smarty jak zwykłe fragmenty szablonów.

Napisany przez: bumelang 4.02.2004, 00:15:33

Cytat
Jak juz wspomnialem model jest klasa tworzaca abstrakcje na zrodla danych [ciach!]


Może jestem nadgorliwy, ale chodzi bardziej o to, że w kontrolerze nie są podejmowane żadne działania z zakresu logiki aplikacji. Kontroler steruje widokami, czyli po prostu interface'm użytkownika, zaś całość logiki zawiera się w modelu. Różnica jest taka, że model nie reprezentuje źródła danych. Fakt, że typowy model to np. wywołanie
[php:1:e6cd80946a]$managerProduktow->dodajProdukt($p)[/php:1:e6cd80946a]
ale od abstarkcji na źródło danych różni się to tym, że model może tu robić niezłą zamotkę z danymi, która z punktu widzenia kontolera jest nieistotna, i tu jest prawdziwy zysk - ktoś zmienia implementację logiki, ale logika prezentacji się nie zmienia.

Z resztą nie da się ukryć, że MVC ma największy sens przy aplikacjach heterogenicznych, gdzie model jest napisany w innym języku programowania, albo przynajmniej jest uruchamiany na innym serwerze.

Napisany przez: rzseattle 4.02.2004, 00:48:46

Cytat
zaś całość logiki zawiera się w modelu.

Musze przyznac ze sie pogubilem. Tworzac pod MVC nie spotkalem sie z sytuacja kiedy model w oparciu o dostarczone mu dane mial decydowac co ma zrobic ( a tak chyba definiujemy logike aplikacji :?: ), wrecz przeciwnie wszystko jest umieszczone w pojedynczych akcjach i to one decyduja co zrobic, przekazujac to modelowi ktory wie jak i gdzie. Jakdla mnie to jest czysta abstrakcja na zrodlo danych

Cytat
... ale od abstarkcji na źródło danych różni się to tym, że model może tu robić niezłą zamotkę z danymi, która z punktu widzenia kontolera jest nieistotna, i tu jest prawdziwy zysk - ktoś zmienia implementację logiki, ale logika prezentacji się nie zmienia.


Jesli mozna wiedziec to co rozumiesz przez "zamotke z danymi". Bo dla mnie zbior operacji ukryty pod jedna metoda to juz jest abstrakcja i biorac pod uwage ze model zajmuje sie danymi zewnetrznymi ( przeciez nie robimy w akcji $mathModel->dodaj($this->input['a'], $this->input['b'], $this->input['c']) ) to dla mnie jest to abstrakcja na zewnetrzne zrodla danych. A to czy operacje na danych sa proste czy skomplikowane to mnie nie interesuje.

No ale moze zle rozumie stwierdzenie "Logika aplikacji" winksmiley.jpg

Napisany przez: bumelang 4.02.2004, 09:54:56

Wszystko wskazuje na to, że mamy odmienne pojęcia na "abstrakcję źródła danych". Z tego, co wiem, to w typowym znaczeniu oznacza ona po prostu klasę dostępową do źródła, niezależną od implementacji na konkretnej bazie danych czy pliku - taki API, jak np. AdoDB.

Innymi słowy, w 3-warstwowym modelu aplikacji najniżej jest warstwa dostępu do danych (do której API dostępu z warstwy drugiej można określić "abstrakcją na źródło danych", jeśli takie jest zastosowane).

Warstwa druga, która jest najczęściej modelem, stanowi tymczasem zbiór klas czy funkcji tzw. "logiki biznesowej", co przede wszystkim oznacza, że ta warstwa + warstwa danych tworzy gotową aplikację - realizuje wszystkie zadane operacje na bazie danych, uwierzytelnianie użytownika, tworzy jakieś logi, wywołuje jakąś usługę SOAP, wysyła maila, cokolwiek, ale jest to kompletny, działający system, tyle, że zamiast interface'u użytkownika udostępnia API programistyczne dla warstwy jeszcze wyższej.

Warstawa kontrolera i widoku to tymczasem warstwa prezentacji, czyli jeszcze wyżej. I teraz wygląda to tak, że użytkownik się loguje, łaczy się z kontrolerem, któremu przesyła żądanie, ten czyści dane wejściowe i jeśli wszystko jest ok wywołuje funkcję zaloguj($login, $haslo) warstwy logiki biznesowej (czyli model) i sprawdza, czy to się powiodło, ale nie wie nic o szczegółach implementacji w modelu i - przede wszystkim - nie ma dostępu do bazy danych, nie może wywołać żadnego zapytania SQL. Później kontroler przekazuje sterowanie do odpowiedniego, w zależności od powodzenia operacji, widoku - ale to jest jasne.

Oczywiście 3-warstwowy model aplikacji jest tu tylko po to, żeby objaśnić zagadnienie modelu jako takie w kontekście "abstrakcji źródła danych". W rzeczywistym systemie z zastosowanym MVC mogą być z równym powodzeniem tylko 2 warstwy - sama prezentacja i model.

Jak widzisz, być może że tylko 1 pojęcie sprawiło, że myślisz, że tego nie rozumiesz, a rozumiesz - jeśli tak to sorry za zamotkę winksmiley.jpg

Napisany przez: rzseattle 4.02.2004, 11:22:27

Cytat
Warstwa druga, która jest najczęściej modelem, stanowi tymczasem zbiór klas czy funkcji tzw. "logiki biznesowej", co przede wszystkim oznacza, że ta warstwa + warstwa danych tworzy gotową aplikację - realizuje wszystkie zadane operacje na bazie danych, uwierzytelnianie użytownika, tworzy jakieś logi, wywołuje jakąś usługę SOAP, wysyła maila, cokolwiek, ale jest to kompletny, działający system, tyle, że zamiast interface'u użytkownika udostępnia API programistyczne dla warstwy jeszcze wyższej.


No maly OT sie zrobil. Ale czy udostepnianie API programistycznego ktore maskuje wszelkie zrodla danych i nie wymaga wiedzy skad i dokad podazaja zmienne nie jest abstrakcja na zrodlo. Dla mnie wlasnie tu jest granica - Dopiero tam gdzie przestajemy sie interesowac czy dane pochodza z ADoDB czy jakiegos obiektu obslugujacego XML konczy sie abstrakcja. Ale rozumiem twoje podejscie , jednak zauwaz ze np ADoDB tez udostepnia API programistyczne ktore ulatwia obsluge bazy danych.

No ale jak juz powiedzialem OT smile.gif.

Napisany przez: bumelang 4.02.2004, 11:46:58

Być może to jest OT, ale nie wiem, czy można nazwać abstrakcją na źródło danych coś, co nie koniecznie operuje na danych w bazodanowym sensie i nie koniecznie ma dostęp do źródła danych. Przecież model może np. pobrać informacje o dostępności produktu przez SOAP, sprawdzić stan rachunku bankowego, zamówić produkt i przelać kasę. I to wszystko w jednym wywołaniu modelu.

A warto też dodać, że model może być np. aplikacją w C, która ma za zadanie obliczyć symulowane odsetki, a kontroler tylko robi exec('/usr/bin/odsetki -sklada_miesieczna 3000');

Napisany przez: Zepco 4.02.2004, 12:18:48

Jak dla mnie takie OT mogą być, o ile mieszczą się w pewnych ramach tematu tak jak powyższa polemika. :-)

Tak na marginesie chciałem zapytać skąd czerpaliście informacje na temat MVC?

Napisany przez: Sh4dow 4.02.2004, 12:55:15

Moze troche sie wtrącam do waszej zrozmowy, ale moze powiecie mi pare rzeczy. Jako ze nie obeznany jestem tak jak Wy, nie zawsze kojaze co za skroty uzywacie, albo jakies pojecia anglojezyczne. No ale nie o oto i do konca chodzi. Jak napisal scanner ze jeden z takich MCV jest dostepny na necie oczywiscie tam zagladolem. Ale niestety moja wiedza tajemna nie byla wstanie przegrysc samego manuala, wiec o testach na phiendzie nie bylo mowy.
Ale po kolejnych postach zaczyna cos mi swiatac na temat calego tego MVC.

Bumelang napisał o 3 warstwowym poziomie aplikacji, szczerze mowiac dopiero jego post dal mi do myslenia jesli chodzi o cale zagdanienie MVC.

Jesli dobrze zrozumialem do pierwsza warstwa jest odpowiedzialna za pobranie danych, naprzyklad skrypt rozpoznaje zapytanie, np User chce zobaczyc na stronie komantarze do artykulu, wiec skrypt rozpoznaje ze chodzi o komentarze o jakies danej specyfikacji, wiec lpobiera dane dla tej specyfikacji (pliki, bazy danych, sockets itd). Procz tego apytania, sa standardowe zapytanie, powiedzy o konfiguracje strony (tytul, adres, kolor itd). Jako standardowe zapytanie przy wiekszosci odslon.
Ta warstwa teoretycznie konczy swoje zadanie i przesyła dane do drugiej warstwy, której zadaniem jest przetworzenie wszystkich otrzymanych danych. Tutaj nawołując do przykladu, skrypt powiedzmy ze w komentarzach przetwarza text (np BBcode) ustawia zapis daty i jakie pare tam innych opcji mniej waznych.
Przetworzone dane wędruja teraz do warstwy ktora zajmuje sie wyswietlanie, powiedzmy ze beda to Smarty, które generuja nam gotowy kod wysylany do przegladarki. i tutaj piszecie jeszcze o wykonaniu destruktora.

A teraz pare Pytanek:
- czy dobrze zrozumialem to zagadnienie? oczywiscie jest ono mocno uproszczone.
- czy warstwa 2(czyli przetwarzanie danych) moze czesciej pobierac dane z 1 warstwy? Np. po otrzymaniu danych, podczas przetwarzania pobrac dodatkowe informacje, czy trzeba przewidziec to w 1 warstwie i wyslac odrazu.
- czym jest destruktor, jakie jest jego działaniei i co sie stanie jesli go nie bedzie?

Cytat
Oczywiście 3-warstwowy model aplikacji jest tu tylko po to, żeby objaśnić zagadnienie modelu jako takie w kontekście "abstrakcji źródła danych". W rzeczywistym systemie z zastosowanym MVC mogą być z równym powodzeniem tylko 2 warstwy - sama prezentacja i model.

czy zalozenie 2 warstw mam rozumiec poprze poprzez polaczeni pierwszej i drugiej? Ma to jakas zalete?

Napisany przez: hawk 4.02.2004, 15:22:33

Cytat
Jak napisal scanner ze jeden z takich MCV jest dostepny na necie oczywiscie tam zagladolem. Ale niestety moja wiedza tajemna nie byla wstanie przegrysc samego manuala, wiec o testach na phiendzie nie bylo mowy.

Hmm, jako autor phienda potwierdzam że proste to-to nie jest. A moje anty-patriotyczne podejście do lokalizacji manula :oops: niektórym nie ułatwia sprawy. Ale podobno gdzieś tutaj na forum powstaje tłumaczenie.

Ja myślę że kojarzenie MVC z warstwami jest zbytnim uproszczeniem. Owszem, MVC wymusza podział aplikacja na warstwy (w ogóle wymusza sensowną organizację aplikacji). Ale warstw może być więcej niż 3, np:

1) baza danych (mySQL)
2) warstwa abstrakcji nad bazą danych (ADODB)
3) klasy Modelu (php)
4) Kontroler (php)
5) klasy Widoku (php)
6) szablony Widoku (Smarty)
7) wynik końcowy (HTML)

To daje 7 warstw smile.gif . Dzielić można różnie, ale ważne jest to, że wg. MVC aplikacja powinna mieć 3 główne częśći:

1) Model: logika biznesowa, operacje na źródle danych (np. baza danych), nic nie wie o HTML

2) Widok: logika prezentacji, czyli nie tylko szablony (ale implementacja Widoku za pomocą szablonów jest dobrym pomysłem), wie jak wyciągnąć potrzebne dane z Modelu

3) Kontroler: zbiera to wszystko do kupy, wie że jest żądanie strony i decyduje co należy zrobić żeby wygenerować odpowiedź

MVC pozwala łatwo modyfikować aplikację, np. zmieniać bazę danych, strukturę URLi, wygląd strony, przejść z HTML na PDF, itd. Bo jest podział odpowiedzialności i hermetyzacja.

Cytat
Tak na marginesie chciałem zapytać skąd czerpaliście informacje na temat MVC?

Niektórzy, nie chwaląc się, czerpali m.in. z dokumentacji phienda biggrin.gif , ale poza tym polecam artykuły w php|architect z maja i czerwca 2003. Jakoś trafiłem na promocję i darmowy numer.

Poza tym, jak tylko ruszy portal php.pl, pokaże się na nim mój obszerny artykuł na ten temat. Na razie leży sobie gotowy w DocBooku i czeka, aż będzie gdzie go umieścić.

Napisany przez: bumelang 4.02.2004, 15:30:08

Cytat
Tak na marginesie chciałem zapytać skąd czerpaliście informacje na temat MVC?


Ja prywatnie znam to zagadnienie z Javy, gdzie jest kilka framework'ów MVC - np. Struts albo WebWorks i też kilka książek dotyczących wzorców projektowych. Nie mniej, jeśli nie znasz Javy, to niewiele Ci to pomoże - ale na lekturkę być może warto zawsze się szarpnąć, bo koncepcja jest wspólna.

Cytat
Jak napisal scanner ze jeden z takich MCV[...]

Mylisz trochę pojęcia - MVC to nie jakiś program czy skrypt, tylko strategia pisania interface'u użytkownika. Taką strategię w bardziej rozwiniętych obiektowo językach nazywa się wzorcem projktowym. Ten wzorzec definiuje po prostu, że ma być ten model, view i controller i jak mają ze sobą współpracować. Wybór konktretnego ułatwiacza to nie wybór MVC.

A co do tego, co napisałeś potem, to chyba za bardzo namieszałem z tymi warstwami. MVC nie ma z tym nic wspólnego. Model, widok i kontroler to 3 klasy i tylko tyle. Teraz, jeśli masz aplikację pisaną w architekturze 3-warstowej, to tak wychodzi, że kontroler i widok są w warstwie klienta (prezentacji) a model w warstwie logiki biznesowej. Ale ogólnie mówiąc architektura 3-warstwowa jest niezależna od MVC jako pojęcie.

Działa to tak: użytkownik wysyła żądanie w sensie HTTP, np. wypełnia jakiś formularz i klika "Submit", gdzie akcja formularza jest ustawiona na skrypt, w którym znajduje się kontroler. Ten łączy się z modelem, wywołuje tam jakieś metody biznesowe i gdy te zwrócą mu już efekty swojej pracy, to w zależności od tego, jakie one są, przekazuje to wywołanie do odpowiedniego widoku, czyli odpowiedniej strony php (która może być napisana w Smarty). W php w najprostszym wariancie może być to po prostu
[php:1:a43ca395d1]<?php
/* Kontroler */
if($model->zaloguj($login, $haslo) == SUCCESS) //wywołanie modelu
include("strona_glowna.php"); // wywołanie widoku
else
include("blad.php"); // wywołanie innego widoku
?>[/php:1:a43ca395d1]

Różnica w architekturze pomiędzy MVC a jego brakiem jest taka, że bez MVC logika jest zaszyta w kontrolerze (można powiedzieć, że nie ma warstwy logiki). Nie można jednak traktować Smarty jako kolejnej warstwy, bo to nie o to chodzi.

Natomiast aplikacja może być 2-warstwowa w takim sensie, jak napisałem wtedy, jak nie ma bazy danych, tylko np. coś liczy. Wtedy warstwa danych nie istnieje, nie że łączy się z jakąś inną w jedność.

Mam nadzieję, że nie zaciemniłem za bardzo obrazu tymi warstwami smile.gif

Napisany przez: DeyV 4.02.2004, 19:27:46

jak już trwa taka zaciekła rozmowa na temat MVC, to zauważę, że warto ponownie zainteresować się ciekawym systemem WACT http://www.phppatterns.com/index.php/article/articleview/85/1/9/
System ten, poza paroma ciekawymi innowacjami, pokazuje również (z tego co zdążyłem się zorientować po paru minutach przegladania) bardzo ciekawy sposób komunikacji pomiędzy modelem a widokiem, któy pozwala na przeniesienie zainicjowania procesu pobrania danych przez view, dopir0o w momencie, gdy te dane będą mu potrzebne.
Chyba nie trzeba nikogo przekonywać, jak często takie rozwiązanie może być bardzo przydatne.

Napisany przez: hawk 4.02.2004, 22:22:12

Hmm, ciekawe...
Z tego co na razie widziałem, WACT ma bardzo fajny system szablonów. Wspominał o tym gdzieś Nalfein (ale o idei, nie o WACT): wyciągać dane z modelu tylko wtedy, kiedy widok naprawdę ich potrzebuje, a nie jak np. w Smarty najpierw wyciągać, a potem zobaczymy czy widok w ogóle z nich skorzysta. To jest wielki plus.

I sam język szablonów jest ładny, taki XML-owy smile.gif . Czyli podobny do Struts w Javie. Albo nie do samego Struts, ale do JSP generalnie. Taka strona wygląda jak JSP i działa mniej więcej jak JSP.

Ale nie widziałem tam jeszcze samego kontrolera :? . Może dlatego że coś mi strona WACT kiepsko działała. Anyway, gdzie tam jest założenie, że mamy jeden główny skrypt (kontroler) i akcje? Gdzie rozdział między akcjami a modelem? W tutorialu widziałem SQL przemieszany z assignami do szablonu.

No ale niedokładnie szukałem, a sam WACT jest pre-alpha. Na razie wydaje mi się, że to jest świetne rozwiązanie widoku, ale nie całego MVC.

Napisany przez: scanner 4.02.2004, 22:58:39

Cytat
Hmm, jako autor phienda potwierdzam że proste to-to nie jest. A moje anty-patriotyczne podejście do lokalizacji manula :oops: niektórym nie ułatwia sprawy. Ale podobno gdzieś tutaj na forum powstaje tłumaczenie.
Jako szef Content Teamu Mogę powiedzieć, że tłumaczenia już jest gotowe, niestety tłumaczka nie miała do dyspozycji edytora XML, zatem ja żmudnie w wolnych chwilach przenosze wszystko z Worda. Dostępne na CVS'ie (dla developerów) jest już 4,5 rozdziału i byłbym wdzięczny hawk, gdybyś na to zerknął. Jutro powinieniem dodać końcówkę 4 i może cały 5 rozdział.
Hawk: w razie uwag, proszę na PW lub maila smile.gif

Dokumentacja phienda po polsku w założeniach ma ukazać się na php.pl.

Napisany przez: cagrET 5.02.2004, 01:41:57

Cytat
Anyway, gdzie tam jest założenie, że mamy jeden główny skrypt (kontroler) i akcje? Gdzie rozdział między akcjami a modelem?

Jeżeli dobrze doczytałem to doszli do wniosku, że kontroler jest zbędny w php. Kod jest mniej elastyczny, trudniej jest go zintegrować z innymi aplikacjiami. Za kontroler uznano sam Apache, a akcjami są pliki .php

czyli struktura aplikacji jest w stylu:

/news/view.php
/news/list.php
/news/edit.php

/forum/viewTopic.php
/forum/viewForum.php

etc

Napisany przez: Nalfein][WR 6.02.2004, 15:57:13

Cytat
Jeżeli dobrze doczytałem to doszli do wniosku, że kontroler jest zbędny w php. Kod jest mniej elastyczny, trudniej jest go zintegrować z innymi aplikacjiami. Za kontroler uznano sam Apache, a akcjami są pliki .php


Wow! A już myślałem, że tylko ja jestem taki crazy, żeby zrywać ze wszystkimi standardami ;P Założenia bardzo fajne, popieram wszystkiema ręcami i nogami.

Ale to ma też minusy, bo nie można dać dwóch urli (np. pl-"electronics" i en-"elektronika") pod jedną akcję, chyba, że będziemy chamsko robili require() przy w drugim pliku. Dlatego robię u siebie akcje tylko wywoływane (wybierane) ze skryptów w "site dir", a implementecje są dalej w "code dir". W ten sposób zyskuję to co chcieli w WACT - eliminuję router (do pewnego etapu - pliki w "site dir" mogą być routerami, bo mogę napisać /forum/viewpost.php/110), ale zachowuję możliwość zmiany URLi bez zmiany nazwy pliku z akcją.

Napisany przez: hawk 6.02.2004, 17:25:01

Minusów jest więcej:
- Co zrobić, jak tego pliku akurat nie ma? Kontroler sobie poradzi, Apache nie.

- Nie każda akcja musi kończyć się wyświetleniem HTMLa - patrz akcje logiki. A tak co? Robić require w tych plikach, i skończyć z taką siecią powiązań?

- Jak będziesz chciał zmienić np. lokalizację WACT, albo jakiekolwiek inne ustawienie globalne, to globalny regexp po wszystkich plikach albo z godzinka roboty...

Jest różnica pomiędzy wywaleniem w ogóle kontrolera, a eliminację routera. Chociaż pojęcie routera jest nasze autorskie i nie występuje w MVC. Hierarcha katalogów jako sposób wybierania akcji do wywołania OK, ale oni idą znacznie dalej.

BTW, trochę zabawne że oni mimo to piszą o MVC. Zrobiliśmy framework oparty o wzorzec Model-View-Controller, ale wywaliliśmy z wzorca cały kontroler laugh.gif . Co nie znaczy że wszystko co dobre musi być MVC. Ale jeżeli ktoś usilnie stara się przedstawić swój projekt jako MVC, to o czymś świadczy...

Napisany przez: Nalfein][WR 6.02.2004, 21:57:31

Nie wywalili kontrolera, ale wywalili obiekt typu FrontController. Akcje logiki to też przecież warstwa kontrolera.

Napisany przez: hawk 6.02.2004, 22:57:34

Ale warstwa kontrolera bez kontrolera? biggrin.gif
To tak jak system bazodanywy bez bazy danych. Albo aplikacja obiektowa bez obiektów.

Zresztą, u nich nie ma akcji logiki.

Napisany przez: Nalfein][WR 7.02.2004, 12:28:19

Chyba za dużo nad Phiendem przesiedziałeś winksmiley.jpg To tak jak rozproszona baza danych (np. pliki XML) czy jak aplikacja obiektowa bez menedżera obiektów. Ja robię to tak np. w pliku /forum/view.php mam:

[php:1:17e5bd469d]
<?php
$app = CodeZone::instance();
$action = $app->create('ViewForumAction', 'actions/forum');
$app->run($action);

// albo $app->execute($request, $response, $action);
// aby realizować testy XP z obiektami FakeRequest oraz FakeResponse
?>
[/php:1:17e5bd469d]

Metoda ::run() klasy aplikacji przekazuje obiekt $action do kontrolera wraz z obiektami $request, $response, które tworzy. Kontroler obsługuje żądanie wypełniając $response, a aplikacja wyrzuca wynik na ekran. Nie wywołujemy tutaj jawnie kontrolera (FrontControllera), przez co możemy w ogóle z niego zrezygnować w prostych aplikacjach, a może za tym wszystkim siedzieć nawet Phiend2.

© Paladine Framework winksmiley.jpg

Napisany przez: cagrET 7.02.2004, 14:28:31

Cytat
- Co zrobić, jak tego pliku akurat nie ma? Kontroler sobie poradzi, Apache nie.

Już raz to gdzieś pisałem
Kod
<IfModule mod_rewrite.c>

    RewriteEngine On

    RewriteCond %{REQUEST_FILENAME} !-f

    RewriteCond %{REQUEST_FILENAME} !-d

    RewriteRule ^(.*)$ error/404.php [L]

</IfModule>


Cytat
- Nie każda akcja musi kończyć się wyświetleniem HTMLa - patrz akcje logiki. A tak co? Robić require w tych plikach, i skończyć z taką siecią powiązań?

Nie rozumiem co miałeś tutaj na myśli. Kto powiedział że każda akcja musi się kończyć wyświetleniem htmla ? Jaka sieć powiązań ? To właśnie użwając FronControllera jest dużo niepotrzebnych includów.

Cytat
- Jak będziesz chciał zmienić np. lokalizację WACT, albo jakiekolwiek inne ustawienie globalne, to globalny regexp po wszystkich plikach albo z godzinka roboty...

Bardziej cenię sobie elastyczność. Ty już jesteś przyklejony na zawsze do tych ustawień globalnych. Ja mam wolną rękę. A gdy potrzebuję globalnych zmian REGEXP jest idealnym narzędziem biggrin.gif

Cytat
BTW, trochę zabawne że oni mimo to piszą o MVC. Zrobiliśmy framework oparty o wzorzec Model-View-Controller, ale wywaliliśmy z wzorca cały kontroler laugh.gif . Co nie znaczy że wszystko co dobre musi być MVC. Ale jeżeli ktoś usilnie stara się przedstawić swój projekt jako MVC, to o czymś świadczy...

Nie zapominaj że php jest językiem skryptowym. Nie widzę sensu kopiować wszystkiego krok w krok z innych języków, bo w php się to po prostu nie sprawdza. O kontrolerze już pisałem że jest, tylko inaczej pojmowanym.

Napisany przez: hawk 7.02.2004, 15:38:42

To w takim razie każda aplikacja w php jest oparta o wzorzec MVC, bo w każdej występuje Apache jako kontroler. Dochodzimy do absurdu.

Napisany przez: Sh4dow 7.02.2004, 17:03:06

Hmm, tak szczerze mowiac, to kazda strona napisana w php, z wykozystaniem, bazy danych, jest juz oparta na modelu MVC.
Jesli dobrze wszystko rozumiem, to kazda strona dziala na takim założeniu. Dziwne by to chyba wygladało jak by szlo to w odwrotnym kierunku.
zeby nie zrobic gafy opieram sie na zend.com. Chyba kazda strona pobiera najpierw dane, pozniej dane sa obrabiane w tak zwanej "business logic" a na koncu sa/"moga byc" wyswietlane.
mam nadzieje ze teraz rozumiem to, jakos prawidlowo. Patrzac na to co wy mowicie, to jedyne czym moga sie roznic "wasze" strony od "moich" (mowie tutaj o sposobie pisania) to jest taka ze wy tworzycie zaawansowane klasy, a ja siedze jeszcze po czesci w procedurach.

Napisany przez: Nalfein][WR 7.02.2004, 17:35:12

Cytat
To w takim razie każda aplikacja w php jest oparta o wzorzec MVC, bo w każdej występuje Apache jako kontroler. Dochodzimy do absurdu.


Jeśli uważasz, że wzorzec FrontController-a = całe MVC to może i tak smile.gif Tylko, że Apachem możemy wskazać jeden obiekt MVC, zależnie co mamy pod urlami - akcję lub widok. Chyba, że w plikach .php wybieramy widok i akcję wypełniającą widok (ViewController jak się zresztą ją określa) - wtedy mamy taki rozproszony kontroler, a Apache robi za router.

Napisany przez: KaGe 11.05.2004, 00:05:41

OK
MVC itd...
Ale jak to wygląda w praktyce? - w momencie, gdy mamy zabrać się za pisanie właściwego projektu - opisać klasy itd...

czy ktoś ma jakiś gotowy wykresik prezentujący np. podział klas na MVC - w miarę dokładny?

Bo z tego co tu się pojawia to ja to widzę jakoś tak:

+KONTROLER © - max nadrzędnie
|- MODEL_a (M) - ściąga dane z bazy i operuje na nich fizycznie
|- MODEL_b (M) - inna klasa operująca na danych - np. danych usera itd..
|- MODEL_c (M) - jeszcze co innego - np. odpowiedzialnego za newsy, artukuły itd...
|- WIDOK (V) - dostaje info z kontrolera - po przetworzeniu odpowiedniego modelu i wyświetla to lub tworzy plik z wynikiem - w każdym bądź razie jest wywoływany na końcu i zajmuje się tylko prezentacją

Czy dobrze rozumuję?

Napisany przez: marcin96 11.05.2004, 07:10:35

http://phppatterns.com/index.php/imagecatalogue/imageview/15/?RefererURL=/article/articleview/19/1/1/

...tyle tylko, że w większości frameworków MVC masz jeden obiekt kontrolera, który wywołuje odpowiednie akcje/widoki w odpowiedzi na dane wejściowe. Model łączy się z akcjami/widokami poprzez agregację (czyli tak jak na tamtym diagramie) lub kompozycję (a nie przez dziedziczenie... bo wtedy to już masz model zagnieżdżony w akcjach/widokach.. a tego chcemy uniknąć przeważnie - inaczej to nie jest MVC snitch.gif) ). Czyli jedyne co robisz w widokach/akcjach, to wywołujesz odpowiednie metody odpowiednich modelów. Przynajmniej ja tak to wszystko rozumiem snitch.gif]

Napisany przez: KaGe 12.05.2004, 00:54:57

Diagram widziałem, napisałem sobie nawet własne MVC - dokładnie takie samo, ale dot. czego innego - żeby się nauczyć. - nauczyłem się tego.
Ale:
1) jakbym chciał zrobić usuwanie, doadawanie itd.. - to gdzie dodać odpowiedzialne za to funkcje? - chyba do modelu, ale tam model jest tak zrobiony, że nie odpowiada konkretnemu zbiorowi danych w tabeli a jedynie służy za narzędzie. Więc może do kontrolera? - ok, ale on musiałby przekazać to wszystko do modelu i patrze pkt. wyżej....
2) nigdzie tam nie ma ustalonego id dla OKREŚLONEGO odpowiednika w bazie danych!! - ja wiem, moze nie do konca rozumiem OOP itd.. ale czy to nie jest troche malo uniwersalne, jezeli tylko kontrolerowi podaje id do wyswietlenia i nie moge potem np. zrobic tak:
[php:1:a31b6f25fe]<?php
$a = new ArticleSingleController($dao,$_GET); // gdzie $_GET[id]=2
$a-> // i tu jakos podzialac zeby display wyswietlil np. 3 art.
echo $a->view->Display();

?>[/php:1:a31b6f25fe]
Da sie tak?

Napisany przez: marcin96 12.05.2004, 06:11:35

ad 1) poczytaj dokumentacje phienda snitch.gif)

http://phiend.sourceforge.net/manual/actions.html <- zwlaszcza to pomoże...

W akcjach/widokach wywolujesz jedynie odpowiednie metody modelu. np
[php:1:121515932c]<?php
$ProductModel->DeleteItem($_GET['id']); // to będzie w akcji odpowiedzialnej za usuwanie
$ProductModel->UpdateItem($_GET['id'], $_POST['data']); // a to w akcji odpowiedzialnej za update..
?>[/php:1:121515932c]

Dopiero w modelu trzymamy SQL, czy cokolwiek innego odpowiedzialnego za usuwanie, modyfikacje.. czy zwracanie danych.

ad 2) w tym przykladzie jak zobaczysz na zrodlo ( http://phppatterns.com/index.php/article/articleview/19/1/1/ ...bo chyba podałem wczesniej link przypadkiem tylko do samego diagramu..), to kontroler tak naprawde zostal zrealizowany w index.php:
[php:1:121515932c]<?php
switch ( $_GET['view'] ) {
case "product":
$controller=& new ProductItemController($dao,$_GET);
break;
default:
$controller=& new ProductTableController($dao,$_GET);
break;
}
?>[/php:1:121515932c]

Tamten przykład podałem aby pokazać zależność między widokami/akcjami a modelem.. natomiast jak dla mnie realizacja kontrolera jest całkowicie bezsensowna... Naprawdę polecam lekturę Phiend'a. Na stronie projektu ( http://sourceforge.net/project/showfiles.php?group_id=90219 ) też jest źródło aplikacji, którą masz tutaj:
http://phiend.sourceforge.net/application/

Napisany przez: KaGe 12.05.2004, 22:39:58

1) Czy mam w takim razie do kontrolera, oproocz $model i $view dodać np. obiekt $action , który będzie działał na modelu? czy po prostu do samego modelu dodac odpowiednie metody?

2) A moze po prostu w modelu owszem, dopisac metody usuwania itd... a potem w kontrolerze - odpowiadające im, ale juz przekazujące identyfkatory i dane? - czy tak bedzie dobrze?

3) Jeszcze jedna sprawa: Tak mi sie wydaje, ze jak robie strone w MVC to:
powinien byc 1 kontroler - ktoory by wszystko tworzyl, ustawial, usuwal itd...
modele : odpowiedzialny za baze danych, odpwiednie do newsoow itd.. ,
widoki : prezentacje kazdego z modeli do newsoow itd...

Teraz tak:
czy nie powienien byc jeszcze jeden model i odpowiadajacy mu widok : np. o nazwie SiteModel i SiteView - ktoore odpowiadaly by za cala strone?
i np: SiteView to cos takiego:
[php:1:21abc83259]<?php
Class SiteView
{
var $views;
var $model;
var $output;

function SiteView($model)
{
$this->model = $model;
}

function AddView($view)
{
$this->views[] = $view;
}

function Header()
{
// naglowek <html> itd...
}

function Footer()
{
// /html itd...
}

function Site()
{
foreach($this->views as $n => $view)
{
$this->output .= $view->Display();
}
}

function Display()
{
$this->Header();
$this->Site();
$this->Footer();
return $this->output;
}
}
?>[/php:1:21abc83259]

Czy to jest dobre rozwiązanie?
jak np. chciałbym wyswietlic newsy to tylko bym dal w kontrolerze, ze

[php:1:21abc83259]<?php
$news= new NewsModel;
$newsview = new NewsView($news);

$siteview = new SiteView;
$siteview->AddView($newsview);

// a potem juz tylko:
echo $siteview->Display();

?>[/php:1:21abc83259]

Napisany przez: marcin96 13.05.2004, 07:43:40

Cytat
1) Czy mam w takim razie do kontrolera, oproocz $model i $view dodać np. obiekt $action , który będzie działał na modelu? czy po prostu do samego modelu dodac odpowiednie metody?


Do kontrolera nie dodajesz modelu... to w akcji/widoku sobie tworzysz instancje jednego modelu.. lub więcej, jeśli masz taką potrzebę.

Wprowadziłem tutaj podział na obiekty action i view podobnie jak w phiend - te pierwsze to akcje logiki - odpowiadają za modyfikację danych (tak, operują na modelu, który posiada metody dodajElement, zmieńElement itp), a te drugie to akcje widoku - odpowiadają, za zwracanie danych klientowi - wyświetlanie, przekierowanie do innej strony itp (również operują na modelu, korzystają z metod typu np:zwróćListęProduktów, zwróćProdukt itd). Może przykładowy kod (phiend) ;>]
[php:1:4e23e0d6b9]
<?php

class ActionUpdateProduct extends Action
{

function perform()
{
$data['ID'] = $_GET['ProductID'];
$data['price'] = $_POST['ProductPrice'];
$data['name'] = $_POST['ProductName'];

$product = new Product($_GET['ProductID']);
$product->updateProduct($data);
return 'ViewProduct';
}

}



class ViewProduct extends Action
{

function perform()
{
$product = new Product($_GET['ProductID']);

$data = $product->getAsArray();

// i tutaj wyświetlanie produktu
// [..]

return true;
}

}
?>
[/php:1:4e23e0d6b9]
Cytat
2) A moze po prostu w modelu owszem, dopisac metody usuwania itd... a potem w kontrolerze - odpowiadające im, ale juz przekazujące identyfkatory i dane? - czy tak bedzie dobrze?


Kontroler służy jedynie do wybierania, którą akcję/widok ma 'uruchomić', tworzenia sesji, autoryzacji i sprawdzania, czy dany user ma uprawnienia do odpalenia danej akcji itp, natomiast nie ma nic wspólnego z modelem (yhm... jedynie np: mechanizm autoryzacji musi korzystać z modelu User, ale to już troche inna para kaloszy)

Cytat
3) Jeszcze jedna sprawa: Tak mi sie wydaje, ze jak robie strone w MVC to:
powinien byc 1 kontroler - ktoory by wszystko tworzyl, ustawial, usuwal itd...
modele : odpowiedzialny za baze danych, odpwiednie do newsoow itd.. ,
widoki : prezentacje kazdego z modeli do newsoow itd...


Dokładnie...

Cytat
Teraz tak:
czy nie powienien byc jeszcze jeden model i odpowiadajacy mu widok : np. o nazwie SiteModel i SiteView - ktoore odpowiadaly by za cala strone?
i np: SiteView to cos takiego:
[..]
Czy to jest dobre rozwiązanie?


IMHO nie bardzo... operując na MVC w stylu phiend, to zrobiłbym raczej klasę rodzica, a każdy widok aby dziedziczył po tej klasie:
[php:1:4e23e0d6b9]
<?php
Class SiteView extends Action
{

function Header()
{
// naglowek <html> itd...
}

function Footer()
{
// /html itd...
}

}

Class ViewProduct extends SiteView
{

function Display()
{
$this->header();

// tutaj inicjowanie modelu, zbieranie danych itp
// i następnie ich prezentacja

$this->footer();
}

}
?>[/php:1:4e23e0d6b9]

...albo drugie rozwiązanie (i to może być bardziej elastyczne) - zrobić widoki Header i Footer i wtedy (znowu - phiend)

[php:1:4e23e0d6b9]<?php
Class ViewProduct extends Action
{

function Display()
{
$this->_callAction('header');

// tutaj inicjowanie modelu, zbieranie danych itp
// i następnie ich prezentacja

$this->_callAction('footer');
}

}
?>[/php:1:4e23e0d6b9]

Napisany przez: KaGe 13.05.2004, 23:27:38

Na phppatterns jest schemacik prezentuajcy MVC 2 i do tego jest śliczny kodzik źródłowy.

Mam pytanko w sprawie modelu (ProductModel) z tego kodu:
... a raczej kilka pytań:

1) Dlaczego ten model nie odpowiada pojedynczemu produktowi (wierszowi w tabeli bazy dancyh)?

2) ... można go napisać tak, żeby odpowiadał, ale wtedy możemy się pożegnać z listProducts - czyli wysłaniem żądania o kilka wierszy.... Jak sobie z tym poradzić

3) Czy można napisać taki model (np. articleModel) - który miałby też tablicę modeli np. CommentModel - i dzięki temu jakoś mógły sobie podporządkowywać Komentarze do samego siebie, dodawać usuwać itd...
np tak:
[php:1:7db2f59b24]<?php
Class Comment
{
var $data;
var $dao;

function Comment($dao)
{
$this->dao = $dao;

// Standardowa pusta tablica na dane - czy to doby pomysł?
$this->data[title] = "";
$this->data[body] = "";
}

function GetById($id)
{
$this->dao->query("SELECT * FROM comments WHERE id=".$id);
// i tu pojawia się kwestia : czy dać tu od razu, żeby uzupełnić całą pustą tablicę $data, czy też jakoś inaczej? - jakaś rada?
}

function cośtam?()
{
// i tu by sie przydało coś co wyciąga je po np. articleid
}

function ReturnComment()
{
// i teraz nie wiem czy dać
// return $this->data;
// czy też return $this->dao->GetRow();
// w zależności od rozwiązania, jak dam $this->data to mogę się pożegnać z późniejszym wykorzystaniem while($cośtam = $CommentModel->ReturnComment())
}
}

// i do tego klasa art
Class ArticleModel
{
var $dao;
var $data;
var $comments;

function ArticleModel() // tu wszystko po staremu
{
}

// KWESTIA OPISANA PONIŻEJ:

}

?>[/php:1:7db2f59b24]

Jak zrobić, żeby dało się tak przypisać klasie ArticleModel przynależność kolejnych Komentarzy w bazie, żeby ArticleModel zarówno odpowiadał artukułowi co jest w bazie jak i komentarzom, im przypisanym?

Wie ktoś może jak to rozwiązać?

O widoki nie pytam, bo to już w miare mały problem winksmiley.jpg

Napisany przez: marcin96 14.05.2004, 08:38:47

Cytat
Na phppatterns jest schemacik prezentuajcy MVC 2 i do tego jest śliczny kodzik źródłowy.

Mam pytanko w sprawie modelu (ProductModel) z tego kodu:
... a raczej kilka pytań:

1) Dlaczego ten model nie odpowiada pojedynczemu produktowi (wierszowi w tabeli bazy dancyh)?


Bo to jest tylko prosty przykład? snitch.gif)

Cytat
2) ... można go napisać tak, żeby odpowiadał, ale wtedy możemy się pożegnać z listProducts - czyli wysłaniem żądania o kilka wierszy.... Jak sobie z tym poradzić


Nalfein napisał artykuł o podstawach OOP i tam jest przykład, który myślę pomoże Ci snitch.gif)
http://php.pl/index.php/phppl/artyku_y/aplikacje_internetowe/architektura/oo_programowanie_obiektowe_w_praktyce/rozdzia_i_wprowadzenie/rozwi_zanie_obiektowe
Cytat
3) Czy można napisać taki model (np. articleModel) - który miałby też tablicę modeli np. CommentModel - i dzięki temu jakoś mógły sobie podporządkowywać Komentarze do samego siebie, dodawać usuwać itd...
np tak:
[..]
Jak zrobić, żeby dało się tak przypisać klasie ArticleModel przynależność kolejnych Komentarzy w bazie, żeby ArticleModel zarówno odpowiadał artukułowi co jest w bazie jak i komentarzom, im przypisanym?

Wie ktoś może jak to rozwiązać?


Artykuły nie muszą nic wiedzieć o komentarzach - po co? Jedynie przy usuwaniu artykułu przydałoby się automatyczne usuwanie komentarzy... ale tutaj może się przydać wzorzec observer - zerknij na www.phppatterns.com . Jeśli zaś chodzi o komentarze, to wystarczy znać id artykułu, a klasa Comments już będzie posiadać metodę getCommentsByAID.

Jeśli zaś chodzi o kod, to chyba w artykule Nalfeina znajdziesz odpowiedzi na pytania snitch.gif)

Napisany przez: KaGe 16.05.2004, 01:22:32

Mam problem. Chciałbym zapisywać i dodawać, szukać itd... dane w bazie na tej zasadzie, ze przekazuje nie Id, czy jakis jeden paramentr a cala tablice odpowiadajaca zawartosci danego modelu w bazie. czyli np:

ArticleModel i ArticleDataModel - gdzie ArticleDataModel jest obiektem generującym tablicę zawierającą dane artykułu. Później w ArticleData dodać metodę SaveByData($data), gidze $data to instancja ArticleDataModel i zawiera dane, które mają być zapisane. TAk samo z dodaniem. ArticleDataModel będzie mógł być tworzony bezpośrenio z formularza - co wy na to?
jak to rozwiązać?

Napisany przez: hawk 16.05.2004, 09:27:50

Nie rozumiem :? ArticleDataModel i ArticleModel mają odpowiadać obiektowi Article i kontenerowi artykułów? Sugerowałbym wywalenie tego Model z nazwy klasy, bo ono tam nie pasuje a nikt nie powiedział że klasa należąca do Modelu musi mieć to w swojej nazwie. Nazwa klasy powinna odzwierciedlać jej przeznaczenie i być prosta, jasna i oczywista.

Napisany przez: KaGe 20.05.2004, 14:59:58

Więc w takim razie przedstawie ten problem tak:

[php:1:22b83270b7]<?php
Class ArticleData
{
var $data = array(
art_id => null,
art_title => null
); // i tak dalej z całą resztą

function ArticleData($data=array())
{
foreach($data as $key => $value)
{
if ($data[$key] != "")
{
// tu następuje przepisanie danych z tablicy data - np. z formularza
// do tablicy tej klasy
$this->data[$key] = $data[$key];
}
}
}

function ReturnAsString()
{
$str = array();
foreach($this->data as $key => $value)
{
if (!is_numeric($value))
{
$value = "'$value'";
}
$str[] = "$key=$value";
}
return implode(" AND ", $str);
}
}

Class Article
{
// konstruktor itd...

function GetByData($data)
{
$this->dao->query("SELECT * FROM articles WHERE ".$data->ReturnAsString());
}
}

?>[/php:1:22b83270b7]


I teraz tak:
Article i ArticleData są właściwie wogóle nie związane - ArticleData jest tworzone np. tak, że jako argument podawana jest zawartość fomularza - klasa sama wie co ma sobie wziąć ;. ArticleData będzie tworzona w widokach i przekazywana do modelu Article jako argument dodawania, wyciągania z bazy itd...

Czy to jest dobre rozwiązanie? Może zaproponuje ktoś coś lepszego?

Napisany przez: hawk 20.05.2004, 18:49:22

Hmm, zaczynasz od końca... co nie jest jakąś szczególną krytyką bo to jest raczej powszechne.

Bo przedstawiasz kod, a kod dużo mówi na temat algorytmów i sposobu implementacji, a mało o projekcie i założeniach jakie system miał spełniać.

Po co są klasy Article i ArticleData? Nazwa ArticleData jest myląca, bo nie wiadomo czym to się różni od Article. Piszesz że nie są związane, a potem że ArticleData jest przekazywane do Article jako argument - to jest asocjacja, nawet jeżeli tylko <<uses>>.

Dyskusja na odpowiednio wysokim poziomie abstrakcji jest bardzo trudna i często nie kończy się niczym konkretnym. Ale dyskusja na nie zdefiniowanym poziomie abstrakcji jest jeszcze gorsza.

Jest różnica pomiędzy OOP a OOD, tak jak pomiędzy programowaniem a projektowaniem w ogólności, a wątek w końcu jest o wzorcu projektowym :wink: . Mam nadzieję że nie zamieszałem zbytnio biggrin.gif .

Napisany przez: KaGe 26.05.2004, 09:30:05

"Dyskusja na odpowiednio wysokim poziomie abstrakcji jest bardzo trudna i często nie kończy się niczym konkretnym. Ale dyskusja na nie zdefiniowanym poziomie abstrakcji jest jeszcze gorsza. " - chodzi mi tylko o to, czy takie przekazywanie danych jest wogoole przyjmowane za "poprawne" ? - jeśli jest to ok - będe tak pisał całą stronę, jeśli nie to trudno... - trzeba poszukać lepszego rozwiązania

Napisany przez: Balin 23.06.2004, 14:01:04

Ja mam pytanie o cos innego.
Wiadomo, ze niektore akcje moga zostac wykonane, jesli uzytkownik ma odpowiedni poziom (np. usuwanie newsow tylko przez admina) - jak to dobrze przeprowadzic w aplikacji wzorowanej na mvc ?
Czy sprawdzaniem poziomu uzytkowanika ma zajmowac sie kontroler, czy tez modul artykulow powinien zarzadac wiadomosci o poziomie usera ?

Napisany przez: gkeb 4.07.2004, 10:43:35

Ostatnio troche dumałem nad MVC i w związku z tym mam pytania. Zaznaczam że jestem w tym temacie poczatkujący biggrin.gif

1. Chodzi mi o przeplyw informacji między Kontrolerem Widokiem i Modelem. Zakładam, że każdy z nich to osobna klasa z czego Kontroler jest nadrzędny. Kontroler na podstawie danych z Inputa wywołuje odpowiednie metody z Modelu. Czy Model przekazuje dane zwrotne klasie Kontrolera czy bezpośrenio Widokowi?

2. Czy Model może samodzielnie pobierać dane (np. konfiguracji) z Kontrolera czy też lepiej w trakcie tworzenia klasy Modelu przez Kontroler wysłać wszystkie niezbędne dane potrzebne do pracy (login, hasło do db itp.)?

3. Rozumiem że Widok jest typu Output i nie powinien nic wysyłać do Kontrolera.

Na pewno namieszałem biggrin.gif

Napisany przez: Zepco 4.07.2004, 10:52:58

1. Z tego co ja już zdążyłem się zorientować, to np. w przypadku wyświetlania kontroler wywołuje widok, który wyciąga dane z modelu i "wyrzuca" je na wyjście.

3. Widok może wysłać do kontrolera żądanie wywołania innej akcji, ale nie powinien mieć wpływu na zmianę danych w modelu i kontrolerze.

Napisany przez: rmn 15.07.2004, 22:10:03

kurcze od jakiegos czasu probuje dowiedziec jak 'to' robic w mvc;) Zaczelo sie od artykuly na php.pl. Potem napisalem nawet sporo kodu w oparciu o to co zrozumialem. Nie wiem tylko jak zweryfikowac to czy to co napisalem faktycznie mozna opatrzec etykietka mvc... Jest tak dlatego, że

każdy pisze coś innego ohmy.gif

Jedni twierdza ze pewne rzeczy powinien robic kotroler inni ze nie; ze model(instancja) powiniene byc przekazywany jako parametr do widoku, inni ze absolutnie nie tak itd... Generalnie widze same sprzecznosci i dochodze do wniosku ze tak naprawde idea mvc jest bardzo ogolnym spojrzeniem na zagadnienie projektowania aplikacji i nie dostarcza konkretnych rozwian do wielu problemow tutaj poruszanych:/ a ew dywagacje na te tematy wprowadzaja straszne zamieszanie?

czy ktos ma podebne odczucia?

Napisany przez: Ozzy 16.07.2004, 11:10:33

MVC jest dobre, ale....w Javie:) Przykład: Swing, widok zmienia się w zależności od platformy lub "wyglądu i wrażenia". Sterowniki przechwytuje zdarzenia, a model przechowuje dane komponentu. W takim przypadku stosowanie MVC wydaje się uzasadnione, jednak w php, gdzie każda dodatkowa klasa wydłuża czas generowania strony, próby używania MVC na siłę, tylko po to, by być "trendy" wyraźnie mija się z celem. Może niektórym nie spodoba się to co napisałem, jednak taka jest moja opinia na dzień dzisiejszy:)

Napisany przez: Ace 16.07.2004, 11:21:29

Tak, tez mam takie wrazenie. Wyszedlem z zalozenia ze MVC [ model view controler ] mozna bardziej luzno potraktowac. Jesli ty piszesz swoj MVC, to zapewne bedziesz mial w planie rozszerzac jego mozliwosci, a wiec to na ogol ty bedziesz go pisal/rozszerzal. Wiec na poczatku wychodzisz z glownego zalozenia, musi byc MODEL, WIDOK , i KONTROLER tego wszystkiego. Reszta wedlug mnie to kwestja sporna. Fakt, ze Widok nie powinien edytowac danych, tylko je wyswietlac, nie ma nic wspolnego z tym, ze nie moze zarzadac zmiany danych przy Modelu. Teraz tez pisze aplikacje na podstawie zalozen MVC, najgorszy jest pomysl. Siedze juz dluzszy czas przy kontrolerze, zeby wyszedl elastyczny/latwy do edycji, modyfikacji... Dlatego skupie sie dluzej na kontrolerze... Pozniej Model, oraz glowne zalozenia, jakie maja spelniac akcje, prawa dostepu/autoryzacjia... I widok. Calosc nastepnie trzeba rozszerzac o dodatkowe moduly/akcje.

Napisany przez: gkeb 25.07.2004, 23:01:49

Tak sobie dumam i dumam i.... :

koncepcja 1:
1.wywolany jest index.php;
2.index uruchamia klase kontroler wraz z wszystkimi parametrami (dane z adresu URL, i inne potrzebne);
3.Kontroler przekazuje informacje do klasy modelu w celu wykonania odpowiedniej akcji z danych pobranych z kontrolera(informacje dla akcji jak i do przekazania widokowi);
4.model przesyla wynik do klasy widoku wraz z danymi niezbednymi do wyswietlenia a uzyskanymi od kontrolera;
5.widok generuje odpowiedni szablon z danymi z modelu.

koncepcja 2:
1.wywolany jest index.php;
2.index uruchamia klase kontrolera wraz z parametrami
3.Kontroler przekazuje niezbedne informacje (tylko i wylacznie dane potrzebne do uzyskania danych z modelu) klasy modela w celu wykonania odpowiedniej akcjii z danych pobranych z kontrolera;
4.model przesyla wynik do klasy kontrolera;
5.kontroler przekazuje dane do widoku (te uzyskane z modelu jak i inne wymagane do poprawnego wyswietlenia)
6.widok generuje odpowiedni szablon z danymi z modelu.

czy ktoras z tych koncepcji jest prawidlowa?? czy moze jeszcze inaczej to powinno wygladac?
wiem ze pewnie namieszalem ale czlowiek stale sie uczy smile.gif ciagle sie uczy

Napisany przez: marcin96 25.07.2004, 23:57:46

Żadna nie jest ;>)

1. index[*] odpala kontroler
2. kontroler sprawdza sobie url, parametry itp i na tej podstawie odpala akcje (wcześniej moża wrzucić jakieś sprawdzanie autoryzacji i praw dostepu do danej akcji)
3. akcja operuje na klasach modelu niezależnych[**] od widoków, akcji, kontrolera...
4. wynik wykonania akcji przekazywany jest do widoku
5. na podstawie danych z akcji widok wypluwa wynik na ekran/ przesyla gdzies indziej xml itp

[*] nie musi być tylko jeden 'wyzwalacz' kontrolera.. można zrobić kilka wyzwalaczy, każdy będzie operował na tych samych bibliotekach itd, ale dzięki temu można zrobić kilka różnych wersji konfiguracji - rozbicie aplikacji na mniejsze, niezależne od siebie/mniej zależne od siebie

[**]dlaczego podkreśliłem niezależnych? Dzięki temu gdy w przyszłości będziemy chcieli zmienić framework obsługujący aplikację modelu nie będziemy musieli nawet ruszać.. i w drugą strone - jeżeli mamy już jakiś gotowy model, a chcemy 'ożywić' go za pomocą MVC, to właśnie ta separacja pozwala nam bezproblemowo to uczynić.

Zależności między widokami/kontrolerem/akcjami i częscią autoryzującą wykonanie akcji/widoku oraz jak odseparować to od modelu.. to już inna bajka, zostało to całkiem fajnie poruszone w temacie 'jak pisać jądro...': http://forum.php.pl/index.php?showtopic=13770

Napisany przez: gkeb 26.07.2004, 16:11:51

Hehe smile.gif
Wiedziałem ze sie myle smile.gif

W mojej koncepcji chcialem by wszystko bylo wprowadzone do kontrolera jako parametry by potem juz ani kontroler ani model ani widok nie korzystaly z tablic GLOBAL. Czy to ma sens?
Zastanawia mnie koncepcja wielu kontrolerów. Jakby to miało wyglądac?
Jeżeli chodzi o akcje to też sobie podobnie wymyśliłem, tzn.: sam model to klasa ktora jest interfejsem wywołującym konkretną akcje (każda akcja to osobna klasa w osobnym pliku).Czy tak może być?

Napisany przez: hawk 26.07.2004, 21:12:51

Oczywiście że model nie powinien korzystać z żadnych globalnych tablic, bo nie ma tam nic co mogłoby być mu potrzebne. Natomiast ciekawe jak napiszesz kontroler który w ogóle nie rusza tablicy $_POST, chociażby bo to aby gdzieś przepisać jej zawartość tongue.gif .

Po co ci wiele kontrolerów? Chyba że mówimy o Page Controller, ale MVC raczej operuje na jednym, centralnym kontrolerze.

Jeżeli chodzi o model i akcje to ni <męski narząd moczowo-płciowy> nie mogę nic z tego wyrozumieć. "model to klasa ktora jest interfejsem wywołującym konkretną akcje"? Klasa nie jest interfejsem, to raz. Dwa, że obiekt modelu absolutnie nie powinien wywoływać metody obiektu akcji. Jak by to miało wyglądać? No chyba że mówimy o listenerze w Smalltalku/Swingu, ale to inny MVC niż w php i raczej nie o to nam chodzi biggrin.gif .

BTW, dlaczego z MVC jest tyle zamieszania? Mi się wydaje że to bardzo naturalny sposób tworzenia aplikacji, i jakby nie był wymyślony, to i tak ludzie sami z siebie by do tego doszli blink.gif .

BTW2, Marcin wyrasta nam na eksperta od MVC, który nie tylko wie co i jak ale i potrafi to łopatologicznie wyjaśnić biggrin.gif

----------------------------------------
Grr, dlaczego nie mogę dać 2 odpowiedzi pod rząd? aaevil.gif
@Ozzy:
IMHO to nie tak. MVC w Swingu sporo różni się od tego w php, bo inny jest model interakcji. Więcej, MVC w Swingu różni się od tego w JSP i Struts, z takich samych powodów.
Natomiast używanie MVC na siłę oczywiście jest stratą czasu. Zwłaszcza w php gdzie wczytywanie kolejnych klas jest tak popieprzone jak jest. php na ogół stosowane jest do prostych serwisów. Serwisy banków już raczej w JSP. Dlaczego? Bo php jest zbyt prymitywny do tego celu. Jeżeli php dalej ma się rozwijać do Personal Home Page, to nie ma problemu, można sobie zlać MVC, wzorce i w ogóle wszystko to co wprowadzili w PHP5 bo bez tego też się da. Ale całe te zmiany idą (chyba) w kierunku uczynienia z php dobrego języka na poziomie "enterprise". I wtedy Smarty przestaje wystarczać, i trzeba pomyśleć np. o modyfikowalności itd.

Napisany przez: gkeb 26.07.2004, 22:24:39

Co do wielu kontrolerow to zauwaz ze to Marcin wlasnie napisal a ja stwierdzilem ze jest to do przemyslenia aaevil.gif
Co do modelu i akcji to chyba nie zakumalem od razu i dopiero teraz do mnie dotarlo smile.gif W poprzednim rozumowaniu (dodam ze blednym smile.gif ) uznalem ze kontroler wywoluje model a dopiero ten wywoluje odpowiednia akcje - zakladalem ze jest jeden model, wiele akcji. Prawidlowo to jest tylko jeden kontroler a wiele modeli i tu tkwi moj blad (zgadza sie??)
Co do zamieszania przy MVC to zauwaz ze kazdy jakos inaczej pisze i jak ktos dopiero zaczyna zabawe z tym (tak jak ja) to moze sie troche pogobic.

Napisany przez: hawk 27.07.2004, 11:00:25

Z tymi wieloma kontrolerami to Marcin raczej pisał (IMHO, nie chcę nic imputować) o wielu konfiguracjach. Nie możesz odpalić na raz dwóch kontrolerów, ale możesz mieć kilka wersji konfiguracji, albo kilka aplikacji na jednym serwerze, itd.

Co do modelu, to generalnie jest takie permanentne zamieszanie. Bo co to jest model? Zbiór klas. Więc co to znaczy "wywołać model"? No nie wiadomo. O ile kontroler jest pojedynczym obiektem i może coś wywoływać, o tyle w przypadku modelu możemy mówić o konkretnym obiekcie należącym do modelu, który coś robi. A cały model to logiczna część aplikacji a nie jakaś fizyczna rzecz. Więc nawet nie ma sensu mówić że jest "jeden model" lub "wiele modeli". To tak jak jedna pamięć/wiele pamięci, jedna policja/wiele policji, itd. Bez sensu. Niepoliczalne. Klasy modelu już są policzalne.

Jak dla mnie, to w tych dyskusjach nad MVC ciągle są wątpliwości co do szczegółów, a brakuje jakby zrozumienia idei. Że chodzi o sensowne zaplanowanie aplikacji i nieważne czy jest "jeden model", czy 50, ale ważne że sterowanie idzie od kontrolera do modelu a nie w drugą stronę. Bo inaczej to nie ma sensu. Takie rzeczy jakoś mało się rzucają w oczy w php. Znacznie bardziej w zwykłych, okienkowych aplikacjach. MFC jest oparte o MVC, AWT i Swing też. Spróbuj zrobić aplikację na chociaż kilkanaście tysięcy linii kodu bez separacji dokumentu od widoku. Wychodzi z tego wielki syf który nie wiadomo jak działa i dlaczego w ogóle działa. A w php jakoś się daje sklecić system, wydajność jest ważniejsza od jakości i nie czuć tych problemów.

Napisany przez: marcin96 27.07.2004, 11:30:50

Cytat(hawk @ 2004-07-27 11:00:25)
Z tymi wieloma kontrolerami to Marcin raczej pisał (IMHO, nie chcę nic imputować) o wielu konfiguracjach. Nie możesz odpalić na raz dwóch kontrolerów, ale możesz mieć kilka wersji konfiguracji, albo kilka aplikacji na jednym serwerze, itd.

otototo.. wiele wyzwalaczy kontrolerów, a nie wiele kontrolerów.. czyli np możesz mieć powiedzmy trzy wyzwalacze:

sklep.php
hurtownia.php
costamjeszcze.php

...wszystko będzie działało na tych samych klasach, ale będą inne konfiguraje odpalone. Tutaj mamy jedną witrynę podzieloną na trzy niezależne aplikacje korzystające z tych samych klas/bibliotek etc. Po co osobne konfiguracje? A po co hurtownia ma wiedzieć jakie są akcje dostępne w sklepie oraz na odwrót?

Oczywiście nie we wszystkich przypadkach jest sens tak robić... ale czasem takie myślenie może się przydać (np: gdy korzystając z phienda zaczyna nam się konfig niebezpiecznie rozrastać ;>)) )

Cytat
BTW2, Marcin wyrasta nam na eksperta od MVC, który nie tylko wie co i jak ale i potrafi to łopatologicznie wyjaśnić


A tam.. po prostu uważnie prześledziłem manual phienda ;>)P

Napisany przez: aleksander 30.10.2004, 15:07:53

witam,

więc bez zbędnych wstępów parę pytań:

1. nie wiem czy dobrze rozumuje: model to czesc programu, ktora jest posrednikiem pomiedzy DB a widokiem/akcja. wykonuje ona zapytania, wstawia dane i je zwraca ( w czystej postaci). dobrze rozumuje??

2. czy dla skryptu forum (ktory wlasnie chce zaprojektowac w oparciu o MVC) cos takiego bedzie poprawne:

a) dla wyswietlenia tematow

- kontroler ustala, ze przegladarka chce zobaczyc topiki. wywoluje widok 'showforum($forumid)'
- widok wywoluje model 'showforum($forumid)' ktory zwraca dane z bazy danych w czystej postaci (tablica)
- widok obrabia te dane, i przekazuje wynik do szablonow

cool.gif dla wstawienia postu

- kontroler ustala ze przegladarka chce dodac posta. wywoluje akcje 'addpost'
- akcja wywoluje model 'addpost' ktory tylko robi polecenie insert i zwraca, czy udalo sie wstawic posta
- ta sama akcja po udanym wstawieniu wywoluje widok 'showtopic($topicid)'
-widok wywoluje model 'showtopic($topicid)' ktory zwraca dane z bazy w czystej postaci (tablica)
- widok obrabia te dane i przekazuje je do szablonow (smarty)

3. zamierzam wszystkie metody (nawet takie standardowe jak showtopic, showforum itp) umiescic jako moduły. Czyli taki moduł powinien składać się z modelu i widoku/akcji ?

Napisany przez: bela_666 30.10.2004, 15:18:47

Cytat
1. nie wiem czy dobrze rozumuje: model to czesc programu, ktora jest posrednikiem pomiedzy DB a widokiem/akcja. wykonuje ona zapytania, wstawia dane i je zwraca ( w czystej postaci). dobrze rozumuje??


to o czym myslisz to raczej DAO

Cytat
2. czy dla skryptu forum (ktory wlasnie chce zaprojektowac w oparciu o MVC) cos takiego bedzie poprawne:

a) dla wyswietlenia tematow

- kontroler ustala, ze przegladarka chce zobaczyc topiki. wywoluje widok 'showforum($forumid)'
- widok wywoluje model 'showforum($forumid)' ktory zwraca dane z bazy danych w czystej postaci (tablica)
- widok obrabia te dane, i przekazuje wynik do szablonow


- kontroler wywołuje akcje showtopic
- akcja wywołuje model
- widok odpowiada za wyswietlanie np. Smarty

Cytat
3. zamierzam wszystkie metody (nawet takie standardowe jak showtopic, showforum itp) umiescic jako moduły. Czyli taki moduł powinien składać się z modelu i widoku/akcji ?


moduł to raczej logiczny zbior akcji

Napisany przez: matid 30.10.2004, 15:54:58

A czy taki przebieg pracy aplikacji jest zgodny z modelem MVC?

Tak w zasadzie wygląda moja koncepcja. Jak widać nie ma jednej klasy Widoku, jest ich wiele, natomiast Model i Kontroler jest tylko jeden.
Oczywiście to jest prosty przykład, bez żadnych łańcuchów, ale chciałbym wiedzieć, czy ta idea jest dobra, a jeśli nie to co w niej wymaga poprawienia.

Napisany przez: aleksander 30.10.2004, 18:25:26

ale teraz wywiązuj się pytanie: jeżeli dodam nową funkcjonalność do aplikacji (powiedzmy wyświetlanie userów) to oprócz widoku, który przetwarza dane z modelu, musze także dodać model odpowiedzialny za wyciągnięcie odpowiednich danych z bazy i przekazanie w czystej postasci widokowi. czy tak?

Napisany przez: ActivePlayer 30.10.2004, 21:03:23

Nie wiem czy moja idea jest dobra ale czy mozna najpierw pobrac dane z GET POST i SESSION, potem wg nich stworzyc lancuch akcji a potem w petli while je wykonac questionmark.gif oczywiscie ostatnią akcją byłoby wyswietlenie odpowiedniego widoku ...questionmark.gif

Napisany przez: matid 30.10.2004, 21:29:47

Cytat(Olo @ 2004-10-30 19:25:26)
ale teraz wywiązuj się pytanie: jeżeli dodam nową funkcjonalność do aplikacji (powiedzmy wyświetlanie userów) to oprócz widoku, który przetwarza dane z modelu, musze także dodać model odpowiedzialny za wyciągnięcie odpowiednich danych z bazy i przekazanie w czystej postasci widokowi. czy tak?

Nie. W moim rozumowaniu model dostaje od widoku zapotrzebowanie na jakieś dane. Pobiera te dane i wzraca je widokowi. Niezależnie od tego jakie zadanie ma wykonać akcja Model pozostaje ten sam i służy za pośrednik pomiędzy aplikacją a źródłem danych. Takim źródłem danych może być baza danych obsługiwana przez klasę abstrakcji.

Prosiłbym o wypowiedź kogoś obeznanego w tych tematach i o poprawienie moich ew. błędów w rozumowaniu.

Napisany przez: aleksander 30.10.2004, 21:43:19

no tak, ale jeżeli nowy widok bedzie kozystal z nowej tabeli w db to skad model ma o niej wiedziec, a jak ma stworzyc odpowiednie zapytanie zwracajace odpowioednie dane?

Napisany przez: dag 30.10.2004, 22:32:32

ArticleModel:
- dodaj
- edytuj
- usun
- get title
- get author
- get body



ArticleView:
pobiera z modelu ArticleModel -> get title, get author, get body, formatuje i wyswietla


AddArticleAction:
dodaje za pomoca ArticleModel -> dodaj

W ten sposób mamy obiektowość. Można by było zrobić każdą metodę ArticleModel jako osobny model ale po co??

Co sądzicie?

Napisany przez: hawk 31.10.2004, 20:55:35

@ogólnie:

Nie ma sensu zastanawiać się, czy model jest jeden, dwa czy dwadzieścia. Model to tylko warstwa. To tak jakby mieć dwie warstwy bazy danych. Można mieć dwie bazy danych, ale obie należą do warstwy bazy danych. Masłomaślanizm powyższego dowodzi, że mówienie o modelach jest bez sensu.

Ja jestem przeciwny jakiemuś akcentowaniu w nazwach itd. że mamy do czynienia z modelem. Po prostu klasy Article, User, itd. Cała zabawa polega przecież na tym, żeby model był odseparowany od HTTP i innych okropności. Żeby był to ładny, elegancki projekt obiektowy (OOD), bez zawiłości protokołów, sesji, itd. Więc nie żadne $model->getData(), nie żadne metody modelu, tylko po prostu $articleContainer->getArticleById(12345) itd.

A nazywanie klasy ArticleModel jest niekorzystne z tego powodu, że skoro model jest odseparowany od całej reszty, to też nie wie nic o kontrolerze i o MVC. Jak tworzę klasę do artykułów, to nazywam ją Article. Jak tworzę klasę do artykułów w aplikacji MVC, to powinienem postępować tak samo jak poprzednio. W końcu o to chodzi w MVC.

@dag:

To już zagadnienie nie MVC, tylko ogólnie OOD, ale podane przez ciebie metody do Article(Model) są złe. Tzn nie złe z punktu widzenia modelu, tylko złe z punktu widzenia hierarchii klas. Jeżeli są sobie artykuły, to logiczne jest, że potrzebuję klasy Article. Ale potrzebuję też kontenera artykułów. Inaczej się nie da tego sensownie zrobić. Jeżeli mam zbiór artykułów (a przecież mam), to ten zbiór musi być "czymś", czyli musi mieć obiekt. A jak obiekt to i klasa. Kontener. Na tym etapie też robi się tzw. projekt trwałości, czyli po ludzku zaznacza, co siedzi w bazie danych (artykuły). I kontener je wyciąga.

Napisany przez: Vengeance 31.10.2004, 21:11:30

hmm no tak w MVC nigdy nie wnikalem ale teraz moje podstawe pytanie nie odnosi sie w sumie tylko do MVC.

jeden Artykul obrazuje klasa Article powiedzmy

  1. <?php
  2.  
  3. class Article
  4. {
  5.  var $author, $title, $content;
  6. }
  7.  
  8. ?>


Teraz hawk mowisz o kontenetrze. Czyli on trzyma kolejne instancje klasy Article (czyt. kolejne artykuly). Pytanie on trzyma wszyskie arty czy np. tylko 10 (bo powiedzmy porcjowanie wynikow na www jest co 10 artow). I czy pobieranie do niego danych polega na tym
ze z bazy sql pobieramy wszystkie rekordy, w petli tworzymy kolejne obiekty klasy Article uzupelniajac je danymi a potem wkladamy je w ten kontener. Chyba zle to rozumiem bo to zbyt ergonomiczne nie jest ;]

Napisany przez: hawk 2.11.2004, 09:29:23

Zaczynamy od tego, że mamy ten Article tak jak w twoim kodzie. Wyszukiwanie artykułów nie jest zadaniem dla samego artykułu, więc potrzebujesz coś do tego. Kontener. Manager. Jak zwał tak zwał. Nie chodzi o to, żeby ten kontener trzymał 10 czy 100 artykułów, tylko żeby umożliwiał do nich dostęp. A to, że artykuły są w bazie, i że jest jakiś SQL, to jest jego wewnętrzna sprawa.

Pewnie, może sobie wszystkie wczytać i przechowywać, ale to będzie mało wydajne.

Popatrz na to z punktu widzenia MVC. Nie możesz do akcji wrzucić zapytania SQL, które wyciąga artykuły, bo to jest Model. Więc gdzieś to zapytanie musi się znajdować, i to najlepiej w jednym miejscu. Nie może znajdować się w klasie Article, bo musiałbyś stworzyć artykuł a potem go wyciągać - masło maślane. No chyba że w metodzie statycznej, wtedy klasa Article pełni podwójną funkcję. Więc potrzebujesz osobną klasę która potrafi wyciągać artykuły.

Dobrze jest sobie popatrzyć na dostępne systemy DAO, takie jak Turbine/Propel etc. Chociaż tam akurat rozwiązali to poprzez metody statyczne.

Napisany przez: bela_666 8.11.2004, 22:39:22

hm dzis sobie w szkole myslałem o mvc i narysowałem taki oto "projekt"

Kod
           |-----------|
           | 2.Router  |
           |-----------|
              |    |
          3.  |    | 1.
              |    |
           |-----------| 10.|----------|
           | Kontroler |--->|  Widok   |
           |-----------|    |----------|
              |    |
           4. |    | 9.
              |    |
           |-----------|
           | 8.Akcja   |
           |-----------|
              |    |
           5. |    | 7.
              |    |
           |-----------|
           |   Model   |
           |-----------|
              |    |
              |    |
              | __ |
              6.DB

1. Kontroler odwołuje się do Router
2. Router parsuje URL i wyciąga z niego nazwe akcji
3. Nazwa akcji jest przekazywana do Kontrolera
4. Kontrole wywołuje akcje
5. Akcja odwołuje się do Modelu
6. Model odwołuje się do DB
7. Model zwraca dane
8. Akcja operuje na danych z Modelu
9. Akcja zwraca przetworzone dane do Kontrolera
10. Kontroler wywołuje Widok
11. Widok zwraca dane do USER_AGENTa

Niech ktoś skoryguje błedy winksmiley.jpg

I teraz mam pare pytań:
1. Dotyczy punktów od 9. wzwyż, czy dan są przekazywane przez Kontroler do Widoku czy bezpośrednio z Akcji ?
2. Gdzie są trzymane dane o akcjach ( we Phiendzie w pliku XML, ale jaka jest sensowna alternatywa )
3. Jak są generowane linki dry.gif
4. Jeżeli dane są przesyłane przez Kontroler do Widoku, to w jakiej formie no przepływają ?
5. Jak sensownie rozwiązać kwestie szablonów ? Wiadomo, że szablon dla artykułów różni się od szablonu forum
6. @hawk skąd ty brałeś informacje winksmiley.jpg

Napisany przez: hawk 9.11.2004, 09:33:31

1. Ja bym to zrobił tak, że Widok może dostać dane bezpośrednio od Modelu. Tzn normalnie pobiera dane. Pamiętając o tym, że nie wolno mu niczego modyfikować, ale nie da się tego wymusić przez jakieś zabronienie dostępu.

2. Hmm, gdzie? Można w pliku ini. Można w wielkiej tablicy php (np. phrame). Można mieć wszystko hard-coded w kodzie akcji (np. mojavi). Nie widziałem jeszcze sensownego systemu, gdzie to wszystko siedziałoby w bazie danych, ale jest to niegłupie rozwiązanie - ułatwia zarządzanie akcjami.

3. Jak chcesz. To jest niezależne od MVC. Ale po to wymyślałem router, żeby był obiekt odpowiedzialny za tworzenie linków winksmiley.jpg

5. -

6. Szablony są niezależne od MVC. Klasa Widoku to w końcu tylko klasa. Jaki szablon ma w środku, to już jej sprawa, i reszcie aplikacji nic do tego.

7. Jestem genialny tongue.gif. Serio, w sumie to nie wiem. phparchitect. sitepoint. phrame. Polecam też materiały Suna i Microsoftu na temat MVC i takich. Oni to mają trochę lepiej uporządkowane.

A router to wyszedł tak sam z siebie, i nie ma go ani w Javie, ani w .NET.

Napisany przez: DeyV 9.11.2004, 09:55:15

Cytat
Ja bym to zrobił tak, że Widok może dostać dane bezpośrednio od Modelu.

Ja zazwyczaj komunikację pomiędzy modelem a widokiem sprowadzam do tego, że w akcji pobieram jakieś dane z modelu, które przesyłam do widoku, który je jakoś iteruje i wyświetla.
Skoro jednak w php5 mamy swietną obsługę iteratorów, pozwalającą na pełną symulację tablicy przy pomocy obiektu, to często najlepszym sposobem, jest właśnie pobranie od modelu iteratora (który w sumie również jest częścią modelu) i przesłanie go do widoku.
Oczywiście - dzięki temu zyskujemy nie tylko wydajność - (zamiast przechowywać dane w tablicach, można je "na żywo" pobierać z bazy), ale również upewniamy się, że widok nie będzie nam w żaden sposób 'wpływał' na model.

Cytat
Ale po to wymyślałem route

heh - Ty go tylko ładne nazwałeś winksmiley.jpg
Patern pozwalający na pobieranie nazwy wykonywanej akcji z adresu jest jednak chyba nieco starszy niż phiend...

Napisany przez: hawk 9.11.2004, 10:49:26

@DeyV: ale phiend wcale nie ma routera. Ba, nie znam żadnego obecnie funkcjonującego frameworka, który ma router. Owszem, wszędzie przejawia się koncepcja, że z URLa trzeba wyciągnąć nazwę akcji, i jakiś kawałek systemu się tym zajmuje. Niektóre systemy dają tutaj kilka możliwości (index.php?page=foo, index.php/foo, itd). Np. phiend daje kilka możliwości.

Ale nie o to chodzi. Chodzi o to żeby wywalić tą funkcjonalność poza kontroler. Zrobić takie MVCR. I to mi daje dużą elastyczność bo mogę router wymieniać nie ruszając reszty systemu.

A co do wymyślania i nazywania - w sumie to bez znaczenia. I tak nikt routera nie patentuje biggrin.gif.

Napisany przez: Vengeance 9.11.2004, 14:17:48

to moze trzeba opatentowac smile.gif bill ci opatentowal podwojne klikniecie to i my mozemy tongue.gif

Napisany przez: bela_666 9.11.2004, 16:51:40

Cytat
1. Ja bym to zrobił tak, że Widok może dostać dane bezpośrednio od Modelu. Tzn normalnie pobiera dane. Pamiętając o tym, że nie wolno mu niczego modyfikować, ale nie da się tego wymusić przez jakieś zabronienie dostępu.


no to już całkiem się zakręciłem winksmiley.jpg

jezeli dane są bezpośrednio wysyłane z Modelu do Widoku to jaki sens akcji ?

Napisany przez: dag 9.11.2004, 17:12:40

bela_666 @ przeczytaj dokładnie artykuł o MVC na php.pl.

Akcja to np. dodawania usera, usuwanie artykułu.

Widok wyświetla, jak sama nazwa wskazuje czyli to co widzimy ;-). Wytłumaczone łopatologiczne, tak na chłopski rozum ;-) lepiej masz wszystko opisane w artykule.

Napisany przez: bela_666 10.11.2004, 18:56:30

Cytat(dag @ 2004-11-09 18:12:40)
bela_666 @ przeczytaj dokładnie artykuł o MVC na php.pl.

Akcja to np. dodawania usera, usuwanie artykułu.

Widok wyświetla, jak sama nazwa wskazuje czyli to co widzimy ;-). Wytłumaczone łopatologiczne, tak na chłopski rozum ;-) lepiej masz wszystko opisane w artykule.

przeczytałem, przeanalizowałem i znalazłem błąd smile.gif

z tego co zrozumiałem jezeli dane sie nie zmieniają / są tylko pobierane to akcje nie istnieją, jeżeli są jakies operacje na danych to w gre wchodzą akcje, w drugim miejscu jest napisane że model jest odpowiedzialny za zmiene danych, pogubić się można dry.gif a wiec jak są rozróżniane zapytania wymagające i nie wymagające akcji ?

Napisany przez: aleksander 10.11.2004, 18:58:18

zapytania nie wymagające akcji: SELECT
zapytania wymagające akcji: UPDATE, INSERT

biggrin.gif:D:D

Napisany przez: hawk 11.11.2004, 09:34:32

@Bela:

Lepiej nie mówmy o zapytaniach, bo w MVC wcale nie musi być bazy danych. A zwłaszcza nie powinno być tego widać w akcjach i w Widoku.

W moim artykule był taki ładny schemat działania MVC, ale chyba się nie wyświetla sad.gif.

Powinno być tak:

1) Zawsze uruchamia się akcja, która robi wszystkie zmiany w Modelu (addUser, deleteUser, modifyUser, blah, blah).
2) Akcja zawsze podaje, jaki widok uruchomić
3) Zawsze uruchamia się widok, który wyciąga z Modelu potrzebne dane i wyświetla je, bez zmieniania niczego

Czyli w najprostszym przypadku (tylko wyświetlamy coś) akcja nic nie robi, poza wskazaniem widoku. Inna sprawa, czy chce nam się robić klasy dla takich jednolinijkowych akcji, ale tak wygląda oficjalny MVC. Zawsze jest akcja - widok. Tak więc nie ma żadnego rozróżniania zapytań wymagających i nie wymagających akcji. Zawsze jest akcja, a jak ta akcja nic z siebie nie robi, to już jej sprawa.

Tak na marginesie, w phiendzie zrobiłem tak że w zdegenerowanym przypadku bez żadnych modyfikacji można przejść od razu do widoku, bez wywoływania "pustej" akcji. Tylko że to się nazywało "logic action" i "view action". Tak też można, ale ze świadomością, że naginamy wzorzec żeby poprawić wydajność.

Napisany przez: bela_666 12.11.2004, 00:00:03

Cytat(hawk @ 2004-11-11 10:34:32)
Lepiej nie mówmy o zapytaniach, bo w MVC wcale nie musi być bazy danych.  A zwłaszcza nie powinno być tego widać w akcjach i w Widoku.

W moim artykule był taki ładny schemat działania MVC, ale chyba się nie wyświetla sad.gif.

1. wiem, ze nie musi byc to baza

2. na szczescie jest wersja pdf winksmiley.jpg ale słaba jakosc obrazkow tam jest

3. dzieki hawk za rozjasnienie wszystkiego smile.gif

Napisany przez: aleksander 15.11.2004, 15:14:00

ok to mi jeszcze ukazał się taki oto problem:

wyobraźmy sobie, że robię silnik/cms oparty na mvc. Na stronie opartej o taki skrypt może być jednocześnie potrzebnych kilka widoków np. widok newsow, widok menu, widok stopki i Bóg wie jeszcze czego. A jak wiadomo widok musi być ostatni - więc jak wywoływać te poszczególne widoki? Ja pomyslałem nad kolejką ale co wy o tym sądzicie?

Napisany przez: hawk 15.11.2004, 16:47:21

Hmm, są dwie zasady:

1. Widok powinien być jeden.
2. Jeżeli potrzebujesz więcej widoków, patrz punkt 1.

biggrin.gif

Tak naprawdę jest. Żaden wzorzec nie jest idealny i MVC po prostu nie podejmuje tematu: co zrobić jak chcemy mieć wspólne menu itd. I nie musi. Zauważ że nic ci nie zabrania includować w klasie widoku wspólnego szablonu menu. Oczywiście, wspólny szablon menu wymaga też wspólnego kodu który stworzy to menu i podstawi odpowiednie wartości. Ale ten sam problem miałbyś ze zwykłymi skryptami, które korzystają z szablonów i też muszą jakoś współdzielić kod. MVC ani tutaj pomaga ani przeszkadza.

Może trochę jednak ułatwia, bo mamy klasę widoku, więc możemy jakoś sobie dziedziczyć, np. ArticleView extends ViewWithMenu itd. Możesz wpychać to co wypluwa klasa widoku w jakieś headery/footery generowane przez inną klasę. Jest pole do popisu winksmiley.jpg.

BTW nie mówimy "widok stopki", tylko raczej "klasa wyświetlająca stopkę należąca do warstwy widoku". Podobnie jak bez sensu jest mówić "model artykułów".

Napisany przez: hamlecik 17.12.2004, 11:15:45

Witam,

Mam taki maly OT. Otoz stworzylem sobie ostatnio cos na wzor MVC. Jest to bardzo prosta aplikacja, wyswietlanie listy userow i wyswietlanie danych jednego usera. Idea jest prosta. Wywoluje kontroler w zaleznosci od tego jaka wartosc przyjmuje zmienna $_GET['show'], kontroler wywoluje widok, widok pobiera dane z modelu i wyswietla strone.

Jednak moje rozwiazanie jest malo elastyczne poniewaz kazda akcja ma "swoje pliki".

np wylistowanie userow:

UsersController
UsersModel
UsersView

wyswietlenie danych jednego usera:

UserController
UserModel
UserView

Problem pojawia sie np jak bym dodal jeszcze inne funkcje do tej aplikacji, wtedy bym zginal w gaszczu plikow winksmiley.jpg

1) Myslalem, zeby zrobic jeden kontroler, wtedy kazda akcja, miala by tylko plik modelu i formatowana przez Smarty strone. Ale jak to zrobic?

2) Chcialem jeszcze zrobic "glowny" kontroler. Byl by to trzon aplikacji. Jego zadaniem bylo by wywolywanie "malych kontrolerow", ktore mialy by okreslone zadania np kontroler userow, kontroler newsow.

Przyklad:

Kod
"Glowny" kontroler -> "maly" kontroler

   modul newsow    -->  wyswietlanie newsow
                            |->  wyswietlanie konkretnego newsa
                            \->  kasowanie newsa itd itp


Niestety znowu moja ograniczona wiedza (albo brak wiary?) nie pozwala mi tego osiagnac. Byl bym bardzo wdzieczny gdyby ktos chcial ze mna podyskutowac na ten temat.

Napisany przez: Ludvik 17.12.2004, 12:35:45

Kontroler z natury tego wzorca jest jeden.

Cytat
Wywoluje kontroler w zaleznosci od tego jaka wartosc przyjmuje zmienna $_GET['show']

To raczej kontroler powinien się zajmować tym, to on powinien wiedzieć którą akcję uruchomić. W katalogu BluePrints jest ładnie napisane: Sterownik tłumaczy interakcje[użytkownika] z widokiem na akcje, aby zostały wykonane przez model.
Te interakcje są zawarte w zmiennych przesyłanych metodą GET. Chcesz zobaczyć newsy, to klikasz na odnośnik do newsów, pod którym kryje się adres w postaci np. index.php?show=news. Zmienna show jest analizowana przez kontroler, który z niej się dowiaduje, że powinien wykonać akcję "news". Akcja pobiera dane z modelu i przesyła je do widoku, który jest dostępny dla końcowego użytkownika. Przynajmniej taki jest mój punkt widzenia.

Skoro jesteśmy już przy tym temacie, to na jakiej zasadzie działały twoje kontrolery?

Polecam lekturę artykułu hawka o MVC i dokładniejszy opis MVC na stronach BluePrints Suna.

Napisany przez: Seth 17.12.2004, 13:12:42

@hamlecik:
Ja to robie w ten sposob:
Mam jeden glowny kontroler, ktory pobiera dane od usera i na ich podstawie odpala odpowiednia akcje, ktora jest w konfigu.

Przyklad wywolania:
www.example.pl/index.php?go=/phppl/news/12

W pliku z konfigiem mam np.:
$actionsConfig['phppl'] = array( 'news' => 'NewsAction' );
(oczywiscie to tylko kawalek, bo brakuje fallbackow i defaultowych akcji)

phppl - oznacza widok
news - to nazwa akcji
12 (i ew dalsze wartosci po slashu) - to parametry akcji

I teraz kontroler na podstawie tych danych odpala akcje, ktora znajduje sie w action/phppl/NewsAction.class.php:
NewsAction->run( $view, $param );

$view = 'phppl'
$param = array(12)

Na tej podstawie akcja cos tam sobie mieli i korzysta np z NewsModel, ktory to potem odpowiednio przekazuje do widoku - umnie jest to smarty.
I tyle winksmiley.jpg

Napisany przez: hamlecik 18.12.2004, 11:30:28

Seth: Wielkie dzieki za rozjasnienie mi sprawy, chociaz to co napisales troche mi koliduje z tym co czytalem. Czy kontroler nie powinienen wywolywac akcji, akcja wywoluje rzadany widok, a widok pobiera z modelu potrzebne mu dane?

Kod
INPUT -> kontroler -> akcja -> widok <-> model
                                   |        
                                   |        
                               OUTPUT




Chyba powoli rozumiem dlaczego nic mi nie wychodzi. Bo kazdy kto pisze o MVC robi to troche inaczej niz jest w oryginalnym wzorcu, a jak sie przeczyta 5 wypowiedzi, w ktorych jest cos innego to sie nie wiem wkoncu co i jak.

Ide pisac, jak cos napisze to wtedy tu wroce winksmiley.jpg

Napisany przez: Seth 19.12.2004, 13:01:48

Faktycznie troche zmodyfikowalem wzorzec ale inny niz podales.

Kod
input ---> [kontroler] <---> [akcja] <---> [model]
               |
               v
output <--- [widok] <---> [model]

Napisany przez: Vengeance 31.12.2004, 15:35:43

Pora na moje pytanie smile.gif

Dwa różne schematy działania:

1. user chce zobaczyc tresc danego wątku na forum

ActionController >> showTopic >> showTopicView

2. user dodaje nowy post, na koniec wyswietla sie taka sama tresc danego wątku
z tą jednak roznica ze na gorze jest "belka" z napisem "post dodany pomyslnie"

ActionController >> addNewPost >> showTopic >> showTopicView


Jeśli już tu są jakieś błędy to mnie poprawcie. Teraz jednak podstawowe pytanie.
Jak i gdzie zamieścić ten kod php odpowiedzialny za wyświetlanie belki z "post dodany pomyślnie".

Napisany przez: bregovic 31.12.2004, 15:53:30

U mnie to wyglada tak:

Co do twojego pytania, to ja wyswietlilbym belke przekazujac parametr do akcji ShowTopic.

Napisany przez: kurak 31.12.2004, 16:25:47

Vengeance, co u Ciebie robi showTopic?

Napisany przez: Vengeance 31.12.2004, 17:26:42

to jest akcja wyswietlajaca to co widzisz teraz winksmiley.jpg
tytul wątku i wszystkie posty (odpowiedzi) userów smile.gif

Napisany przez: kurak 31.12.2004, 19:00:01

A po co Ci i showTopic, i showTopicView? Przeciez mozna to zrobic tylko za pomoca showTopicView. Z reszta przegladajac ten topic i czytajac art Hawka mozna sie dowiedziec, ze akcje sa czescia MVC odpowiedzialna za updatowanie uduwanie i dodawanie danych do np. bazy danych - dlatego nie wiem co ma akcja do wyswietlenia topicu. Tym powinien zajac sie widok, pobierajac przez model dane i je wyswietlajac.
Jak sie myle to mnie poprawcie.
pozdrawiam i zycze swietnej zabawy sylwestrowej do rana smile.gif

Napisany przez: bregovic 31.12.2004, 19:07:42

Zaraz, moment, akcja jest częścią kontrolera - i nie ma nic wspólnego z danymi - model jest odpowiedzialny za prace z danymi, widok za wyświetlanie danych w porządanym formacie - natomiast kontroler (więc i akcja) jest odpowiedzialny za aktywowanie modelu, wyciągniecie od niego właściwych danych i przekazanie ich do widoku - który cały ten szajs wyświetli.

Napisany przez: kurak 31.12.2004, 19:12:40

bregovic, sciagnij sobie pdf'a z artem hawka 'Wprowadzenie do MVC'. Jest tam bardzo fajny schemat obslugi zadania (rozdzial: 'Obsługa żądania'). Niestety w arcie na wortalu go nie ma.

Napisany przez: bela_666 31.12.2004, 19:38:02

Cytat(kurak @ 2004-12-31 20:12:40)
bregovic, sciagnij sobie pdf'a z artem hawka 'Wprowadzenie do MVC'. Jest tam bardzo fajny schemat obslugi zadania (rozdzial: 'Obsługa żądania'). Niestety w arcie na wortalu go nie ma.

tak i omawiane było to wiele razy, że rysunku nie ma, ale nikt nic z tym nie zrobił sad.gif

Napisany przez: Vengeance 31.12.2004, 20:22:03

@kurak :

Cytat(hawk)
Powinno być tak:

1) Zawsze uruchamia się akcja, która robi wszystkie zmiany w Modelu (addUser, deleteUser, modifyUser, blah, blah).
2) Akcja zawsze podaje, jaki widok uruchomić
3) Zawsze uruchamia się widok, który wyciąga z Modelu potrzebne dane i wyświetla je, bez zmieniania niczego

Czyli w najprostszym przypadku (tylko wyświetlamy coś) akcja nic nie robi, poza wskazaniem widoku. Inna sprawa, czy chce nam się robić klasy dla takich jednolinijkowych akcji, ale tak wygląda oficjalny MVC. Zawsze jest akcja - widok. Tak więc nie ma żadnego rozróżniania zapytań wymagających i nie wymagających akcji. Zawsze jest akcja, a jak ta akcja nic z siebie nie robi, to już jej sprawa.

Napisany przez: kurak 1.01.2005, 14:33:29

Hmmm... no to mamy tu przypadek rozbieznosci zeznan tongue.gif Hawk w swoim arcie jasno dal do zrozumienia, ze akcje uruchamiamy tylko w przypadku, kiedy zachodzi potrzeba zmiany stanu danych w modelu. Najlepiej poczekajmy na wypowiedz Hawka biggrin.gif
Cale szczescie, ze poruszany jest ten temat, bo wlasnie pisze kontroler...

Napisany przez: Vengeance 1.01.2005, 15:35:12

ee ale to w sumie jest dowolne! nie przesadzajmy ze jesli hawk powie to i to to jest to wlasnie MVC a cala reszta nie.

MVC takze nic nie mowi o akcjach przeciez! ich nawet nie musi byc.
Pozatym wzroce sa po to takze aby je naginac snitch.gif (czesto tak powstaja nowe wzroce) hehe ;]

Napisany przez: hawk 1.01.2005, 16:45:27

Żeby wyjaśnić rozbieżności:

Diagram to nie implementacja. Jeżeli kontroler ma uruchomić po prostu widok, i nie ma żadnej modyfikacji (czyli nie potrzeba do tego specjalnej akcji), to jak to zrobić? Można sobie wyobrazić taką implementację, gdzie bezpośrednio wykonywany jest widok (np. phiend), lub taką, gdzie potrzebna jest jakaś minimalna akcja, która odpali ten widok (tak ma większość). To kwestia tego, jak sie napisze framework. Ale idea jest ta sama - nie ma żadnej modyfikacji, chcemy wyświetlić widok jak najmniejszym kosztem.

Napisany przez: bregovic 1.01.2005, 17:42:32

Hmm... Hawk, podsumowywując - nie ma znaczenia czy nazwiemy to akcją, czy widokiem, czy czymkolwiek - to musi być jakaś klasa, która coś wyświetli. W przypadku phienda, są to klasy z funkcją display - które ewentualnie łączą się z modelem i wyświetlają output (np. przy pomocy smarty).
Innym rozwiązaniem (które tak na prawdę jest dokładnie tym samym - z tymże z innymi nazwami) jest stworzenie akcji - które nie robią nic innego jak wyciągnięcie danych z bazy i wyświetlenie ich.

Różnica, z tego co widzę polega na ilości kontroli jaką przekażemy widokowi. Mnie, wydaje się że widok jako taki nie powinien mieć dostępu do modelu - bo zbyt komplikuje to implementację. Wydaje mi się że to kontroler (więc i akcje) powinien pracować na api modelu - a widok powinien zająć się wcale niełatwą sprawą wyświetlania danych...

Czy się mylę?

Napisany przez: Vengeance 1.01.2005, 17:59:09

@bregovic: krotka mowiac myslisz o tworzeniu widoku przez akcje
i przekazywaniu mu jakos (glownie przez parametry w konstruktorze)
jedynie wyniku jakis tam operacji na modelu (pobierania danych).

Z tego co widze bo roznych przygladach wiele skryptow przekazuje do
widoku instancje modelu aby ten zrobil sobie "co potrzebuje". Jednak moze zrobic takze cos wiecej. A w przypadku rozwiazania podanego powyzej mialby dostepdo tego co naprawde jest mu koniecznie.
Czy tak?

Napisany przez: DaNTe 24.01.2005, 12:47:08

Podłącze się pod temat, żeby nie zakładać nowego smile.gif
Jestem na etapie budowania aplikacji w oparciu o phiend (co prawda to tylko podstawa, którą trzeba dosć mocno rozbudować, ale zawsze).

Z tego co zdążyłem się zorientować, nie ma tutaj matod dających dostęp to parametrów POST, GET itp, a jako, że nie bardzo chcę operować na nich bezpośrednio - muszę sobie taki kawałek kodu dopisać.

Problem jest właśnie z parametrami GET sad.gif bo prawdopodobnie czasami na wywołania nałożony będzie mod_rewrite, zresztą ze standardową postacia index.php/moja/akcja/ też nie ładnie wyglądały parametry get przekazane po znaku zapytania.

I tu właściwe pytanie - jak radzicie sobie z wywolaniami w stylu /artykul/15/strona/6 ?

Jakieś idee poza ręczną analizą REQUESTED_URI - którą defacto powinien odwalić rontroler ?

Napisany przez: hawk 24.01.2005, 13:11:39

Jeżeli chodzi o index/nazwa/akcji, to na pewno możesz to zrobić za pomocą standardowego phienda. Tak działa np. strona projektu.

Jeżeli chodzi o artykuł/16/strona/5, to istotnie kontroler powinien takie coś odwalić. Ale sam framework nie, bo nie wie nic o artykułach. W zależności od tego, ile akcji potrzebuje takich danych, można wydziedziczyć wszystkie/niektóre akcje z abstrakcyjnej klasy, która parsuje takie coś i wyciąga to co potrzeba.

Można też przyjąć, że url zawsze ma postać cośtam/nazwa/wartość/nazwa2/wartość2 itd. Tego phiend automatycznie nie parsuje, i wtedy najlepiej chyba byłoby zrobić klasę bazową dla wszystkich akcji.

Napisany przez: aleksander 9.02.2005, 18:22:42

ok no więc ja poruszę troche inny temat MVC. Jest to własciwie tylko małe uniedogodnienie, ale czasem może wkurzyć. Być może ja coś źle robię.

mam akcję showcomments. W tej akcji są wyświetlane komentarze i formularz do wstawienia nowego komentarza. Gdy kliknę na przycisk dodaj komentarz, przejdę do akcji addcomment. Ta akcja zwróci nazwę widoku showcomments, wieć znowu zobaczę komentarze, ale w pasku adresu będzie nadal addcomments i gdy użytkownik niechący lub chcący kliknie F5 to do bazy znowu doda się identyczny komentarz (pomijam, że przeglądarka ostrzega przed tym).

Można by w akcji addcomment zrobic header( 'Location'); do akcji showcomments i po problemie, ale to z kolei odbiera od zasady MVC. Co Państwo o tym myślą?

pozdrawiam

Napisany przez: dag 9.02.2005, 18:42:20

Można zwrócić widok z tekstem "komentarz został dodany..<a>zobacz komentarze</a>"

Napisany przez: sopel 9.02.2005, 19:55:19

albo po prostu uneimożliwić dodanie takiego samego komentarza, poprzez sprawdzeni przy dodawaniu do bazy czy nie istnieje juz dokladnie taki sam rekord (pomijając czas oczywiście, no i trzeba uważać żeby przy okazji nie zablokować użytkownikowi możliwości wielokrotnego postowania popoularnych fraz np. "ok")

nawiasem mówiąc, przy okazji implementujemy mały mechanizm anty-floodowy.

Napisany przez: marcin96 10.02.2005, 15:04:30

Cytat
Można by w akcji addcomment zrobic header( 'Location'); do akcji showcomments i po problemie, ale to z kolei odbiera od zasady MVC. Co Państwo o tym myślą?


Czemu odbiega? Zrobić widok wykonywany po wykonaniu akcji dodania komentarza do bazy. Widok ten wysyła do użytkownika właśnie header("Location: ..."); i tyle...

Napisany przez: hawk 10.02.2005, 16:50:22

Fakt, nie odbiega. Patrz np. phrame.

A generalnie to po prostu potrzebna jest kontrola postback. A przekierowanie jest właśnie jedną z takich metod.

Zresztą można nawet puścić header już w początkowej akcji. Redirect i tak jest tylko wewnętrznym trikiem, a nie widokiem.

Napisany przez: squid 9.03.2005, 13:57:27

czy mozna laczyc MVC z innymi wzorcami, ktos juz tak probowal?

Napisany przez: M4chu 9.03.2005, 15:51:00

Mozna? Nawet trzeba! Np Dao, Intercepting Filter, Decorator (do widoku).
Btw sam MVC jest zbudowany na Composite, Observer, Strategy i pewnie jeszcze kilku smile.gif

Napisany przez: UFO 10.08.2005, 22:16:48

Witam!
I ja pozwolę sobie dołączyć się do dyskusji biggrin.gif Zacząłem właśnie pisać własny framework. Początkowo miał to być CMS, ale stopniowo ewoluowało do frameworka. Planuję wykorzystać model MVC, jednak męczy mnie parę kwestii...

Po pierwsze:
We wprowadzeniu do MVC wyczytałem że powinien być tylko jeden kontroler. Co w sumie logiczne jest jeśli system ma być elastyczny i łatwo się dopasowywać poprzez wyedytowanie configa. Jednak problem pojawia się jeśli chcemy zastosować do tego czegoś subdomeny. Mamy dany kontroler kontroler.php. I teraz w zależności od parametrów przekazanych do niego chcemy wyświetlić dział newsy albo czat. Czyli kontroler.php?dzial=newsy kontroler.php?dzial=czat I wszystko ładnie i pięknie do czasu aż wprowadzimy subdomeny. newsy.domena.pl czat.domena.pl I co się wtedy dzieje? Wychodzi na to że trzeba zastosować kilka kontrolerów. Chyba że... wykorzystać mod_rewrite, ale ten nie zawsze jest dostępny. Można też teoretycznie wykorzystać stronę błędu 404 do "emulacji" mod_rewrite ale to rozwiązanie mało eleganckie. A jeśli podzielimy kontroler to znowu stracimy możliwość łatwej konfiguracji i system w ten sposób będzie mało elastyczny (właściwie przypisany do jednego konkretnetego rozwiązania - czyli przestanie być frameworkiem). Może więc w każdej subdomenie dać plik index.php, w którym wysyłać header Location, przekierowujący do kontrolera i przekazujący mu wszystkie parametry? To też rozwiązanie mało eleganckie i rozwiązujące problem tylko częściowo. A może są jeszcze jakieś ciekawe rozwiązania tego problemu?

Druga sprawa:
Druga? W trakcie pisania tego postu przyszło mi do głowy kilka pomysłów na rozwiązanie pozostałych problemów biggrin.gif

Pozdrawiam

Napisany przez: Ociu 11.08.2005, 09:50:50

Ja mam coś takiego: localhost/język/content(lub forum, chat)/moduł/opcja/id/

przykładowo: localhost/pl/content/articles/show/1/

Do subdomen, można by rzeczywiście użyć mod_rewrite... jaki w tym problem ?

Napisany przez: Vengeance 11.08.2005, 10:49:32

przecież każda subdomena może wskazywać na ten sam katalog, z tym samym index.php i kontrolerem, a kontroler sprawdzi poprawność $_SERVER[HOST].

Jeżeli stwierdzi, że ma doczynienia z odwołaniem z subdomeny, ustala np. katalog z którego ma brać akcje np. /actions/chat/*

Pozatym do tego służy także wzorzec FrontControllera pozwalający utworzyć "jeden spójny punkt wejścia" do aplikacji.

Napisany przez: max_catch 27.08.2005, 18:22:48

Mam pytanie z nieco innego obszaru. Nie dysponuję gotowym kodem, rozważam jedynie teoretycznie, ale postaram się przedstawić moje wątpliwości w miarę zrozumiale.

Rozpatrując modularyzację aplikacji wygodna jest możłiwość wykonywania sekwencji akcji (czy też łańcuchów akcji; być może mylę pojęcia) przy czym akcje te mogą być dynamicznie kolejkowane w trakcie wykonywania dowolnej akcji.

Przykład: stronę tworzą takie komponenty: drzewiaste menu (np: katalog produktów w e-sklepie - kategorie), lista produktów (główna treść), pole wskazujące w jakim miejscu strony jest użytkownik. Aby wygodnie rozdzielić zadania i ułatwić edycję, każdy z wymienionych komponentów strony może być realizowany oddzielną akcją i wywoływany w zbiorczej akcji, choćby tak:

  1. <?php
  2.  
  3. class Store extends Action {
  4. public function perform(httpRequest $request, httpResponse $response) {
  5. // kolejkowanie potrzebnych elementów, czyli tworzenie omawianej sekwencji akcji
  6. Controller::getInstance()->enqueue('displayCatalog');
  7. Controller::getInstance()->enqueue('displayLocation');
  8. Controller::getInstance()->enqueue('displayProducts');
  9. }
  10. }
  11.  
  12. ?>


w takiej sytuacji kontroller otrzymawszy żądanie 'www.test.com/go/Store' podczas inicjalizacji wprowadza do swojej wewnętrznej listy akcji nazwę akcji do wykonania (tutaj 'Store', nie jest uzasadnione wprowadzanie na listę gotowego obiektu). Kontroler startuje; podczas wykonania Store zakolejkowane zostają 3 kolejne akcje i pętla wykonawcza sunie dalej.

A teraz sedno sprawy. sad.gif

Na platformie MVC potrzebujemy także filtrów. Moje pytania dotyczą wzajemnych relacji między akcjami a filtrami.

1. Czy wykonanie łańcucha akcji powierzać samemu kontrolerowi, czy może kontroler powinien wykonywać jedynie szereg filtrów, z których ostatni będzie filtrem ExecutionFilter i jemu przekazywać kontrolę nad sekwencją akcji? Jakie są korzyści zastosowania każdego z rozwiązań?

2. Czy wykonanie akcji w sekwencji wiązałoby się z wykonaniem osobnego szeregu filtrów dla każdej akcji? Czyli czy łańcuch filtrów to pomysł, który powinno się stosować przed wykonaniem łańcucha akcji, czy też dla każdej akcji w łańcuchu indywidualnie?

Podsumowując, chciałbym abyście podzielili się swoimi pomysłami na rozwiązanie problemu "interakcji łańcucha filtrów z łańcuchem akcji" i sprecyzowali miejsca obu wymienionych części we frameworku MVC.

Napisany przez: pies 9.09.2005, 09:25:22

Jakiś czas temu razem z paroma osobami ze świata napisaliśmy (a oni dalej rozwijają) framework MVC -- Cake php (www.cakephp.org). Rozwiązanie problemu URLi ściągnęliśmy z RoR (www.rubyonrails.org).

Pomysł opiera się na przypisaniu adresów do konkretnych klas i metod, tak, że np. adres:

www.example.com/blog/view/55

odpowiada klasie BlogController (Controller to "C" w "MVC") i metodzie view() w tej klasie, a "55" przekazywane jest jako parametr do wywołania metody, czyli powyższe wywołanie przekształcane jest w:

Kod
print BlogController->view(55);


Reguły przypisania określane są przez mechanizm Router. Można dzięki niemu zmienić rozumienie wywołań w dość dowolny sposób:

Kod
$Router->connect('/', array('controller'=>'Pages', 'action'=>'view', 'home'));


...oznacza, że wywołanie strony głównej (/) uruchamia PagesController->view('home').

Kod
$Router->connect('/kupuj/:action/*', array('controller'=>'Shop', 'action'=>'kategoria'));


...oznacza, że wywołania adresów typu /kupuj, /kupuj/koszyk, /kupuj/kategoria/5, /kupuj/produkt/234/czerwony przekształcane są w wywołania, odpowiednio:

Kod
print ShopController->kategoria();
print ShopController->koszyk();
print ShopController->kategoria(5);
print ShopController->produkt(234, 'czerwony');


Jest do tego manual smile.gif

Napisany przez: Ociu 10.09.2005, 08:29:05

pies: czyli dla każdego modułu musisz tworzyć nowy Controller ? Nie widze najmniejszego sensu.

Mam link w takiej postaci:
/pl/content/home/ - dla strony głównej portalu. Jeśli chce uruchomić np. blog to daje.
/pl/blog/home/

opcjonalnie mam link z parametrem /pl/blog/entry/view,13/ (przykład).

Request: (cząstka)

  1. <?php
  2. public function SimpleVirtualURL() {
  3. $iURL = (http://www.php.net/isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : THRORIN_LINK);
  4. $this->iURL = http://www.php.net/explode('/', $iURL);
  5. }
  6. ?>


Czyli rozbija adres do tablicy. w Routerze jest analizowanie tej tablicy:
  1. <?php
  2. public function Analyse() {
  3. $this->request->SimpleVirtualURL();
  4. $this->lang = (http://www.php.net/empty($this->request->iURL[1]) ? THRORIN_LANG : $this->request->iURL[1]);
  5. $this->system=(http://www.php.net/empty($this->request->iURL[2]) ? 'content' : $this->request->iURL[2]);
  6. $this->module=(http://www.php.net/empty($this->request->iURL[3]) ? 'home' : $this->request->iURL[3]);
  7.  
  8.  
  9. if(!http://www.php.net/isset($this->request->iURL[4])) http://www.php.net/exit();
  10.  
  11. $url = http://www.php.net/explode(',', $this->request->iURL[4]);
  12.  
  13. # czyszczenie tablicy iURL
  14. $this->request->iURL = http://www.php.net/array();
  15.  
  16. $this->option=$url[0];
  17. $this->id=$url[1];
  18. }
  19. ?>


Później Controller wywołuje odpowiednią akcję.
I tak dzięki 4 plikom (+view) mam uniwersalny silnik smile.gif

Napisany przez: pies 12.09.2005, 14:00:38

Cytat
pies: czyli dla każdego modułu musisz tworzyć nowy Controller ? Nie widze najmniejszego sensu.


Nie bardzo rozumiem co masz na myśli. Jeżeli moduł to pojedyncza funkcjonalność serwisu (np. newsy albo obsługa formularza) to w moim modelu moduł nazywa właśnie controller.

Cytat
Później Controller wywołuje odpowiednią akcję.
I tak dzięki 4 plikom (+view) mam uniwersalny silnik smile.gif


Mój mechanizm działa bardzo podobnie, tylko dodatkowo jest konfigurowalny i ma obsługę błędów (zakładam, że Twój też). Nie wiem z ilu plików się składa, bo jest częścią frameworku i ma trochę zależności (m.in. logowanie błędów), ale ogólnie rzecz biorąc mam klasy Router (konfiguracja URLi) i Dispatcher (odczytuje konfigurację, ładuje potrzebne klasy, tworzy obiekt controllera i uruchamia go).

Konfigurowalność pozwala na dodanie m.in. krótkiego aliasu do jakiejś strony, na przykład
Kod
www.audi.com/a4
które działa tak jak
Kod
www.audi.com/products/view/a4
.

Robi się to tak:
  1. <?php
  2. $Router->connect('/a4', http://www.php.net/array('controller'=>'Product', 'action'=>'view', 'a4');
  3. ?>


Wywołana będzie metoda ProductController->view('a4').

Napisany przez: Ociu 16.09.2005, 12:09:43

Witam,

Cytat
Nie bardzo rozumiem co masz na myśli. Jeżeli moduł to pojedyncza funkcjonalność serwisu (np. newsy albo obsługa formularza) to w moim modelu moduł nazywa właśnie controller.

To już mi się wydaje bardziej logiczne. Coś mi się wcześniej ubzdurało, że controller modułu =/= moduł. 'Błądzić jest rzeczą ludzką.'

Cytat
Mój mechanizm działa bardzo podobnie, tylko dodatkowo jest konfigurowalny i ma obsługę błędów (zakładam, że Twój też).

Pewnie, że mam. Mój ErrorHandler jest dostępny na Algorytmy, klasy, funkcje

---

Tak nie mając dostępu do komputera, myślałem, troszke o linkach i stwierdziłem, ze nie ma sensu tworzenia tak długiego linku. Zastosuje się do /module/option/id/, czyli np. /produkty/pokaz/14/.

Aliasy ? hm.. nie głupie, ale. Aliasy są tworzone, dla unikalnych id. A jeśli chciałbyś stworzyć aliasy dla newsów i artykułów ? Wtedy mogą wystąpić takie same id i skrypt się sypie. Oczywiście zakładam dość ekstremalny przypadek, bo raczej nikt nie tworzy aliasów dla newsów i artów, tylko dla sklepów itp. jednak rozpatrzmy wszystkie przypadki smile.gif

pozdrawiam

Napisany przez: pies 16.09.2005, 18:52:00

Cytat
Tak nie mając dostępu do komputera, myślałem, troszke o linkach i stwierdziłem, ze nie ma sensu tworzenia tak długiego linku. Zastosuje się do /module/option/id/, czyli np. /produkty/pokaz/14/.

Czyli jak u mnie /controller/action/id. Moja metoda ma większe możliwości, bo nie ma siły żebyś nie potrzebował zaraz /module/option/id/value i /module/option/id/operation/id2 i tak dalej. U mnie jest to obsługiwane automatycznie (czyli nie stałe id, tylko parametry które option/action przyjmuje jak każda normalna funkcja).

Cytat
Aliasy ? hm.. nie głupie, ale. Aliasy są tworzone, dla unikalnych id. A jeśli chciałbyś stworzyć aliasy dla newsów i artykułów ? Wtedy mogą wystąpić takie same id i skrypt się sypie. Oczywiście zakładam dość ekstremalny przypadek, bo raczej nikt nie tworzy aliasów dla newsów i artów, tylko dla sklepów itp. jednak rozpatrzmy wszystkie przypadki smile.gif

Nie wiem po co _można_ używać aliasów, ale ja dodałem je dlatego, że używamy tego w serwisach -- jako landing-pages do akcji promocyjnych (np. reklamy w różnych portalach mają różne landing-pages żeby na bieżąco zliczały wejścia) czy jako adresy podawane w reklamach.

Docelowo system aliasów będzie konfigurowalny przez CMS, dlatego musi być dość uniwersalny. Nie wiem jeszcze co z tego wyjdzie smile.gif

Napisany przez: Ociu 17.09.2005, 09:51:17

Cytat(pies @ 2005-09-16 19:52:00)
U mnie jest to obsługiwane automatycznie (czyli nie stałe id, tylko parametry które option/action przyjmuje jak każda normalna funkcja).

Mogłbyś rozwinąć swoją wypowiedź ? najlepiej kodem smile.gif

Napisany przez: Strzałek 19.12.2005, 22:14:36

hmmm, no to wziąłem temat po raz kolejny już na raz przeczytałem i nie wiem już co myśleć. Tyle tutaj mądrości tongue.gif Więc ja widzę co tak i chcę się upewnić czy dobrze rozumuje:

adres wygląda tak: http://www.example.com/&lt;action&gt;/&lt;view&gt;/

i teraz wchodzimy na stronkę:

http://example.com/: odpalamy dośmyśną akcję i domyślny widok
http://example.com/articles/: odpalamy akcję articles i domyślny widok dla niej
http://example.com/news/showAll/: odpalamy akcję news i widok showAll
http://example.com/news/rss/: odpalamy akcję news i widok rss (wyświtlamy rssy smile.gif )
http://example.com/news/pdf/423: odpalamy akcję news i widok pdf oraz dajemy jeszcze na końcu id news'a który ma być wyświtlony w formacie pdf'a snitch.gif

i teraz czy czuję o co biega w tym. Co inaczej powinno to działać ? worriedsmiley.gif

Napisany przez: Vengeance 19.12.2005, 22:19:03

To ja się dołącze z innym pytaniem. Co zrobić z Apache/php aby takie URLe jak powyżej działały? Co dać w .htaccess aby każdy taki URL odnosił się do http://example.com/index.php

Ważne także by URLe kończące się jakimś rozszerzeniem, lub takie:
http://example.com/katalog/img.jpg?a=tekst

nie były przeżucane do index.php ale interpretowane standardowo

Napisany przez: FiDO 19.12.2005, 22:56:33

Vengeance: to pytanie nie ma duzego zwiazku z tematem, wiec zadaj je (a w zasadzie znajdz odpowiedz, bo to juz nie raz bylo przerabiane) w opowiednim miejscu, OT tutaj niepotrzebne.

Napisany przez: Ociu 20.12.2005, 19:42:05

Strzałek: uruchom admina snitch.gif

Jako, że nabyłem doświadczenia (no dobra, trochę), przebudowałem cały system do takiej postaci:
/module/action/parametr/paratemtr1/parametr2
defaultowo /content/display/news
FilterChain - (klasycznie) kolejka -> ActionChain:

  1. <?php
  2. public function execute( HttpContext $context, FilterChain $chain ) {
  3. $build = $context->module.'_'.$context->method;
  4. $model = new $build();
  5. $model->perform($context->what, $context->vars);
  6. $chain->nextExecute($context);
  7. }
  8. ?>

(Uproszczony kod).
noi mam ./modules/content/actions/display.php
  1. <?php
  2.  class content_display
  3. public function perform($what, $a = null) {
  4. if($a == null) {
  5. $this->display($what);
  6. } else {
  7. $this->displayByArgs($what, $f);
  8. }
  9. }
  10. ?>



Pozwoliło mi to na stworzenie panelu admina smile.gif

pozdrawiam

Napisany przez: Vomit 26.06.2006, 12:02:31

Nie bede zakladal nowego topic'u poniewaz moje pytania(e) dotycza(y) MVC.

Wszystko co wiem o tym wzorcu wiem z mini-frameworka zaprezentowanego niegdys przez hwao. U siebie zrobilem wiec bardzo podobnie, nie wiem jednak jak zaimplementowac akcje i w jaki sposob.

Napisany przez: Ludvik 26.06.2006, 12:05:23

Stwórz sobie interfejs dla akcji, który posiada jedną metodę, w której akcja dokonuje wszystkich operacji na danych. Żeby nie była odizolowana od otoczenia przekaż jako argument wszystkie potrzebne informacje z kontekstu (żądanie, obiekt sesji itp.). Akcje lepiej uruchamiać w łańcuchach, więc musisz znaleźć sposób na zapisanie nazwy kolejnej akcji (ja to zapisuję w obiekcie Context). Jeżeli nie ma następnej akcji zapisujesz pusty ciąg znaków. Akcje uruchamiasz w pętli...

Napisany przez: Vomit 26.06.2006, 12:15:44

Troszke strasznie to brzmi, cóz bede musial liczyc ze hwao zaimplementuje jeszcze do tego mini frameworka akcje, albo poszukac jakichs przykladow.

Napisany przez: Nostress 10.07.2006, 13:02:33

W skrócie, ale od początku:

- Mamy FronController, który uruchamia to, co potrzebne jest każdej akcji.
- Na podstawie danych od użytkownika (np. z URL) uruchamia on odpowiednią akcje (dajmy na to listaNewsow). Tu na chwile praca FrontControllera się kończy, a funkcję określaną jako Controller przejmuje uruchomiona akcja.
- akcja wczytuje plik modelu, pobiera z niego odpowiednie dane (tu: newsy), co może wyglądać tak:

  1. <?php
  2. require_once( 'model' );
  3. class listanewsowAction
  4. {
  5.  private model;
  6.  
  7.  public function __construct()
  8.  {
  9. $this->model = new Model;
  10.  }
  11.  
  12.  public function uruchom()
  13.  {
  14. $dane = $this->model->listaNewsow();
  15.  }
  16. }
  17. ?>


I w tym miejscu mam pewne wątpliwości:

1) czy ta akcja (listanewsowAction) powinna tylko pobrać dane, zwrócić je FrontControllerowi, a ten wybiera odpowiedni widok?
2) czy akcja sama w sobie powinna pobrać dane, wybrać widok i go wyświetlić?

Mam nadzieje, ze napisalem w miare zrozumiale. Główną myślą tego posta jest "jak uruchamiać widok, jak (w którym momencie) decydujemy jak dane wyświetlić (czy to bedzie smarty, pdf czy xml)". Jak wy to robicie? A może zupełnie pomieszałem?

Napisany przez: squid 10.07.2006, 13:32:41

Cytat(Nostress @ 10.07.2006, 14:02 ) *
I w tym miejscu mam pewne wątpliwości:

1) czy ta akcja (listanewsowAction) powinna tylko pobrać dane, zwrócić je FrontControllerowi, a ten wybiera odpowiedni widok?
2) czy akcja sama w sobie powinna pobrać dane, wybrać widok i go wyświetlić?

Mam nadzieje, ze napisalem w miare zrozumiale. Główną myślą tego posta jest "jak uruchamiać widok, jak (w którym momencie) decydujemy jak dane wyświetlić (czy to bedzie smarty, pdf czy xml)". Jak wy to robicie? A może zupełnie pomieszałem?

Wg danymi po pobraniu i przetworzeniu powienien zajac sie Controller (nie koniecznie FrontController), taki kontroler zdecydowalby jaki ma byc format wyjsciowy danych (na podstawie obiektu Request) i zastosowac otrzymane dane do jakiegos szablonu. Na koniec calosc z odpowiednimi naglowkami wyslac do usera.
U mnie kiedy FrontController dostaje spowrotem sterowanie z akcji uruchamia obiekt widoku, ktory sie tym zajmuje.

Napisany przez: Ociu 13.07.2006, 08:02:04

Wg. mnie to zależne jest od Ciebie jak framework ma działać.

IMHO FrontController uruchamia model, akcję i widok. Model pobiera dane i robi z nimi jakieś czary, przekazuje akcji, a akcja daje widokowi i mamy wynik.

Napisany przez: Levabul 15.07.2006, 11:59:35

To ja zadam pytanie z seri pytań oczywistych (dla innych) tongue.gif. Przedstawie to obrazowo:

Czy model jest klasą obsługującą np. daną tablę w bazie danych:

  1. <?php
  2. class News extends Model {
  3.  
  4. protected $tableName = 'news';
  5. protected $fields = http://www.php.net/array ('id', 'title', 'author_id', 'date', 'content');
  6.  
  7. }
  8.  
  9. $table = new News ();
  10. $table -> WhereAuthor_idEqual('1');
  11. $table -> OrderByIdDesc();
  12. $result = $table -> select ();
  13. ?>


Czy może jest klasą mającą na celu np. obsługę newsów (a więc nie tylko tablei news):

  1. <?php
  2. class News extends Model {
  3.  
  4. protected function getNews () {
  5. $sql = http://www.php.net/mysql_query ('SELECT `id`, `title`, `date`, `content`, `users`.`name` as author FROM `news` IN
    NER JOIN `users` ON `author_id` = `users`.`id` ORDER BY id DESC'
    );
  6. while ($row = http://www.php.net/mysql_fetch_array ($sql)) {
  7. $result[] = $row;
  8. }
  9. return $row;
  10. }
  11.  
  12. #funkcja wykozystywana przez kontroler do pobierania danych od modeli
  13. public function get () {
  14. $data = $this -> getNews ();
  15. return $data;
  16. }
  17. }
  18. ?>

Napisany przez: mariuszn3 15.07.2006, 12:08:40

Te wszystkie klasy należą do modelu. Model jest to wewnętrzna logika aplikacji, włącznie z częścią komunikującą się z bazą danych. Zazwyczaj część odpowiadającą za komunikację z bazą danych wydorębnia się w modelu (w moduł DAO - data access object) ale nadal logicznie rzecz ujmując jest to część modelu. Przynajmniej ja to tak rozumiem.

Napisany przez: squid 15.07.2006, 13:12:49

Jesli moge zastapic slowo model akcja to akcja ma za zadanie wykonac operacje na danych nie dbajac gdzie i jak sa zapisane oraz jakiego sa formaty (no oczywiscie w pewnych granicach). Jak dobijasz sie dodanych to juz raczej nie ejst sprawa modelu, mozesz zastowosowac metode aktywnego rekordu, jakas abstrakcje w stylu PEAR::MDB lub SDO i inne wynalazki.

Napisany przez: Vomit 26.07.2006, 22:00:24

Witam,


Wydaje mi sie ze w moim projekcie udało mi sie zaimplementowac wzorzec MVC, moze nie dokladnie i nie idealnie ale przeciez nie o to chodzi, trzeba korzystac z pasujacych nam rozwiazan a nie wdrazac je na sile.

Doszedlem jednak do pewnego momentu, ktory zainteresowal mnie. Router rozbija URL i zwraca jako tablice. Pierwszy element tablicy to moduł, ktory ma zostac "odpalony". Wszystko jest przemyslane i dobrze dziala, ale teraz mam dobudowac jeszcze jeden, administracje.

Nie moze byc on wlaczany na tych samych prawach jak inne moduły. Znajduje sie on w innym folderze, w innym folderze beda jego szablony. Zle by bylo przeciez gdy w folderze styli byly default, jakisinny, styl_do_admina.

W moim projekcie FrontController, to glowna klasa zarzadzajaca modulami do wczytania. Jak zastrzec ze modul 'admin' ma byc traktowany w inny sposob?

Nie chodzi mi oczywiscie o to zebyscie powiedzieli "potraktuj to if'em" bo tak mozna najprosciej. Chodzi mi o to jak wy robicie to u siebie.

Napisany przez: squid 26.07.2006, 22:39:00

Nie jestem pewien czy Router powinien rozbijac URL na tablice, wydaje mi sie ze to Geqest powinien to robic a na Router spada odpowiedzialnosc za dostarczenie mechanizmu tworzenia linkow i dostarczenia info o akcji jaka zostala zarzadana.

Nie wiem czy dobrze rozumiem ale czy pytasz o autoryzacje? Czy chcesz wiedziec czy uzytkownik X ma prawo wykonac akcje Y? Ja to robie w ten sposob, ze te akcje, ktore maja ograniczona liczbe uzytkownikow (np. akcje administracyjne) przed swoim wykonaniem musza wykonac akcje autoryzacyjna, ktora jest zwykla akcja tyle tylko ze jesli stwierdzi ze user X nie ma prawa wykonac akcji Y to rzuci wyjatkiem a do wykonania zarzadanej akcji nie dojdzie. Daje mi to duza elastycznosc co do wyboru metody i algorytmu autoryzacji, wszysko mam w jednym miejscu i cokolwiek by sie nie zmienilo wystarczy ze zmienie jedna akcje aby dostosowac sie np. do LDAP'a

Napisany przez: mariuszn3 26.07.2006, 22:42:59

Ja w ogóle rozdzieliłem kontroler części administracyjnej i użytkownika (apache jest u mnie front controllerem).
W konfiguracji http ustawiłem też aby część adminstracyjna serwisu była dostępna pod innym portem przykładowo 8100. Natomiast w katalogu htdocs mam dwa podkatalogi 'user' i 'admin'. kiedy użytkownik wchodzi poprzez tradycyjne 'www.mojadomena.com' apache przekierowuje na kontroler w katalogu 'user' a kiedy wchodzi na 'www.mojadomena.com:8100' apache przekierowuje na kontroler w katalogu 'admin'.
Oczywiście aby dokładnie tak to załatwić trzeba mieć pełny dostęp do konfiguracji apache'a.. ale ogólnie idea jest taka, że wydzieliłem osobne ścieżki na część użytkownika i administratora co oczywiście nie przeszkadza im korzystać z tych samych modułów.

Napisany przez: Vomit 26.07.2006, 22:51:00

Squid: zle zrozumiales, fakt, autoryzacja bedzie kolejnym krokiem, ale chodzi mi wlasnie o to o czym mowi mariuszn3.

Rozdzielenie czesci administracyjnej od czesci uzytkownika. Poczynajac wlasnie od kontrolera. Rozwiazanie ciekawe, ale wymaga jak juz napisał dostepu do Apache'a.

Napisany przez: NuLL 26.07.2006, 23:25:24

Witam,

Cytat
Rozdzielenie czesci administracyjnej od czesci uzytkownika


Chyba nic trudnego w stworzeniu dla kazdej akcji prostego configu z opisem do ktorej czesci aplikacji nalezy questionmark.gif smile.gif

Pozdr.

Napisany przez: Vomit 26.07.2006, 23:37:30

Ano nic trudnego, ale nie chce poprostu aby w folderze ktorym trzymane sa moduly byl takze trzymany admin a tpl'ki od admina lezaly w folderze reszty strony.

Niby blahy problem, ale nie chce robic w rodku Frontcontrollera if'a if ( $module == 'admin' ) to odczytuj z innego folderu ;p

Napisany przez: NuLL 26.07.2006, 23:43:17

Vomit - nie rozumiem twojego podejscia - moze napisz sobie osobna aplikacje administracyjna questionmark.gif snitch.gif

Napisany przez: mariuszn3 26.07.2006, 23:43:22

front controler to raczej same if'y i switch'e, więc co zaszkodzi dodać jeszcze jeden smile.gif
Reasumując jeśli nie możesz go zastąpić apachem to chyba nie ma miejsca na inne rozwiązanie.

Napisany przez: Denver 27.07.2006, 06:51:09

Ja, gdy chcę mieć pewność, że uruchomine zostaną tylko i wyłącznie te moduły, które chcę, sprawdzam zawsze, czy mam je zapisane w jakiejś tablicy. Przykładowo:

  1. <?php
  2. $arrModules = http://www.php.net/array ('kontakt', 'galeria', 'rekrutacja', 'uslugi');
  3. $arrAdminModules = http://www.php.net/array ('admin');
  4.  
  5. // Zmienna $strModule została nam przekazana z jakiegoś kontrolera, który odczytał
     ją ze zmiennych GET/POST
  6. if (http://www.php.net/in_array ($strModule, $arrModules))
  7. {
  8. // Uruchom dane akcje modułu
  9. }
  10. elseif (http://www.php.net/in_array ($strModule, $arrAdminModules))
  11. {
  12. // Uruchom panel administracyjny
  13. }
  14. else
  15. {
  16. throw new Exception ('Ten moduł nie jest obsługiwany');
  17. }
  18. ?>

Oczywiście w panelu administracyjnym należy sprawdzić uprawnienia użytkownika do danych sekcji. Ja zazwyczaj trzymam uprawnienia w bazie, więc każdy moduł sprawdza sobie dane flagi przypisane konkretnemu użytkownikowi. Jeśli dostęp powinien być zabroniony, wyrzucam wyjątek i cześć.

Napisany przez: squid 27.07.2006, 13:08:35

Cytat(Vomit @ 26.07.2006, 23:51 ) *
Rozdzielenie czesci administracyjnej od czesci uzytkownika. Poczynajac wlasnie od kontrolera. Rozwiazanie ciekawe, ale wymaga jak juz napisał dostepu do Apache'a.

Ja nie rozdzielam, nie wydaje mi sie aby to byl dobry pozmysl rozdzielac cos co z zasady ma byc jedno. Po co rozdzielac kontroler aplikacji skoro on ma kontrolowac przeplyw miedzy innymi czesciami aplikacji i w zasadzie na tym koniec. Dostajesz zapytanie ?action=x i kontroler przekazuje sterowanie do odpowiedniej metody i nie martwi sie o to co to jest x, moze sprawdzic czy istnieje ale to wszystko.

Napisany przez: Ociu 27.07.2006, 13:10:05

Może poprostu pobawić się uprawnieniami ?

Napisany przez: bigZbig 27.07.2006, 13:34:12

Ja nie wydzielam czesci administracyjnej. U mnie administrator widzi ten sam widok co zwykly user z tym wyjatkiem ze tam gdzie trzeba administratorowi pojawiaja sie jeszcze np. linki edit, delete, add itp. Wymaga to uzycia paru ifow, ale jest bardzo wygodne podczas pracy. Ogladajac cos jako uzytkownik nieraz zauwazam ze cos trzeba zmienic. W takiej sytuacji nie musze sie zastanawiac gdzie to mam w panelu administracyjnym. Zwyczajnie loguje sie jako admin (nie musze nawet przechodzic pomiedzy stronami bo skrypt logowania przekierowuje mnie spowrotem w miejsce z ktorego wyszlo zadanie logowania) i pojawia mi sie odsylacz edit. Prosto i wygodnie. Nie trzeba robic osobnych tplkow poza formularzami.

Napisany przez: Denver 27.07.2006, 14:14:58

Popieram przedmówcę - to bardzo wygodne rozwiązanie. Logowanie przekierowuje do strony, która nas do ostatnio oglądanej strony, i te 2 IF-y w szablonach nie mają wpływu na wydajność skryptu. Szablon sprawdza mi uprawnienia danego użytkownika (odwołując się do obiektu User w którym przechowuję te uprawnienia) i jeśli np. użytkownik ma uprawnienie edycji newsów, to koło nagłówka wiadomości pokazuje się link do jej edycji.
Prosto i przyjemnie smile.gif

Napisany przez: br-design.pl 26.08.2006, 22:00:41

Cytat(bigZbig @ 27.07.2006, 14:34 ) *
Ja nie wydzielam czesci administracyjnej. U mnie administrator widzi ten sam widok co zwykly user z tym wyjatkiem ze tam gdzie trzeba administratorowi pojawiaja sie jeszcze np. linki edit, delete, add itp. Wymaga to uzycia paru ifow, ale jest bardzo wygodne podczas pracy. Ogladajac cos jako uzytkownik nieraz zauwazam ze cos trzeba zmienic. W takiej sytuacji nie musze sie zastanawiac gdzie to mam w panelu administracyjnym. Zwyczajnie loguje sie jako admin (nie musze nawet przechodzic pomiedzy stronami bo skrypt logowania przekierowuje mnie spowrotem w miejsce z ktorego wyszlo zadanie logowania) i pojawia mi sie odsylacz edit. Prosto i wygodnie. Nie trzeba robic osobnych tplkow poza formularzami.


Wszedlem na forum zeby wlasnie zadac to pytanie, super rozwiazanie, ALE, przeciez nie mozna wszystkiego tym rozwiazac, sa inne rzeczy niz tresc strony (np. administracja uzytkownikami, czy np. zamowienia w sklepie) , ktorych user nie widzi, wiec bez panela sie nie obejdzie.

Tak czy siak wracamy do problemu jak rozdzielic panel w MVC. Ja sklaniam sie do zrobienia osobnego frontcontrollera w katalogu admin (w glownym pliku htaccess dac regule ze przekierowania z domena.com/admin kierowac do katalogu admin gdzie czeka juz inny front controller niz domyslny), wtedy controllery, widoki trzymac w osobnych podkatalogach, ale z drugiej strony panel admina powinien moc korzystac z tych samych modeli co controllery glowne (userowe ze tak powiem).

Co o tym myslicie?

Napisany przez: bim2 27.08.2006, 15:13:57

Po co rozdzielac. Pisali Ci juz poco? Dajesz w akacji metode np. add_item() i w add_item() dajesz if($admin==ok) ;P itp. Nie rozdzialaj a dodaj kolejne akcje smile.gif

Napisany przez: br-design.pl 27.08.2006, 15:35:02

No przeciez pisze ze nie wszystko jest "add_item" chocby sprawdzenie zamowien w sklepie internetowym czy np. sprawdzenie platnosci itd. To rzeczy ktorych nie mozna zrobic sensownie ifem, musi byc jakis panel.

Napisany przez: bim2 27.08.2006, 16:08:09

Nie o to mi chodzi :|
mam cos takiego:

  1. <?php
  2. class SklepAction {
  3. function defaults() {} //domyslna akcja
  4. function add_item()
  5. {
  6.  if($admin)
  7.  {
  8. formularz dodania pliku
  9.  }
  10. }
  11. function show_zamowienia()
  12. {
  13.  if($admin)
  14.  {
  15. spis zamówien
  16.  }
  17. }
  18. }
  19. }
  20. ?>
I ja wywołałbym to tak: action=sklep&view=show_zamownienia (zmienan view tlkyo tak, mozna zmienić) I w czym problem?

PS. Pisałem z głowy ale powinno działac jeśli masz podobnie zbudowany Kontroller tongue.gif

Napisany przez: br-design.pl 27.08.2006, 16:18:28

A nie uwazasz ze zbytnio generalizujesz? Taka klasa jak sklepAction ktora oprocz obslugi sklepu bedzie miala jeszcze akcje do zarzadzania np. zamowieniami, uzytkownikami itd zrobi sie mocno przepasna.

Moim zdaniem zamowienia powinny byc osobnym kontrolerem gdzies wlasie w panelu, a jak nie w panelu to przynajmniej powinna byc jakos zabezpieczona przed dostepem.

i wtedy mozna zrobic osobne akcje dla pokzywania zamowien, zmiany statusu, edycji itd.

A dzieki osobnemu front controllerowi (dla panelu) ktory przyjmie obowiazek sprawdzania autoryzacji na siebie, nie musimy sie o to martwic w kontrolerach administracyjnych.

Napisany przez: bim2 28.08.2006, 10:10:00

Nie wiem... może i tak. Tylko teraz jak to zrobić? Osobny kontroller? No nie wiem, ja by dał w starym kontrollerze nową metodę. Np executeAdmin() itp. i ona zajeła by się prawami i czytała akcję np, newsA.action a modele newsA.model.php itd. Może bardziej zaawansowani cos powiedzą tongue.gif No albo zrobić osobny kontroller smile.gif

Napisany przez: altruista 13.09.2006, 16:18:20

tak mnie meczy, w koncu odwazylem sie zaptac...

1.

Jest obiekt "pracownik" - dziedziczy z klasy GenericObject (odwzorowujacej tabele w bazie na obiekt) dodakowo sklada sie z innych obiektow dziedziczacych z GenericObject (np "opinia" - pracownik ma swoje opinie).


Pytanie 1:
Tworzac widok oparty na szablonie smarty, wypada przekazywac mu obiekt np typu "pracownik" zeby szablon sam siegnal do jego metod i powyciagal potrzebne dane (imie, nazwisko, opinie) czy lepiej dla widoku przekazac juz tablice asocjacyjna z wczesniej przygotowanymi danymi (to co w pierwszej propozycji wyciaga smarty, wyciamy wczesniej)... questionmark.gif


2.

kontroler.
1. odwiedzam strone wpisujac http://strona.pl/?action=showPracownicy w celu wyswietlenia wszystkich pracownikow
2. glowny kontroler, analizujac parametr "action" includuje klase showPracownicy.class.php, (kazda klasa zaladowana przez kontroler, ma okreslony interfejs), tworzy obiekt tej klasy i wywoluje jego metode 'exec(HTTPReq $req)' (obiekt 'req' grupuje paramtery przeslane od uzytkownika, w tym wypadku nie jest konieczne przeslanie)
3. Funkcja 'exec(HTTPReq $req)' pobiera model (klasa ktora zawiera wszystkie operacje na pracownikach 'dodaj', 'usun', 'pobierz' 'wyszukaj' itp) i wywoluje jego funkcje 'pobierzWszystkichPracownikow()'; funcka zwaraca tablice/kolekcje obiektow typu 'pracownik'

Pytanie2:
Lepiej bedzie utworzyc widok w metodzie 'exec(HTTPReq $req)' obiektu klasy showPracownicy (jak tworzyc to poprzednie moje pytanie), przypisac wszystko do szablonu i go wyswietlic, czy tez zwrocic nazad do kontrolera nazwe widoku + w jakis sposob opakowane dane potrzebne do wyswietlenia, i niech glowny kontroler (ten z ktorym laczy sie uzytkownik i ten ktory stworzyl obiekt typu showPRacownicy) sobie podopisuje zmienne do szablonu i go wyswietli?



Nie wiem czy dobrze rozumuje cala koncepcje tworzenia oprogramowania, ale wole zapytac niz zaczynac pisac i uczyc sie zlych nawykow...

Watpliwosci:
3. czy rozwiazanie typu http://strona.pl/?action=nazwaAkcji jest prawidlowe? (powstanie pewnie bardzo duzo plikow a katalogu /actions/

Myslalem ze mozna np zrobic (pewnie tak sie robi) http://strona.pl/modul/funkcja/parametry i wtedy glowny kontroler bedzie ladowal klase 'modul' (zawiera wszystkie funkcje jakie sa dostepne dla modulu) i wywolywal jego metode 'funkcja' przekazujac jej 'paramtery' + tablice _REQUEST. Rozwiazanie daloby umieszczenie w jednym miejscu wszystkich funkcji zwiazanych z jednym modulem (kolejny problem to czy modulem moze byc "pracownicy" wraz z wszystkimi funkcjami czy to jest zla idea)


4. Czy mozna uzyc stwierdzenia 'model' w stusunku do klasy operujacych (zawiera wszystkie funckje jakie mozna wykonac z obiektem, np wyszukiwanie, itp) na obiektach 'pracownik'?

Napisany przez: LBO 15.09.2006, 20:15:42

Cytat(bigZbig @ 27.07.2006, 14:34:12 ) *
Ja nie wydzielam czesci administracyjnej. U mnie administrator widzi ten sam widok co zwykly user...

Gdzie wpisujesz te if'y? W pliku widoku (template'cie)? Czy w akcji zmieniasz templaty? Jeżeli, w pliku widoku jak radzisz sobie ze złożonymi zależnosciami? Na przykład: zwykły user, może tylko oglądać. Moderator oglądać i edytować. Administrator oglądać, edytować i kasować. Jak?

Pytam się, bo mam z tym problem i jestem za robieniem osobnej aplikacji administracyjnej.

Napisany przez: Apo 15.09.2006, 21:02:54

Cytat(LBO @ 15.09.2006, 19:15:42 ) *
Gdzie wpisujesz te if'y? W pliku widoku (template'cie)? Czy w akcji zmieniasz templaty? Jeżeli, w pliku widoku jak radzisz sobie ze złożonymi zależnosciami? Na przykład: zwykły user, może tylko oglądać. Moderator oglądać i edytować. Administrator oglądać, edytować i kasować. Jak?

Pytam się, bo mam z tym problem i jestem za robieniem osobnej aplikacji administracyjnej.


Ja to rozwiązałem tak że każda akcja ma swój konfig a w nim wymagane grupy, czy ma być publiczna, czy dostępna po zalogowaniu oraz akcje domyślne w razie braku uprawnien.
Mam główną klase Access która kożysta z klas pomocniczych:
Config - czyta ustawienia z tablicy i udostępnia Api do ich obsługi,
Groups - sprawdza czy dany użytkownik należy do jakiejś grupy lub czy jest zalogowany etc...

W przypadku braku uprawnien do wykanania akcji jest ona forwardowana na domyślną z configu smile.gif
A w samych akcjach mamy dostęp do klasy user która trzyma jego dane i łatwo możemy sprawdzać uprawnienia itp.

Napisany przez: LBO 15.09.2006, 21:15:50

Ale jak to wygląda w praktyce? Masz różne widoki dla różnych grup? Czy w samym widoku ustawiasz co ma być widoczne dla poszczególnej grupy?

Wydaje mi się, że najbardziej zgodne z wzorcem MVC są osobne widoki.

Napisany przez: Apo 15.09.2006, 21:29:36

Cytat(LBO @ 15.09.2006, 20:15:50 ) *
Ale jak to wygląda w praktyce? Masz różne widoki dla różnych grup? Czy w samym widoku ustawiasz co ma być widoczne dla poszczególnej grupy?


Powiedzmy że mam za zadanie wyświetlić dodatkowe dane dla moderatora forum (przycisk: usun, edytuj, przenies) czyli w pliku widoku robi za pomocą Apletu (który ma dostęp do HttpContext, klasy Usera, Modelu) warunek:

plik widoku post.php
Kod
<h1>{$title}</h1>
<?php
if($this->user->hasGroup('moderator'))
{
echo '<a>Edutuj, zmien, usun</a>';
}
?>

dalsza czesc szablonu ....


Aplet 'user' ma metoda hasGroup która sprawdza czy user ma daną grupe:

  1. <?php
  2.  
  3. Aplet user extends Apos_View_Aplet {
  4.  
  5. public function hasGroup($name)
  6. {
  7. return $this->user->hasGroup($name);
  8. }
  9. }?>

Napisany przez: LBO 15.09.2006, 21:43:08

Eeesshh, w Zend Framework jeszcze apletów nie wprowadzili :/ Chociaż w SVN jest już Zend_Acl i zarządzanie uprawnieniami jest łatwiejsze. Będzie trzeba się posiłkować zmiennymi dopisanymi do szablonu.

Napisany przez: Apo 15.09.2006, 22:42:03

W ZF są helpery, a u mnie dziala to na tej samej zasadzie tyle że jak już mówiłem Aplet ma dostęp do HttpContext, klasy Usera, Modelu itp, a zwykły helper takich żeczy nie ma smile.gif

Napisany przez: LBO 16.09.2006, 11:23:44

No nie wiem, nie wydaje mi się, że helpery mogą służyć do tego. Aplet to aplet (czy komponent jak kto woli). Ale można się pokusić o napisanie czegoś podobnego.

Kontekst można uzyskać łatwo:

  1. <?php
  2. Zend_Controller_Front::getInstance(); // Na takiej zasadzie działa Zend_View_Helper_Url - jeszcze w inkubatorze.
  3. ?>

Dostęp do dodatkowych klas i modułów również:
  1. <?php
  2. Zend::register(); // zapisywanie OBIEKTU w rejestrze Frameworka
  3. Zend::registry(); // odczytywanie OBIEKTU z rejestru.
  4. ?>


Cytat
tyle że jak już mówiłem Aplet ma dostęp do HttpContext, klasy Usera, Modelu itp, a zwykły helper takich żeczy nie ma


Heeh, ale kontrolery też nie, przyzwyczaiłem się, że w tej fazie projektu, szkielet aplikacji trzeba stworzyć samemu.

Napisany przez: Prph 17.09.2006, 11:36:16

Cytat(Apo @ 15.09.2006, 21:42:03 ) *
W ZF są helpery, a u mnie dziala to na tej samej zasadzie tyle że jak już mówiłem Aplet ma dostęp do HttpContext, klasy Usera, Modelu itp, a zwykły helper takich żeczy nie ma smile.gif


Podobnie u mnie, ale helpery maja dostep do aktualnego widoku (tj. do widoku, ktory je wywoluje). Dodalem taka funkcjonalnosc, poniewaz byla mi potrzebna. Mam dwa helpery - css oraz js - ktore pozwalaja zaladowac css i javascript do szablonu. Mowa tutaj o widoku dekorujacym, w ktorym mam szablon glowny (Main.php) zawierajacy np. naglowek, menu itp.

Zachecam do zapoznania sie z moim frameworkiem Rapide. Pisalem o nim na forum http://forum.php.pl/Framework-Rapide-Framework-t53356.html. W skrocie powiem, ze Rapide jest podobny do Zend Framework, poniewaz organizacja zostala oparta na tej spotykanej w ZF. Framework jest znacznie bogadszy od ZF i zawiera m.in. aplety, helpery, acl, user, language.

Pozdrawiam, Adrian.

Napisany przez: J4r0d 24.11.2006, 18:40:34

Cytat(rzseattle @ 28.01.2004, 16:03:04 ) *
(...)
1) Router "dekoduje" url i wysyla do kontrolera jak akcje ma uruchomic
2) Kontroler sprawdza czy akcja potrzebuje zalogowania , czy jest plik akcji itd...
3) Kontroler uruchamia akcje.
(...)

Kontroler to nic innego jak switch
  1. <?php
  2. switch(http://www.php.net/intval($_GET['wartosc_parametru']))
  3. {
  4. case 1:
  5. case 2:
  6. case 3:
  7.  etc..
  8. }
  9. ?>

czyli router i kontroler to jest to samo.. :/


Cytat(bumelang @ 4.02.2004, 15:30:08 ) *
(...)
Działa to tak: użytkownik wysyła żądanie w sensie HTTP, np. wypełnia jakiś formularz i klika "Submit", gdzie akcja formularza jest ustawiona na skrypt, w którym znajduje się kontroler. Ten łączy się z modelem, wywołuje tam jakieś metody biznesowe i gdy te zwrócą mu już efekty swojej pracy, to w zależności od tego, jakie one są, przekazuje to wywołanie do odpowiedniego widoku, czyli odpowiedniej strony php (która może być napisana w Smarty). W php w najprostszym wariancie może być to po prostu
  1. <?php
  2. /* Kontroler */
  3. if($model->zaloguj($login, $haslo) == SUCCESS) //wywołanie modelu
  4. include("strona_glowna.php"); // wywołanie widoku
  5. else
  6. include("blad.php"); // wywołanie innego widoku
  7. ?>

(...)

Z całym szacunkiem ale ja dopiero zagłębiam się w MVC. Rozważmy inny przykład:
Na stronie index.php pojawia się tylko okienko logowania. Jeśli login i hasło są prawidłowe to użytkownik sotaje przenoszony do system.php, gdzie ma dostęp do modułów (tylko do tych na które pozwalają uprawnienia przypisane danemu użytkownikowi w bazie danych).

Jakby to wyglądało?
1. Uruchamiany jest widokLogowanie
-użytkownik wpisuje login i hasło po czym naciska submit
2. Kontroler pobiera login i hasło i przekazuje do modelu w formie zalogujUser($login, $haslo);
3. Jeśli dane są poprawne to pobierz uprawniena danego usera i załaduj widokSystem
- w przeciwnym wypadku wyświetl WidokBłąd

Dobrze myślę? Czyli widok jest wywoływany jeszcze zanim kontroler sprawdzi podejmie decyzje o logowaniu..

Napisany przez: mariuszn3 24.11.2006, 18:41:53

Router jest częścią kontrolera, która tłumaczy url na zmienne na podstawie których dalszy algorytm kontrollera wywołuje akcję.

Napisany przez: NuLL 24.11.2006, 18:54:59

Cytat(mariuszn3 @ 24.11.2006, 18:41:53 ) *
Router jest częścią kontrolera, która tłumaczy url na zmienne na podstawie których dalszy algorytm kontrollera wywołuje akcję.

Router nie powinien byc czecia kontrolera gdyz z adresu mozna wyciagnac troche wiecej niz tylko akcje do wykonania. Router powinien nalezyc do requestu i z adresu wyciagac zmienne getowe.

EDIT - teraz zalapalem tongue.gif

Napisany przez: mariuszn3 24.11.2006, 19:03:43

NULL myślę, że za bardzo rozwarstwiasz pewne rzeczy.. jeśli nie częścią kontrolera to częścią czego? Widoku czy Modelu?
Kiedy piszę o kontrolerze piszę o jednej z trzech warstw abstrakcji, która odczytuje żądanie (którego nośnikiem jest między innymi adres url) a nie o konkretnej jednej klasie.

Napisany przez: J4r0d 24.11.2006, 20:02:23

Cytat(Seth @ 17.12.2004, 13:12:42 ) *
@hamlecik:
Ja to robie w ten sposob:
Mam jeden glowny kontroler, ktory pobiera dane od usera i na ich podstawie odpala odpowiednia akcje, ktora jest w konfigu.

I za każdym razem, kiedy wywoływana jest akcja odczytujesz konfiga? Czy to nie zwalnia aplikacji?
Czy może gdzieś na samym początku (ale gdzie?) parsujesz konfiga i każdy parametr ustawiasz jako zmienną sesyjną, żeby nie gubic przy przeładowaniach strony?

Napisany przez: UDAT 26.11.2006, 13:12:37

Cytat(J4r0d @ 24.11.2006, 20:02:23 ) *
I za każdym razem, kiedy wywoływana jest akcja odczytujesz konfiga? Czy to nie zwalnia aplikacji?
Czy może gdzieś na samym początku (ale gdzie?) parsujesz konfiga i każdy parametr ustawiasz jako zmienną sesyjną, żeby nie gubic przy przeładowaniach strony?

Raz. Wystarczy cache'owanie konfiga.
Ustawianie jako zmiennej sesyjnej mija się z celem, zmiana conifg'u może nastąpić teraz jednak dopiero za np. 12h zmienii się to dla user'a który będzie mocno używał twoją aplikację.

Dwa. Jak trzymasz konfiga w bazie to zapis do zmiennych sesyjnych jest nieopłacalny wydajnościowo, możesz mieć ogromnego config'a ale potrzebować 1% danych z niego.

Napisany przez: J4r0d 26.11.2006, 13:15:54

Cytat(UDAT @ 26.11.2006, 13:12:37 ) *
Raz. Wystarczy cache'owanie konfiga.

Ale odczyt z pliku co jakąś akcje też obciąża.

Cytat(UDAT @ 26.11.2006, 13:12:37 ) *
Ustawianie jako zmiennej sesyjnej mija się z celem, zmiana conifg'u może nastąpić teraz jednak dopiero za np. 12h zmienii się to dla user'a który będzie mocno używał twoją aplikację.

Wyjaśnij to bo zamotałeś i nie wiem o co Ci chodzi..

Cytat(UDAT @ 26.11.2006, 13:12:37 ) *
Dwa. Jak trzymasz konfiga w bazie to zapis do zmiennych sesyjnych jest nieopłacalny wydajnościowo, możesz mieć ogromnego config'a ale potrzebować 1% danych z niego.

Tu się zgodze..

Napisany przez: NuLL 26.11.2006, 17:57:53

Cytat
Ale odczyt z pliku co jakąś akcje też obciąża.

Tysieczne czesci sekundy winksmiley.jpg

Napisany przez: J4r0d 2.12.2006, 11:16:30

Zauważyłem w swoich projektach, że duża część kodu powtarza się. Przyglądałem się frameworkom, które były prezentowane przez użytkowników tego forum jak i innym. Podoba mi się np, Rapide ale jak na razie jest za duży dla moich potrzeb. Chcę spróbować napisać sobie zestaw kilku prostych klas i zaimplementować MVC. Czytałem ten temat mnóstwo artykułów i każdy inaczej rozumie ten wzorzec. Spróbuje zebrać to co zrozumiałem - jeśli się mylę to mnie poprawcie:

1. Model - odpowiedzialny za logikę biznesową, jest jedyną częścią aplikacji, która przechowuje dane. Sposób przechowywania jest obojętny (baza, plik, itp.) Dobrym sposobem implementacji modelu jest utworzenie odzielnej klasy dla każdego logicznego obiektu, np. klasa Produkty, która będzie pobierać dane o produktach lub klasa Uzytkownicy, która będzie pobierać listę zarejestrowaych użytkowników... Jeśli dane są przechowywane w bazie danych, zazwyczaj jedna klasa odpowiada jednej tabeli lub kilku tabelom ściśle powiązanych ze sobą.

Spotkałem się też z twierdzeniem, że dobrze zaprojektowany model powinien być odporny na wewnętrzne zmiany w strukturze tabel bazy. I tu uważam, że jest to ciężkie do zrealizowania. Bo jeśli klasa Użytownicy pobiera dane wskazanego użytkownika (np. imie, nazwisko, pesel, data zarejestrowania itp, to po zmianie struktury trzeba zmieniać zapytanie..)


Widok - odpowiada za prezentacje danych. Wykorzystuje model do pobrania danych. Widok powinien utworzyć instacje klas modelu i wywołać metody odpowiedzialne za pobranie danych. Widok nie może modyfikować danych. Widok nie jest szablonem, pobiera dane i includuje odpowiedni szablon.

Kontroler - na podstawie analizy żądania http powinien zdecydować jakie akcje wykonać i jaki widok wyświetlić. Kontroler to jeden główny plik zbudowany na switchu..


PYTANIA:
1. Jeśli widok nie może zmieniać danych, to jak odbywa się aktualizacja (np. zmień hasło użytkownikowi) ?

Kontroler odbiera żądanie zmień hasło i wywołuje odpowiednią akcje, która uruchamia widok z formularzem zmiany hasła. Ten formularz wywołuje.. co? Znowu kontroler czy inną akcje, która zmienia hasło i odpala widok z komunikatem udanej zmiany/nieudanej zmiany ?

2. Wiele z osób torzy jeszcze klasy Request i Response. Po co?

Napisany przez: NuLL 4.12.2006, 13:12:05

Cytat
Kontroler to jeden główny plik zbudowany na switchu..

laugh.gif U mnie projekcie wartwa kontrolera to 8-10 klas - zalezy od jego konfiguracji

Ja warstwy modelowej nie stosuje wiec sie nie znam winksmiley.jpg

Cytat
2. Wiele z osób torzy jeszcze klasy Request i Response. Po co?
Nikt ich nie wymaga. A po co je sie robi questionmark.gif Aby zadanie HTTP mialo ladna otoczke.

Napisany przez: Sh4dow 4.12.2006, 15:36:23

Cytat(J4r0d @ 2.12.2006, 11:16:30 ) *
...
1. Jeśli widok nie może zmieniać danych, to jak odbywa się aktualizacja (np. zmień hasło użytkownikowi) ?

Kontroler odbiera żądanie zmień hasło i wywołuje odpowiednią akcje, która uruchamia widok z formularzem zmiany hasła. Ten formularz wywołuje.. co? Znowu kontroler czy inną akcje, która zmienia hasło i odpala widok z komunikatem udanej zmiany/nieudanej zmiany ?

2. Wiele z osób torzy jeszcze klasy Request i Response. Po co?

ad. 1 Sam napisałeś Model zajmuje sie całą logiką, On otrzymuje polecenie wykonania zmiany hasła, zwraca powiedzmy wartosc bool ktora okresla czy sie to udalo czy nie a widok na tej podstawie podaje wiadomosc z potwierdzeniem lub błędem.

ad. 2 Jesli chodzi klasy Request/Response to czesto jest to połączone z jakimiś filtrami, validatorami. Pobierajac jakas dane powiedzmy POST mozesz rzadac ze to ma byc liczba i jesli sie nie zgadza zwracasz false/null/error (dowolnie, w zaleznosci od uznania) lub tez mozesz przefiltrować zmienna i wszystkie nie cyfry wywalici znowu cos tam zwrocic.

Napisany przez: J4r0d 4.12.2006, 18:04:24

Początkowo kontroler wydawał mi się najłatwiejszy (myliłem się). Dorwałem frameworka i załapałem widok, model i jak to działa. Wiem jak ogólnie działa kontroler ale nie mogę załapać jak napisać i połączyć w wspólne działanie Request/Response.. :/

Mógłby mi to ktoś wyłumaczyć prostym przykłądem (dwie przykładowe klasy i jak to połączyć)?

Napisany przez: jastu 8.01.2007, 14:24:57

Przyłącze się do prośby ... ja jestem juz po wybieraniu z urla potrzebnych informacji,operowania na nich , problem mam natomiast z generowaniem wyniku operacji .


//edit
Jak klasa specjalizująca może dodawać funkcjonalności nadklasie ? (jeśli dobrze rozumiem o co chcę zapytać )

Czy mógłby ktoś naszkicować diagram (uml) do elementu głównego dla wzorca MVC ( np obiekt page jako obiekt który powstaje z innych klas dzięki dziedziczeniu,kompozycji bądź innch) , poglądowy - jak połączyć klasy ? . Rozumiem częściowo jak klasy mogą przekazywać sobie wyniki operacji na obiektach , ale jeszcze mi czegoś brakuje

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)