![]() |
![]() ![]() |
![]() |
![]()
Post
#1
|
|
Grupa: Zarejestrowani Postów: 45 Pomógł: 0 Dołączył: 15.09.2008 Ostrzeżenie: (0%) ![]() ![]() |
Witam,
uprzedzam, że przeczytałem temat przypięty wraz z odnośnikami i niewiele mi to pomogło - niestety. Mam trzy pytania odnośnie tego wzorca - jeżeli tworzę aplikację web'ową, to: 1. Czy kontroler jest samym plikiem (index.php), czy dopiero plik główny go inicjuje? 2. Jak jest z widokiem? Czy HTML jest zwracany do kontrolera, czy do pliku głównego? (przy opcji, że kontroler trzeba wcześniej załączyć) 3. Czy widok jest załączany przez kontroler, czy przez plik główny? (również przy drugiej opcji) |
|
|
![]()
Post
#2
|
|
Grupa: Zarejestrowani Postów: 690 Pomógł: 81 Dołączył: 6.04.2005 Skąd: Szczecin Ostrzeżenie: (0%) ![]() ![]() |
ad1. index.php to bootstrap, czyli plik, który odpowiada za ustawienie aplikacji tzn dołączenie potrzebnych bibliotek etc oraz odpalenie kontrolera, który został wywołany
ad2. widok zwracany jest użytkownikowi, czyli najpierw odpalany jest bootstrap, który ładuje odpowiedni kontroler, kontroler pobiera dane z modelu i wysyła je do widoku, widok składa wsio w całość i prezentuje userowi ad3. przez kontroler |
|
|
![]()
Post
#3
|
|
Grupa: Zarejestrowani Postów: 45 Pomógł: 0 Dołączył: 15.09.2008 Ostrzeżenie: (0%) ![]() ![]() |
OK, jeszcze jedno pytanie (ad2.) - jak to wygląda? Bo kontroler jest klasą, która wywołuje następną klasę (jeżeli dobrze rozumiem). I jak wtedy z widoku przekazać cokolwiek do bootstrapa?
|
|
|
![]()
Post
#4
|
|
Newsman Grupa: Moderatorzy Postów: 2 033 Pomógł: 290 Dołączył: 21.12.2007 Skąd: Łódź ![]() |
Widok juz nic nigdzie nie przekazuje, wywołuje jedynie metodę np. show(), która daje na wyjście gotowy HTML.
|
|
|
![]()
Post
#5
|
|
Grupa: Zarejestrowani Postów: 45 Pomógł: 0 Dołączył: 15.09.2008 Ostrzeżenie: (0%) ![]() ![]() |
Czyli bootstrap inicjuje kontroler, kontroler moduły, a na końcu widok, który korzysta np. z echo?
|
|
|
![]()
Post
#6
|
|
Grupa: Zarejestrowani Postów: 1 182 Pomógł: 115 Dołączył: 4.03.2009 Skąd: Myszków Ostrzeżenie: (0%) ![]() ![]() |
Sprawdź sobie jak to robią popularne frameworki.
|
|
|
![]()
Post
#7
|
|
Developer Grupa: Moderatorzy Postów: 3 045 Pomógł: 290 Dołączył: 20.01.2007 ![]() |
Masz model, kontroler i widok. Kontroler pobiera dane z modelu i przekazuje do widoku, a jak sobie to zaprojektujesz to już Twoja sprawa. Możesz obsługiwać żądania w indexie, a możesz napisać front controller, router, dispatcher itp.
|
|
|
![]()
Post
#8
|
|
Grupa: Zarejestrowani Postów: 952 Pomógł: 154 Dołączył: 20.01.2007 Skąd: /dev/oracle Ostrzeżenie: (0%) ![]() ![]() |
Kontroler nie przekazuje żadnych danych z modelu do widoku. We wzorcu MVC widok jest sam zobligowany je pobierać z modelu, a przesyłanie ich przez kontroler to wymysł twórców Ruby On Rails i podobnych pionierskich frameworków, którzy źle spojrzeli na diagram i co później zostało powielone w milionach egzemplarzy jako obowiązujący dogmat. Nawiasem mówiąc jest to jeden z głupszych pomysłów, bo taki pseudo-MVC nie różni się praktycznie niczym od pisania kodu ciurkiem, gdzie skrypt najpierw sobie pobiera dane z bazy, a później wstawia je w szablon, tyle że w "profesjonalnych frameworkach" pobieranie z bazy nazwano Modelem, szablon Widokiem, a resztę Kontrolerem i dlatego jest to "profesjonalne".
Ten post edytował Zyx 5.02.2010, 15:21:08 |
|
|
![]()
Post
#9
|
|
Newsman Grupa: Moderatorzy Postów: 2 033 Pomógł: 290 Dołączył: 21.12.2007 Skąd: Łódź ![]() |
Kurczę, Zyx, teraz żes mnie zastrzelił (IMG:style_emoticons/default/sad.gif)
http://www.ploug.org.pl/szkola/szkola_5/ma...ly/5_Struts.pdf Czyli prawidłowo skonstruowana architektura MVC powinna wyglądać tak: - index.php ładuje kontroler (nazwijmy go akcja01) - kontroler akcja01 ładuje model akcja01, a ten z kolei tworzy sobie obiekt widoku akcja01 - kontroler akcja01 wywołuje dzialanie01, na podstawie akcji usera (np. kliknięcie na link index.php?akcja=01&dzialanie=01 ) - model realizuje dzialanie01, generuje wyniki i przekazuje je do widoku akcja01, który wyswietla je w miejscu przeznaczonym na rezultat wykonania dzialanie01. Czyli róznica polega na tym, że model gotowych wyników dzialania01 nie zwraca juz do kontrolera, a ten dopiero przekazuje ten wynik do widoku, ale od razu wynik dzialania01 idzie z modelu do widoku, tak? |
|
|
![]()
Post
#10
|
|
Grupa: Zarejestrowani Postów: 952 Pomógł: 154 Dołączył: 20.01.2007 Skąd: /dev/oracle Ostrzeżenie: (0%) ![]() ![]() |
Mniej więcej właśnie o to chodzi. Architektura MVC dla aplikacji WWW (tzw. Model 2) wygląda następująco. Mamy dwa scenariusze:
Użytkownik chce coś zobaczyć Kontroler: - Sprawdza, co zrobił użytkownik - Wybiera odpowiedni widok - Wybiera odpowiedni model - Informuje widok, z jakiego modelu będzie korzystać. Model - Pobiera dane na żądanie widoku Widok - Decyduje o tym, jak wyświetlić dane - Pobiera interesujące go dane z modelu - Zajmuje się obsługą logiki wyświetlania - Wyświetla wszystko Użytkownik chce coś zmienić (formularz) Tutaj w stosunku do klasycznego MVC jest taka modyfikacja, że dane przychodzą do nas w żądaniu HTTP jako pewne zadanie dla kontrolera. Kontroler - Sprawdza, co użytkownik zrobił. - Wybiera model. - Wybiera widok, jeśli potrzeba, albo robi redirect, co technicznie oznacza, że inny kontroler rozpoczyna pracę. - Pobiera dane i przekazuje je do modelu z żądaniem zmiany stanu (czyli np. aktualizacja danych w bazie). - Informuje widok, z jakiego modelu ma korzystać. Model - Zmienia swój stan, czyli dokonuje aktualizacji informacji. - Udostępnia dane. Widok Nie ma bata, w HTTP albo robimy przekierowanie, czyli skaczemy do innego kontrolera, albo musimy coś wyświetlić, dlatego widok dalej działa tak samo. Zasadniczo w klasycznym MVC wmieszany jest jeszcze wzorzec obserwatora na wypadek, gdyby model samoistnie zmienił stan (wtedy może on powiadomić widok, że coś się zmieniło i trzeba odświeżyć ekran), jednak w WWW nie ma to żadnego sensu praktycznego ze względu na budowę protokołu HTTP, dlatego się to pomija. Zauważmy też, że część komunikacji między komponentami realizowana jest za pomocą wywołań odpowiednich metod, a część (np. widok informuje kontroler, że coś się stało) realizowana jest za pomocą żądań HTTP. Dodatkowo należy pamiętać jeszcze o dwóch kretynizmach popełnianych we frameworkach: - Zrównanie modelu z ORM-em. ORM może być wykorzystywany przez model, ale nie może być modelem, bo nie i koniec. Model ma stanowić abstrakcyjny interfejs dostępowy tak, by aplikacja nie musiała się zajmować tym, czy dane idą z bazy czy z plików czy z czegoś innego. Tymczasem we współczesnych frameworkach z technicznego punktu widzenia jeśli będziemy chcieli coś pobrać z czegoś innego niż baza, to pozbawiamy się modelu. Przykład problemu, który to powoduje: mamy jakieś teksty informacyjne wyświetlane w różnych miejscach strony, które zapisane są na sztywno w jakimś pliku. Aplikacja jest rozbudowywana, pojawia się możliwość wprowadzania artykułów i klient chciałby, by w ramach tego mógł też edytować te statyczne teksty. I nagle okazuje się, że zmienia się wewnętrzna reprezentacja danych, a my żeby ją uwzględnić, zmieniamy... kontroler. - Zrównanie szablonów i systemów szablonów z widokiem. No hola hola, a gdzie logika prezentacji? Przecież jak mamy np. stronicowanie, to gdzieś musimy je także skonfigurować, coś się musi zająć obsługą techniczną tego stronicowania, ale ponieważ widok jest szablonem, kod leci do... kontrolera. Coś tu nie gra, kontroler przecież nie powinien zajmować się tym, jak dane są prezentowane, a według mnie obecność stronicowania to specyfika ustaleń między widokiem, a modelem. Poniżej przykład, jak można w takim modelu MVC zbudować coś fajnego. Przyjrzyjmy się CRUD-owi, czyli klasycznemu zestawowi operacji bazodanowych. Mamy listy elementów: newsy, artykuły, użytkowników itd. W "pseudo-MVC" głoszonym przez współczesne frameworki PHP tzw. "szybkość i prostotę tworzenia" uzyskuje się nie za pomocą "pseudo-MVC", tylko narzędzia konsolowego, które automatycznie generuje nam 483827834738 plików, po jednym dla każdej tabeli i które potem musimy ręcznie wypełniać. Tymczasem w prawdziwym MVC możemy zastosować takie podejście: - Tworzymy widok ListView, który pobiera dane z modelu, opakowuje je w listę, dodaje sortowanie po kolumnach i stronicowanie. - Autorytarnie stwierdzamy, że widok ListView może współpracować z modelami implementującymi interfejsy Listable, Sortable, Paginable, ListDefinitions - Za pomocą zawartych w tych interfejsach metod widok pobiera z modelu listę elementów, pobiera informacje o tym, które elementy można sortować, przekazuje informacje o tym, jaka strona wyników go interesuje, zaś przy pomocy ListDefinitions może ściągnąć informacje o tym, jak np. zatytułować kolumny, jak nazywają się wyświetlane byty itd. - Tworzymy 298373 modeli implementujących te interfejsy, każdy pobiera dane ze swojej tabelki i odpowiednio reaguje na wywołania metod w tych czterech interfejsach. Różnica jest kolosalna. Jeśli w takim Zend Frameworku czy innym nagle stwierdzimy, że chcemy wzbogacić interfejs o np. wyszukiwanie, jesteśmy w d..., bo musimy to dopisać z osobna do każdego kontrolera, każdego modelu i każdego widoku dla każdej tabeli. Tutaj dodajemy kolejny interfejs, zmieniamy JEDEN widok, a reszta to poprawki w modelach. O ileż mniej roboty? O ileż większa zgodność z zasadami projektowania obiektowego? Powiem nawet więcej - widok może być inteligentny i posprawdzać sobie, jakie interfejsy implementuje model i na podstawie tego decydować: "aaa, ten model nie implementuje Paginable, więc oznacza to, że tu nie ma być stronicowania". I nagle okazuje się, że możemy diametralnie zmienić funkcjonalność, po prostu dodając lub zabierając interfejsy z modeli. Oczywiście jak piszemy front-end i sztywne ramy mechanizmu CRUD nam nie pasują, musimy napisać inne widoki do konkretnych zastosowań, ale w wielu przypadkach nawet te konkretne zastosowania są na tyle ogólne, że można stworzyć jeden widok pasujący do kilku miejsc i sytuacji. Tak się składa, że robiłem niedawno aplikację w PHP opartą o prawdziwy wzorzec MVC i to, co serwują nam frameworki, nawet do pięt mu nie dorasta. Ironią jest, że jedyny znany mi skrypt poprawnie implementujący MVC to... Joomla. I to jest chyba jedyna dobra rzecz, jaką można powiedzieć o jej kodzie. Jakby ktoś jeszcze nie dowierzał, to podaję pierwszą z brzegu książkę prezentującą właśnie taki sposób działania MVC w aplikacjach WWW, z widokiem komunikującym się bezpośrednio z modelem: Head First Design Patterns, strony 567-575. Ten post edytował Zyx 5.02.2010, 16:56:54 |
|
|
![]()
Post
#11
|
|
Grupa: Zarejestrowani Postów: 45 Pomógł: 0 Dołączył: 15.09.2008 Ostrzeżenie: (0%) ![]() ![]() |
Ciekawa dyskusja się tutaj wywiązała, ale jako laik liczyłbym na jakąś zgodną myśl.
Ciekawa dyskusja się tutaj wywiązała, ale jako laik liczyłbym na jakąś zgodną myśl. |
|
|
![]()
Post
#12
|
|
Newsman Grupa: Moderatorzy Postów: 2 033 Pomógł: 290 Dołączył: 21.12.2007 Skąd: Łódź ![]() |
@Zyx, dziękuję Ci bardzo za wyjaśnienie. W wolnej chwili, jeśli masz takowe, czy mógłbyś zamieścić parę linków do jakiś bardziej szczegółowych opisów tematu? Oczywiście nie omieszkam poszukać, ale może masz coś godnego uwagi, a trudnego w wygooglowaniu.
|
|
|
![]()
Post
#13
|
|
Grupa: Moderatorzy Postów: 2 921 Pomógł: 269 Dołączył: 11.08.2005 Skąd: 127.0.0.1 ![]() |
@Zyx
Wszystko ładnie pięknie, ale to tylko teoria. A jak wiadomo od teorii do praktyki droga daleka. Implementacja MVC w "nowoczesnych" frameworkach, nie jest jakąś tam fanaberią kilku programistów, którzy zapragnęli być pionierami, tylko dobrze przemyślany wybór sztabu ludzi. Przy projektowaniu jakiegoś rozwiązania należy wziąć pod uwagę przede wszystkim koszt*. Jeśli coś można zrobić taniej (co nie znaczy, że gorzej), to dlaczego tego z takiej możliwości nie skorzystać? Ślepe trzymanie się teoretycznych rozważań nie przyniesie nic dobrego. Spowoduje jedynie, że czas wykonania projektu znacząco się wydłuży, a niektóre funkcjonalności nie zostaną wdrożone, ponieważ "tak nie wolno". W prawdziwym świecie MVC oznacza: M - model, czyli klasa/zestaw klas operujących na danych. W projektach, które w rozwoju nie mają zaplanowanej migracji na inne źródło danych lub dodanie nowego źródła danych, mogą bezpośrednio na tym źródle operować. Dobrym zwyczajem jest jednak oddzielić model od bezpośredniego dostępu do danych. V - widok. Miejsce, w którym wyświetlane są dane. I nic więcej. C - kontroler. Odpowiada za przekazanie danych do widoku (nazywane inaczej wskazaniem z jakiego modelu skorzystać). Obok "wielkiej trójcy" jest jeszcze takie coś jak dispatcher, po naszemu dyspozytor, czyli obiekt odpowiedzialny za odpowiednie rozprowadzenie ruchu między kontrolerami oraz za poprawne przekazanie danych, które zostały wysłane przez użytkownika. * - nie chodzi tylko o pieniądze. Do kosztu można doliczyć czas, utrzymanie, zasoby serwera, itp. Zanim zaczniesz/zaczniecie na mnie wieszać psy, za głoszenie herezji, określmy, czy rozmawiamy na poziomie akademickim, czy praktycznym. I w jakim kontekście? PHP, inny język, czy ogólnie. |
|
|
![]()
Post
#14
|
|
Grupa: Zarejestrowani Postów: 2 885 Pomógł: 463 Dołączył: 3.10.2009 Skąd: Wrocław Ostrzeżenie: (0%) ![]() ![]() |
To zacznijmy od tego, że nie ma jednej, a nawet jednolitej implementacji/definicji wzorca mvc, są tylko nakreślone ogólne ramy i zasada działania. Z tego powodu nie powinniśmy rozmawiać, że coś odbiega od standardu, bo takowego po prostu nie ma, jest tylko mniej lub bardziej ogólna koncepcja, której wytyczne i wymagania są w taki czy inny sposób realizowane. Tymczasem rozwiązania frameworkowe mają - powiedzmy - odchyły od tych nakreślonych ram, z powodów, o których wspomniał ~batman - czyli upraszczając - skrócenie czasu wytwarzania kodu i "rozkmina" pod kątem RAD (rapid application development) a co za tym idzie - pieniądze. Ale powracając do MVC - jednym z głównych założeń jest podzielenie aplikacji na łatwo zarządzalne i jak najbardziej niezależne warstwy. Zastosowanie mvc ułatwia zarządzanie kodem, jego konserwację i... znowu pieniądze - im kod łatwiejszy w konserwacji tym tańszy w utrzymaniu. Często właśnie koszty wieloletniej konserwacji kodu kilkunastokrotnie przewyższają początkowy koszt jego wytworzenia. Ogólnie dyskusja ciekawa, niestety - temat rzeka.
// edit ach... polecam lekturę tematu na forum Ten post edytował darko 5.02.2010, 23:48:34 |
|
|
![]()
Post
#15
|
|
Grupa: Zarejestrowani Postów: 2 291 Pomógł: 156 Dołączył: 23.09.2007 Skąd: ITALY-MILAN Ostrzeżenie: (10%) ![]() ![]() |
Cytat Kontroler nie przekazuje żadnych danych z modelu do widoku. We wzorcu MVC widok jest sam zobligowany je pobierać z modelu, a przesyłanie ich przez kontroler to wymysł twórców Ruby On Rails i podobnych pionierskich frameworków, którzy źle spojrzeli na diagram i co później zostało powielone w milionach egzemplarzy jako obowiązujący dogmat. Ja do pionerow nie naleze ale pokaz gdzie jest napisane ze "prawdziwe" MVC dziala tak a nie inaczej. Jak juz napisal @batman,@darko ogolna definicja MVC to niezalezne bardziej lub mniej warstwy od siebie lepiej jak sa bardziej niezalezne a implementacja zalezy od programistow. Twoje rozwiazanie jest lepsze bo wszystko robi sie prawie automatycznie ale zobacz ile potrzeba roboty. Dyskusja podobna do tego jak implementowac plugin'y w aplikacjach mamy definicje plugin'a implementacja jest dowolna po co robic jakis super system plugin'ow z jednolitym API itp... jak sama aplikacja jest latwa i jako tako nie potrzeba tyle kombinowac by dzialala. |
|
|
![]()
Post
#16
|
|
Grupa: Zarejestrowani Postów: 952 Pomógł: 154 Dołączył: 20.01.2007 Skąd: /dev/oracle Ostrzeżenie: (0%) ![]() ![]() |
Rozmawiamy na poziomie aplikacji WWW w ogóle, poziom częściowo akademicki, częściowo praktyczny.
Marcio, Batman -> pokazałem chyba jasno, GDZIE jest napisane, że interakcja między elementami MVC zachodzi tak, jak podaję. Jest jeden link, jest książka i są katalogi wzorców projektowych. Ponieważ widocznie ciężko jest poszukać i sprawdzić, podaję gotowe odnośniki: http://java.sun.com/blueprints/patterns/MVC-detailed.html http://martinfowler.com/eaaCatalog/modelViewController.html + szczegółowy opis w książce Patterns of Enterprise Application Architecture wydanej także w Polsce. Pokażcie mi teraz Wy, gdzie w tych opisach jest jakiekolwiek słowo, że dane z modelu mają iść przez kontroler? Gdzie jest napisane, że widok TYLKO wyświetla dane? Ja widzę, że też je pobiera bezpośrednio z modelu. Cytat Jak juz napisal @batman,@darko ogolna definicja MVC to niezalezne bardziej lub mniej warstwy od siebie lepiej jak sa bardziej niezalezne a implementacja zalezy od programistow. Ogólna definicja mówi nie tylko, że są trzy warstwy, bo gdyby to się do tego sprowadzało, to każdy po podstawowym kursie PHP tworzyłby aplikację MVC. Zabronisz mu nazwać skryptu kontrolerem, funkcji generującej kod HTML widokiem, a wywołań mysql_query() modelem? Ogólna definicja określa też podstawowe zależności, jakie powinny zachodzić między nimi, natomiast nie precyzuje sposobu ich wykonania. I tu dopiero wkracza implementacja, która zależy od programistów. Macie rację, wzorzec to ogólna definicja, ale definicja precyzuje nie tylko, CO powinno się znaleźć, ale JAK powinno ze sobą współpracować. Czy wzorzec obserwator byłby dalej obserwatorem, gdybyśmy wzięli dwie klasy i jedną nazwali obserwatorem, a drugą obserwowanym i nie zapewnili komunikacji, jaką ten wzorzec między nimi wymaga? Cytat Wszystko ładnie pięknie, ale to tylko teoria. A jak wiadomo od teorii do praktyki droga daleka. Implementacja MVC w "nowoczesnych" frameworkach, nie jest jakąś tam fanaberią kilku programistów, którzy zapragnęli być pionierami, tylko dobrze przemyślany wybór sztabu ludzi. W porządku. Chcą tak robić, niech robią, tylko niech nie wmawiają ludziom, że to jest MVC. Cytat Przy projektowaniu jakiegoś rozwiązania należy wziąć pod uwagę przede wszystkim koszt*. Jeśli coś można zrobić taniej (co nie znaczy, że gorzej), to dlaczego tego z takiej możliwości nie skorzystać? Ślepe trzymanie się teoretycznych rozważań nie przyniesie nic dobrego. Spowoduje jedynie, że czas wykonania projektu znacząco się wydłuży, a niektóre funkcjonalności nie zostaną wdrożone, ponieważ "tak nie wolno". Jakieś dowody, że gdyby zastosowali się do wskazań wzorca MVC, to byłoby inaczej? To, co napisałeś, jest suchym sloganem, który można podpiąć właściwie pod wszystko. Podaj mi choć jeden powód, na którym opierasz swoje przesłanki, że gdyby gotowy framework implementował MVC i udostępniał narzędzia RAD z nim współpracujące, to koszt i czas stworzenia aplikacji byłby większy w stosunku do tego, co się implementuje obecnie. Skoro nie ma żadnego przyzwoicie napisanego frameworka MVC, a jest mnóstwo frameworków pseudo-MVC, to jest raczej oczywiste, które rozwiązanie wypada lepiej w zestawieniu czas-koszty. Ale gdyby był? Ja twierdzę, że prawdziwy MVC by wygrał i opieram to na doświadczeniu, gdyż tak się składa, że dane mi było pisać aplikację WWW zarówno jedną, jak i drugą techniką. - Framework może dostarczać gotowe standardowe widoki, np. do CRUD, od razu implementujące stronicowanie, sortowanie itd. Narzędzia RAD mogą od razu generować modele, które z nimi współpracują, dzięki dobrze zdefiniowanym interfejsom. - Jeśli to samo będziemy generowali w pseudo-MVC przy pomocy narzędzia RAD, gdyby standardowa definicja nam nie pasowała, musimy stworzyć własne narzędzie RAD, a to, co już jest wygenerowane, musimy przepisać. Tutaj czegoś takiego nie ma. - Pseudo-MVC razem z olaniem zasad interakcji między trzema literkami wyrzucił też zasady precyzujące, gdzie powinny pracować poszczególne podsystemy. Powoduje to, że nie bardzo wiadomo, gdzie co umieszczać i (mówię o rzeczach w stylu formularzy, ACL, itp. itd): * Każdy programista pisze inaczej, a my werbując nowego człowieka musimy go wdrożyć "w nasz system". * Trudne wejście do technologii. Zauważ, ile nowi programiści mają pytań. Gubią się w tym wzorcu, nie wiedzą, co gdzie umieszczać, mają wiele wątpliwości co do zasady jego działania tym bardziej, że się wmawia im, że to jest MVC, tymczasem działa to tak samo, jak ich wcześniejszy teoretycznie-nie-MVC-kowy kod z tą różnicą, że pobieranie danych z bazy się nazywa modelem, a wyświetlanie widokiem. Tu widać także, do czego prowadzi olanie definicji wzorca, bo tak się składa, że w opisie MVC wiele z tych kwestii jest jasno i klarownie wyjaśnionych. * Zamiast sięgnięcia do wzorca, tworzy się jakieś prowizoryczne nakładki w stylu filtrów, helperów, pluginów, tyle że każdy framework robi to po swojemu, nazywa po swojemu, definiuje po swojemu. - Narzędzia RAD mogą wygenerować Ci co najwyżej CRUD. Przechodzisz do front-endu, który najczęściej ma już dość zróżnicowaną strukturę i musisz klepać wszystko samodzielnie. Tutaj pseudo-MVC przestaje już być pomocny, bo elementy modelu (ORM) walają się po kontrolerach, widoki są powiązane z konkretną akcją i część ich logiki też leży w kontrolerze. Jeśli chcemy mieć możliwość ponownego wykorzystania kodu, musimy ją sobie napisać sami. To ma być tańsze, prostsze i szybsze? - Gdy przestaniemy utożsamiać widok z systemem szablonów, a model z ORM-em, technologia stanie się bardziej elastyczna. W obecnych frameworkach wymiana np. standardowego ORM-a na Doctrine, albo standardowego systemu szablonów na OPT to koszmar wymagający obudowania niemal całego systemu MVC rozmaitymi nakładkami, które praktycznie uniemożliwiają korzystanie z narzędzi RAD. W dodatku nie możemy np. użyć biblioteki wirtualnego systemu plików w roli modelu, bo z punktu widzenia frameworka to nie jest model (IMG:style_emoticons/default/smile.gif) . I nawiasem mówiąc w Javie łączenie widoku bezpośrednio z modelem jest normą i jakoś nikt nie narzeka, że jest to droższe, mniej efektywne itd. Dodam jeszcze moje doświadczenie. Zacząłem korzystać z Zend Frameworka w 2006 roku, później pisałem m.in. w Kohanie. Po trzech latach dalej miałem mnóstwo wątpliwości, czy poszczególne elementy umieszczam we właściwym miejscu. Każdy eksperyment kończył się tym, że coś mi ciągle nie pasowało, ciągle coś nie było tak, jak być powinno, a cały kod był albo obudowany jakimiś cudacznymi konstrukcjami obiektowymi mającymi zapewnić wielokrotne wykorzystanie kodu, albo - jeśli trzymałem się "zaleceń" frameworka, nie różnił się specjalnie zasadą działania od kodu, który pisałem przed erą frameworków. Ot, pobieram dane z bazy, przetwarzam i pakuję do szablonu. A najgorsze było to, że wszędzie walono pustymi sloganami "tańsze i szybsze tworzenie aplikacji", tylko chyba w jakimś innym wymiarze. Dla mnie jedyna różnica była taka, że pod maską był ZF, Kohana, Yii, Symfony czy coś innego, a poza obecnością RAD i paru gotowych rzeczy, jak ACL, ORM itd. wszystko pisało się dokładnie tak samo. Później jakoś tak się złożyło, że musiałem coś w Joomli zrobić i przyszło olśnienie. Gdy widok połączyłem od razu z modelem, przyszło olśnienie i w parę dni miałem rozwiązanie wszystkich problemów, jakie napotykałem przy pseudo-MVC. |
|
|
![]()
Post
#17
|
|
Grupa: Moderatorzy Postów: 2 921 Pomógł: 269 Dołączył: 11.08.2005 Skąd: 127.0.0.1 ![]() |
~Zyx
Musisz pamiętać, że PHP != Java i implementacja MVC w obu językach będzie się różnić. Chociażby wspomniany wzorzec obserwatora. PHP działa od załadowania skryptu, do załadowania skryptu. Wszystkie sztuczki polegające na zapisie stanu aplikacji w sesji, czy ciasteczkach są tak naprawdę okrętką na brak wymaganej funkcjonalności. Napisałeś, że Joomla ma dobrze zaimplementowany MVC. I tylko to jest dobrze zrobione w tym CMS. Wystarczy sprawdzić opinie na temat reszty kodu. O tak właśnie koszt mi chodzi. Podałeś linka do dokumentacji Javy, w której opisane jest jak działać powinien MVC. Szkoda tylko, że opisano MVC w wersji Java. Ja wolę wersję dostarczoną przez Microsoft - http://www.asp.net/learn/mvc/tutorial-02-cs.aspx. W tej wersji kontroler służy do pobrania danych z modelu i przekazuje je (nie bezpośrednio) do widoku. Możemy spierać się, czyja racja jest "mojsza", ale nie ma większego to sensu. Jeśli mamy dyskutować na temat MVC powinno zostać ustalone, że mówimy tylko o PHP i o możliwościach tego języka. |
|
|
![]()
Post
#18
|
|
Grupa: Zarejestrowani Postów: 2 291 Pomógł: 156 Dołączył: 23.09.2007 Skąd: ITALY-MILAN Ostrzeżenie: (10%) ![]() ![]() |
~Zyx Musisz pamiętać, że PHP != Java i implementacja MVC w obu językach będzie się różnić. Chociażby wspomniany wzorzec obserwatora. PHP działa od załadowania skryptu, do załadowania skryptu. Wszystkie sztuczki polegające na zapisie stanu aplikacji w sesji, czy ciasteczkach są tak naprawdę okrętką na brak wymaganej funkcjonalności. Napisałeś, że Joomla ma dobrze zaimplementowany MVC. I tylko to jest dobrze zrobione w tym CMS. Wystarczy sprawdzić opinie na temat reszty kodu. O tak właśnie koszt mi chodzi. Podałeś linka do dokumentacji Javy, w której opisane jest jak działać powinien MVC. Szkoda tylko, że opisano MVC w wersji Java. Ja wolę wersję dostarczoną przez Microsoft - http://www.asp.net/learn/mvc/tutorial-02-cs.aspx. W tej wersji kontroler służy do pobrania danych z modelu i przekazuje je (nie bezpośrednio) do widoku. Możemy spierać się, czyja racja jest "mojsza", ale nie ma większego to sensu. Jeśli mamy dyskutować na temat MVC powinno zostać ustalone, że mówimy tylko o PHP i o możliwościach tego języka. To samo chcialem napisac tak samo z tego co widzialem w ASP.NET definicja MVC jest taka sama implementacja juz nie. Ogolnie definicja jest taka sama dla kazdego jezyka gorzej z implementacja. http://pl.wikipedia.org/wiki/MVC nie wiem czy wiki klamie,opisuje pseudo MVC,lub ja czegos nie rozumiem ale wiem jedno jest jasno napisane: Cytat Kontroler jest odpowiedzialny za odczyt danych z bazy danych (utworzenie modelu) i przekazanie ich do warstwy widoku (interfejsu użytkownika) Wiec jak widac chyba w PHP przyjela sie taka a nie inna implementacja MVC. A potem jak ktos chce ja sobie zmodyfikowac nie ma problemu nie dawno ktos tam wymyslil HMVC chyba nawet w KOHANA 3 zostalo zaimplementowane, nie wiem czym sie rozni bo nie czytalem ale jest ta nastepny odram MVC. MNie jak narazie MVC pasuje tak jak je stosuje fakt faktem ze nic wielkiego na moim fw jeszcze nie napisalem jak narazie pisze ogolny system na ktorym bedzie mozna postawic praktycznie wszystko blog,cms,sklep i bog wie co jeszcze. Fajnie by bylo jakbys nie rzucal linkami do Javy tylko podal jakis bardzo prosty kontroler,model i widok zgodny z twoja idea wtedy moze zrozumie o co ci chodzi choc sie domyslam. POzdro. |
|
|
![]()
Post
#19
|
|
Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
Ideę tego wzorca bardzo szybko i fajnie opisuje obrazek z wiki:
Cytat http://upload.wikimedia.org/wikipedia/comm...llerDiagram.svg (niestety nie można wstawić bezpośrednio obrazu SVG)Model-View-Controller concept. Note: The solid line represents a direct association, the dashed an indirect association via an observer (for example). W przypadku PHP ze względu na środowisko w jakim najczęściej ta technologia pracuje - czyli w obrębie protokołu HTTP komunikacja pomiędzy widokiem, a kontrolerem jest mocno ułomna ze względu na sam sposób działania tego protokołu. Cała reszta może być już poprawnie (w sensie bezproblemowo) zaimplementowana. Zauważcie, że kontroler jedynie "wywołuje" model, nie oczekuje od niego żadnych odpowiedzi, rezultatów. Nie przepadam za odsyłaniem do wiki, ale po prostu jest to tam dobrze opisany ten wzorzec: http://en.wikipedia.org/wiki/Model–v...roller#Overview Ponownie - to widok odpytuje model. Kontroler nic mu nie przekazuje, gdyż nie leży to w jego zakresie obowiązków. @Zyx: chciałbym tylko zwrócić uwagę na to, że w Symfony sytuacja z modelem się nieco poprawiła ostatnim czasy. ORM (Doctrine) nie jest już tak silnie utożsamiany z modelem i poprawnie korzystając z niego możemy mieć porządnie zaimplementowany "pseudo-MVC", ale jak ktoś w kontrolerze robi coś w stylu (przykład akurat dot. Propela): Kod $c = new Criteria(); I się dziwi, że nie ma burdel w aplikacji... to już jego wina.
$c->...; $c->...; $c->...; ...Peer::doSelect($c); |
|
|
![]()
Post
#20
|
|
Grupa: Zarejestrowani Postów: 49 Pomógł: 4 Dołączył: 16.07.2008 Skąd: Gdańsk Ostrzeżenie: (0%) ![]() ![]() |
Pierwotnie MVC został określony tak jak przedstawia go Zyx ale od tamtego czasu pojawiło się jego wiele wariantów które są stosowane przez całkiem poważnych programistów w całkiem poważnych aplikacjach. Tak naprawdę na dzień dzisiejszy MVC jest po prostu koncepcją podziału kodu aplikacji na warstwy a nie sztywnym schematem przepływu danych. Najczęściej stosowany na dzień dzisiejszy, w aplikacjach webowych, flow to właśnie widok->kontroler->model->kontroler->widok. Czytałem sporo publikacji na ten MVC, zapoznałem się z kilkoma wariantami, kilka z nich wypróbowałem w praktyce i uważam że najrozsądniejszym z nich jest mówiący o tym, że widok i kontroler powinny być nieświadome logiki zawartej w modelu, kontroler powinien zawierać logikę użytkową a model logikę biznesową, gdzie model otrzymuje i zwraca jedynie suche dane nie przejmując się istnieniem warstwy prezentacji. Mamy dzięki temu elegancką separację poszczególnych warstw i żadna nie jest ściśle powiązana z inną. Przykładem przewagi tego rozwiązania nad tym promowanym przez Zyxa jest możliwość działania aplikacji jako API przez przekierowanie danych w kontrolerze na wyjście zamiast do widoku. W tym innym wypadku musielibyśmy grzebać zarówno w kontrolerze jak i w modelu no i model musiałby mieć świadomość istnienia takiego a nie innego API co mocno ograniczyłoby przenośność kodu.
A o tym, że ORM!=model trąbiłem dawno temu w innym temacie (IMG:style_emoticons/default/winksmiley.jpg) Ten post edytował dr4ko 12.02.2010, 11:27:50 |
|
|
![]()
Post
#21
|
|
Grupa: Moderatorzy Postów: 4 362 Pomógł: 714 Dołączył: 12.02.2009 Skąd: Jak się położę tak leżę :D ![]() |
Ja w swoich pracach najczęściej korzystam z modelu wspomnianego przez dr4ko, gdyż jest moim zdaniem w chwili obecnej najbardziej adekwatny do sposobu działania aplikacji webowych, gdyż zgodna z przepływem informacji. User coś robi w widoku i te działania muszą być przechwycone, rozpoznane, a w tym celu powstał kontroler i to on musi zareagować odpowiednimi danymi wyciągniętymi z modelu. Te idelanie, gdyby mozna przesłać z modelu wprost do widoku. Tyle, że to wiązalo by się ze stworzeniem tak modelu, iżw odpowiedzi do widoku szedł by świetnie sparsowany i dostosowany do jego struktury pakiet danych lub widok zmieniał się dostosowując do formy odpowiedzi modelu. A to nie jest w zasadzie możliwe bez wpływu kontrolera. Najlepsze byłoby pełne uniezaleznienie warstw, gdzie każda mogła się odnosić do pozostałych bez konieczności pośrednictwa trzeciej czyli coś w stylu znaczka recycligu ale dwukierunkowego. Tylko czy jest realne do stworzenia takie coś, gdzie choćby model sam sobie wywołuje widok zależnie od danych?
|
|
|
![]()
Post
#22
|
|
Grupa: Zarejestrowani Postów: 898 Pomógł: 80 Dołączył: 31.05.2008 Ostrzeżenie: (20%) ![]() ![]() |
|
|
|
![]()
Post
#23
|
|
Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
Cytat @Zyx nie zgadzam się z Twoją wizją MVC. Nie lubię takich trochę personalnych docinków, ale... nie ma to jak uargumentowana opinia. Poza tym to nie jest wizja Zyxa, tylko założenia tego wzorca (który nie był tworzony z myślą o "środowisku webowym", w którym to ten wzorzec najczęściej jest skopany).
|
|
|
![]()
Post
#24
|
|
Grupa: Zarejestrowani Postów: 2 291 Pomógł: 156 Dołączył: 23.09.2007 Skąd: ITALY-MILAN Ostrzeżenie: (10%) ![]() ![]() |
Cytat Nie lubię takich trochę personalnych docinków, ale... nie ma to jak uargumentowana opinia. Poza tym to nie jest wizja Zyxa, tylko założenia tego wzorca (który nie był tworzony z myślą o "środowisku webowym", w którym to ten wzorzec najczęściej jest skopany). A gdzie tak jest napisane ze jest dobrze jak to on mowi na wiki na temat MVC pisza inaczej chyba ze mam problemy z czytaniem. |
|
|
![]()
Post
#25
|
|
Grupa: Zarejestrowani Postów: 304 Pomógł: 51 Dołączył: 4.02.2005 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
A gdzie tak jest napisane ze jest dobrze jak to on mowi na wiki na temat MVC pisza inaczej chyba ze mam problemy z czytaniem. Chyba masz problemy z czytaniem: http://en.wikipedia.org/wiki/MVC_Pattern#Overview A konkretniej zdanie "A view queries the model in order to generate an appropriate user interface". Osobną kwestią jest to, że wikipedia to nie zbyt wiarygodne źródło, zwłaszcza jeśli chodzi o takie informacje. Prosty przykład w MVC jaki serwuje ZF, symfony i inne frameworki: Chcemy pobrać stronicowaną listę elementów modelu, w kontrolerze (lub też w modelu) tworzymy obiekt paginatora, mówimy mu aby pobrał takie i takie elementy. Kontroler przekazuje paginator do widoku, który wyświetla to co w nim jest. Konsekwencje: kontroler miesza się w warstwę prezentacji, bo to widok na podstawie modelu powinien decydować o tym czy dane są stronicowane i co ile. Chcemy zmienić liczbę wyświetlanych elementów lub wyłączyć stronicowanie, paradoksalnie musimy edytować kontroler - widok i kontroler wcale nie są niezależne. W implementacji podanej przez @Zyxa to inaczej wygląda, w widoku (na podstawie danych zawartych w modelu) zachodzi decyzja czy dana lista ma być stronicowana, czy też nie. Kontroler jedynie mówi: ten i ten widok ma wyświetlić ten i ten model, nie mówi jak ma go wyświetlić, czy to ma być paginowalna lista, czy też nie. W tej implementacji MVC widok ma więcej zadań i w przeciwieństwie do znanych frameworków dla php potrzebnych będzie wiele klas widoku do różnych zadań. Bezpośrednie powiązanie między widokiem, a modelem jest widoczne zwłaszcza w aplikacjach desktopowych, przykładowo Java i implementacja swingowej tabeli. Klasa JTable - widok, jest też jakaś klasa odpowiedzialna za model tabeli (nie pamiętam nazwy, pewnie JTableModel (IMG:style_emoticons/default/tongue.gif) ). Model przekazuje się bezpośrednio do konstruktora JTable, to widok bezpośrednio pobiera sobie dane z modelu, model może poinformować widok o tym, że zaszła w nim jakaś zmiana, a widok odświeży się (wzorzec obserwatora - pisał o tym @Zyx) - w aplikacjach www taki feature nie jest potrzebny gdyż http jest protokołem synchronicznym. Aplikacje dektopowe, a aplikacje internetowe to całkowicie dwie różne rzeczy, w aplikacjach www (mówię tutaj o frameworkach php) utarło się że to kontroler jest bliżej modelu niż widok, który służy tylko do prezentacji danych. Ma to swoje plusy oraz minusy. |
|
|
![]()
Post
#26
|
|
Grupa: Moderatorzy Postów: 4 465 Pomógł: 137 Dołączył: 26.03.2004 Skąd: Gorzów Wlkp. ![]() |
@Zyx - Co do pobierania danych przez widok: http://www.apostrophenow.com
Szczególnie polecam manual dla developerów. Pozdrawiam |
|
|
![]()
Post
#27
|
|
Grupa: Zarejestrowani Postów: 2 291 Pomógł: 156 Dołączył: 23.09.2007 Skąd: ITALY-MILAN Ostrzeżenie: (10%) ![]() ![]() |
Jak dla mnie to kontroler powinien zawierac cala logike kodu a widok tylko czesc prezentacyjna.
Cytat Kontroler jedynie mówi: ten i ten widok ma wyświetlić ten i ten model, nie mówi jak ma go wyświetlić, czy to ma być paginowalna lista, czy też nie. W tej implementacji MVC widok ma więcej zadań i w przeciwieństwie do znanych frameworków dla php potrzebnych będzie wiele klas widoku do różnych zadań. No wlasnie ja tak mam mam glowny widoku komponentu news a w nim miejsce dla paginacji jesli paginacja jest to tylko podpinam pod dana zmienna z szablonu widok paginacji i po wtokach nie musze ingerowac w kod modelu. |
|
|
![]()
Post
#28
|
|
Grupa: Zarejestrowani Postów: 83 Pomógł: 7 Dołączył: 3.02.2007 Ostrzeżenie: (0%) ![]() ![]() |
Witam
Przepraszam, że odświeżam wątek, ale to chyba jedyny w języku polskim, gdzie jest dość głęboko poruszony ten temat. Mam straszny mętlik, przez te wszystkie niejasności naprawdę zastanawiam się, czy nie zaniechać próby zastosowania. Ogólnie chciałem zacząć programować, nie wiem czy z wykorzystaniem poprawnego modelu MVC czy nie, ale chyba w sposób podobny jak większość osób pojmuje MVC czy pseudo-MVC. Więc: Mam sobie plik index.php (z tego co wyczytałem powinienem nazywać go bootsraper czy jakoś tak). Daruję sobie jednak te wszystkie ładnie brzmiące pojęcia, niezrozumiałe dla 90% ludzi chcących cokolwiek z tego wszystkiego zrozumieć, więc wybaczcie (IMG:style_emoticons/default/biggrin.gif) . Wracając do tego jak ja chciałbym tworzyć swoje aplikacje. Plik index.php, który w moim przypadku jest plikiem, gdzie są same includy. Teraz chcąc być zgodny z MVC czy pseudo-MVC, tylko bardziej po swojemu (IMG:style_emoticons/default/tongue.gif) , tworzę sobie 3 foldery _views, _controllers, _models. Jak już wcześniej pisałem zdaję sobie sprawę, że samo MVC jest różnie interpretowane ale jakąś koncepcję muszę przyjąć więc przyjąłem taką: _views - zawiera czyste pliczki html z wstawionymi danymi z modeli _models - zawiera klasy z samymi zapytaniami do bazy czy odwolaniami do plików textowych, obrazkowych czy jeszcze innych, gdzie znajduja się jakiekolwiek dane _controllers - zawiera klasy sterujące danymi i wysyłające je do odpowiednich widoków. Bardzo chciałbym trzymać się przyjętej przeze mnie ideologii, jednak już w zasadzie na początku napotkałem na dość prozaiczne problemy. Weźmy sobie ot taki prosty przykład jak menu, ktore widok powinien pokazać w taki sposób: i teraz co zrobić, żeby pętelka wyświetliła mi te wszystkie ...widzę 3 wyjścia i nie wiem które powinienem zastosować, każde wg mnie albo odbiega od przyjętego przeze mnie wzorca, albo komplikuje niepotrzebnie i rozdrabnia widoki: przypadek 1: wewalam część kontrolera do widoku (dokładnie kod pętli) jednak cały kod html dzięki temu jest w widoku przypadek 2: pętelka zostaje w widoku, jednak część kodu html musi się znaleźć w kontrolerze. przypadek 3: tworzę osobny, malutki widok i teraz kontroler przy każdym kroku pętli korzysta z tego widoku, po czym na koniec całość wysyła do widoku menu. Wg mnie żadne z tych rozwiązań nie jest poprawne i ciekawi mnie czy jest jakieś inne wyjście, które pozostanie zgodne z przyjętym przeze mnie wzorcem. Jest jeszcze 4 przyadek gdzie ten kawałek html jest w modelu ale to też wydaje mi się bez sensu. Bardzo proszę napraowadźcie mnie jak prawidłowo powinno się to zrobić, po kilku dniach próby zrozumienia o co w tym wszystkim chodzi, coraz bardziej utwierdzam się w przekonaniu, że albo nie nadaję się na webmastera i nie powinienem się wogóle nim określać, albo po prostu coś tutaj nie do końca jest przemyślane, lub wogólę nie pojmuję idei rozdzielenia poszczególnych warstw. PS. Przepraszam, za tak prozaiczny przykład jednak myślę, że zbyt dużo czytamy w artykułach "ciężkich" tekstów z trudnymi przykładami i dlatego też wiele osób rezygnuje z prób dostosowania się do jakichkolwiek ogólnie przyjętych standardów. Bardzo bym chciał, żeby pojawiało się więcej bardzo prostych przykładów opisanych prostym językiem, bez zbednych niezrozumiałych terminów. Jakby ktoś był tak miły i spróbował przedstawić swoją interpretację MVC, jednak na konkretnym bardzo prostym przykładzie, choćby wyswietlenia prostego menu to już wogóle było by bosko (IMG:style_emoticons/default/smile.gif) dziękuję za uwagę i przepraszam jeśli moja wypowiedź nie jest na poziomie tego forum. Ten post edytował WiruSSS 22.03.2012, 02:41:29 |
|
|
![]()
Post
#29
|
|
Grupa: Zarejestrowani Postów: 6 381 Pomógł: 1116 Dołączył: 30.08.2006 Ostrzeżenie: (0%) ![]() ![]() |
PHP jest stosowane w widoku do prostego wyświetlania danych. Czyli pętla będzie prawidłowa. Ale lepiej by było gdybyś zastosował jakiś system szablonów np http://phptal.org gdzie ten kod miałby postać:
Załóżmy. Czytelne, w postaci XMLowej i jeszcze z parsowaniem poprawności. |
|
|
![]()
Post
#30
|
|
Grupa: Moderatorzy Postów: 4 362 Pomógł: 714 Dołączył: 12.02.2009 Skąd: Jak się położę tak leżę :D ![]() |
Najprostsze rozwiązanie? Kontroler przekazuje do widoku tablicę (lub jakąkolwiek formę kolekcji). Elementy tej tablicy (kolekcji) też są tablicami (lub obiektami) i zawierają adres oraz anchor linku. Widok zawiera pętlę wyświetlającą:
Przykładowo: W kontrolerze masz obiekt widoku, który ma składową odpowiedzialną za linki w menu:
W widoku masz do niej dostęp i możesz w pewnym jej fragmencie dać takie użycie: Tyle, że to nie jest już ściśle rzecz mówiąc MVC ale MVP. Nie ma tu bowiem tyle kontrolera, co prezenter, który pobiera dane z modelu i wrzuca do widoku. |
|
|
![]()
Post
#31
|
|
Grupa: Zarejestrowani Postów: 83 Pomógł: 7 Dołączył: 3.02.2007 Ostrzeżenie: (0%) ![]() ![]() |
tak myślałem robić jednak mam odczucie że taki sposób jest jużniezgodny z samym MVC. Co do systemu szablonów może kiedyś się przkonam, jak narazie chciałbym korzystać z jak najmniejszej potrzebnej liczby rozszerzeń.
|
|
|
![]()
Post
#32
|
|
Grupa: Zarejestrowani Postów: 6 381 Pomógł: 1116 Dołączył: 30.08.2006 Ostrzeżenie: (0%) ![]() ![]() |
Tylko pamiętaj że szablony są i tak kompilowane do czystego kodu PHP. Tylko dla jednej odsłony będzie więcej przetwarzania. A porównaj sobie kod obu przedstawionych rozwiązań i pomyśl że masz do przedstawienia coś bardziej zaawansowanego niż tylko ta jedna lista. Później jest taki bajzel że nie da się nad tym panować. Już nie mówiąc że te dane będziesz musiał jeszcze owinąć w htmlentities().
|
|
|
![]() ![]() |
![]() |
Aktualny czas: 5.10.2025 - 17:59 |