Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

2 Stron V   1 2 >  
Reply to this topicStart new topic
> MVC - wcale nie takie cudne?
cicik
post 17.09.2006, 16:53:08
Post #1





Grupa: Zarejestrowani
Postów: 219
Pomógł: 5
Dołączył: 18.07.2006
Skąd: Piekary Śląskie

Ostrzeżenie: (0%)
-----


Człowiek uczy się całe życie.
Od kilku lat wszystkie prace, które wykonuję bazują na szkielecie, który rozbudowuję przez cały ten czas.
Szkielet ten polega na tym, że mam moduły (jeden moduł - jedna klasa), w których zdefiniowane są poszczególne zadania wykonywane przez moduł (jedno zadanie - jedna metoda). Na przykład za dodanie artykułu do bazy odpowiedzialna jest jedna z metod odpowiedniej klasy.

Jedna z zasad OOP mówi, że jeżeli moduł A chce żeby było zrobione coś co dotyczy modułu B to najlepiej niech moduł B zrobi to sam bo on wie najlepiej jak to zrobić. Przykład ilustrjący tę zasade w moim przypadku:

Jest moduł do zarządzania grupami użytkowników. Jednym z jego zadań jest definiowanie praw dostępu.
Prawa są wyswietlane dla każdego zainstalowanego modułu w formie rozwijanego drzewka, w którym użytkownik zaznacza odpowiednie checkboxy. Aby skonstruować to drzewko moduł zarządzajacy grupami includuje każdy moduł. Każdy z includowanych modułów zawiera metodę, która otzrymuje referencę do obiektu symblizującego generowane drzewko. Zadaniem tej metody jest dodanie do drzewka checkboxów konkretnego modułu.

Wszystko działa pięknie, chuczy, buczy, lata i gada.

Tylko jest jeden problem. Każdy z modułów zawiera 500 - 1000 linijek kodu. jeżeli modułów jest powiedzmy 20 to aby wygenerować to drzewko potrzeba przeparsować całą masękodu po to aby w ażdym dołączonym module skorzystać z jednej metody zawierającej pięć linijek.

Masakra!

I oto myślę sobie: "Kurcze MVC pomoże. Każdy moduł rozbiję na szereg akcji, widoków i elementów modułu i będzie fajnie. Przy każdym żądaniu będę includował tylko to co trzeba."
No i faktycznie rozbiłem kilka przykładowych modułów zgodnie z paradygmatem MVC i jest super.
Tylko natrafiłem na problem, z którym nie bardzo umiem dać sobie radę.

Chodzi o formularze w panelu administracyjnym np. do dodawania użytkowników, artykułów etc.)
Generalnie zasada jest taka:

1. Trzeba dodać użytkownika - ładuje się widok z formularzem.
2. User wypełnia formularz, klika guzik
3. uruchamiana jest akcja dodajaca usera. Jęzli formularz był wypełniony dobrze to dane są zapisywane i ładowany jest widok z listą użytkowników. Jeśli zaś dane zostały wpisane źle to ładowany jest ponownie widok z formularzem.

Teoria piękna (jak to zwykle z teoriami bywa), natomiast z praktyką trohe gorzej.
Przy okazji budowania dotychczasowych stron stworzyłem sobie piekny zestaw klas służący do generowania i walidacji formlarzy. Z perspektywy OOP aż miło mi sie na to patrzy bo to jedna z lepszych rzeczy jaka zobiłem.

Mam zestaw klas Form_Select, Form_TextBox itd. (co robią nie będę tłumaczył bo to oczywste).
Służą one do tego aby do obiektu klasy Form_Form (reprezentującej formularz) dodać odpowiednie pola.
Form_Form jest kontenerem dla obiektów klas dziedziczących po klasie Form_Pole (takich jak wymieniony wcześniej Form_Select etc.). Każda klasa reprezentująca pole formularza przyjmuje też obiekt odpowiadający za walidację pola, np. Waidacja_IntegerDodatnie, Walidacja_StringWymagane, Walidacja_Godzina. Te obiekty są odpowiedzialne za to aby to co user wpisze w pole było tym co ma wpisać.

Następnie formularz jest wyświetlany przez wywołanie jego metody construct(). Tworzy ona podstawowy szkielet html i wywołuje metodę construct() dla wszystkich obiektów reprezentujących pola tak aby się wyświetliły w formularzu.

Kiedy user wypełni formularz i go wyśle tworzony jest znowu jego obiekt aby go zwalidować metodą waliduj(). Zwraca ona true jęli formularz był wypełniony prawidłowo.

Jak widać obiekt formularza jest tworzony dwukrotnie (raz aby go wyświetliś i drugi aby zwalidować).
Stworzyłem więc metodę prywatną w module aby generowała odpowiedni obiekt klasy Form_Form (bo po co kod kopiować).

I teraz niech mi ktoś powie gdzie ja mam ja umieścić uwzględniając wzorzec MVC?

a) czemu nie w akcji?
bo pomimo że Form_Form zawiera metodę waliduj(), która jest odpowiednia dla akcji to zawiera metodę construct(), która wyświetla formularz.

cool.gif czemu nie w widoku?
bo pomimo że Form_Form zawiera metodę construct(), która jest odpowiednia dla widoku to zawiera metodę waliduj(), która waliduje formularz.

c) czemu nie w modelu?
bo pomimo, że do wygenerowania formularza potrzebne są informacje z bazy danych (np. lista kategorii, do których może należeć dodawany artykuł) to są tez tam metody construct() i waliduj(), które są odpowiednie dla widoku i akcji.

I co z tym fantem zrobić?
Wszystko spełnia zasady dotyczące tego co mówią podręczniki uczące OOP. Wszystko jest zgodne ze zdrowym rozsądkiem (przynajmniej moim) i wszystkiego sie wygodnie używa. Tylko do MVC jakoś tak daleko... no i to, że praktycznie za każdym wywołaniem skryptu trzeba includować dużo tysięcy linii kodu.

Gdyby ktoś miał pomysł jak rozwiązać mój dylemat z formularzami to bardzo prosze o pomoc.
Tym, którzy doczytali do końca gratuluję.


--------------------
CMS dla Twojej firmy
Wojciech Małota
Go to the top of the page
+Quote Post
cyphelf
post 17.09.2006, 17:55:53
Post #2





Grupa: Zarejestrowani
Postów: 68
Pomógł: 1
Dołączył: 27.03.2006

Ostrzeżenie: (0%)
-----


Można tak:

1. AkcjaAdd - inicjalizacja formularza

2. AkcjaForm - budowanie i wyświetlanie formularza

2. AkcjaValidate - sprawdzanie poprawności danych

3. AkcjaSave - zapisywanie do bazy

I teraz tak. Użytkownik otwiera stronę dodawania elementu czyli w tym przypadku uruchomi akcję Add, która uruchomi akcję Form. Użytkownik wypełni formularz, wyśle go i dane trafią do akcji Validate. Gdy dane okażą się poprawne to zostaną przekazane do akcji Save. Jeśli nie będą poprawne to z odpowiednimi komunikatami zostaną przekazane spowrotem do akcji Form.

Edycja będzie wyglądała podobnie, tylko zamiast akcji Add będziemy mieć akcję Edit, ktora zainicjalizuje dane do edycji (np. wyciągnie je z bazy).

Akcja Save zaktualizuje lub wstawi dane, zależenie od tego czy jest określony numer ID rekordu czy nie.


--------------------
lorem ipsum : polska społeczność zend framework
Go to the top of the page
+Quote Post
cicik
post 17.09.2006, 18:04:54
Post #3





Grupa: Zarejestrowani
Postów: 219
Pomógł: 5
Dołączył: 18.07.2006
Skąd: Piekary Śląskie

Ostrzeżenie: (0%)
-----


Cytat(cyphelf @ 17.09.2006, 18:55:53 ) *
Można tak:

1. AkcjaAdd - inicjalizacja formularza

2. AkcjaForm - budowanie i wyświetlanie formularza

2. AkcjaValidate - sprawdzanie poprawności danych

3. AkcjaSave - zapisywanie do bazy


Można tak tylko w tym przypadku:

Ad2. Bedzie to wygladalo mnie wiecej tak:
echo("<input ...>");

Ad3. a to tak:
if(!is_null($dana1) && ...)

Takie rozwiazania sa w niektorych enginach ale mi sie to nie podoba bo za duzo roboty przy tym jest.
Ja mam obiekt klasy Form_Form posiadajacy dwie metody: construct() i waliduj().
Poniewaz obiekt ten jest potrzebny w dwoch przypadkach (wyswilanie i walidacja) wiec napisalem prosta metode, ktora buduje taki obiekt i go zwraca. I pytanie, w ktorej czesci MVC taka metoda ma byc umieszczona? Formularz jest generowany na podstawie danych z bazy (model), jest walidowany (akcja/kontroler), jest wyswietlany (widok).


--------------------
CMS dla Twojej firmy
Wojciech Małota
Go to the top of the page
+Quote Post
NuLL
post 17.09.2006, 19:10:30
Post #4





Grupa: Zarejestrowani
Postów: 2 262
Pomógł: 21
Dołączył: 3.05.2004
Skąd: Sopot, Krakow, W-wa

Ostrzeżenie: (0%)
-----


Przepraszam za krotko odpowiedziec na php PRO ;-)

A moze by tak kazda akcja to pojedyncza klasa, modul to katalog - i tyle smile.gif


--------------------
Javascript, Coffeescript, Node.js, Mongo, CouchDb, chmury, workery & inne bajery - zycie jest zbyt krotkie aby miec nudna prace :)
Go to the top of the page
+Quote Post
cicik
post 17.09.2006, 19:35:10
Post #5





Grupa: Zarejestrowani
Postów: 219
Pomógł: 5
Dołączył: 18.07.2006
Skąd: Piekary Śląskie

Ostrzeżenie: (0%)
-----


Cytat(NuLL @ 17.09.2006, 20:10:30 ) *
Przepraszam za krotko odpowiedziec na php PRO ;-)

A moze by tak kazda akcja to pojedyncza klasa, modul to katalog - i tyle smile.gif


No właśnie do tego dążę rozpoczynając zabawę z MVC i nie mam z tym najmniejszego problemu.
Jest to rozwiązanie problemu includowania jak najmniejszej ilości kodu.

Jednak mam problem, o którym pisałem, z przyporządkowaniem metody generującej formularz do odpowiedniej warstwy gdyż potrzebuję jej we wszystkich trzech warstwach, a raczej to ta metoda zawiera elementy wszystkich trzec warstw. Takiego czegoś MVC nie przewiduje.


--------------------
CMS dla Twojej firmy
Wojciech Małota
Go to the top of the page
+Quote Post
cyphelf
post 17.09.2006, 19:44:40
Post #6





Grupa: Zarejestrowani
Postów: 68
Pomógł: 1
Dołączył: 27.03.2006

Ostrzeżenie: (0%)
-----


Cytat(cicik @ 17.09.2006, 18:35:10 ) *
Jednak mam problem, o którym pisałem, z przyporządkowaniem metody generującej formularz do odpowiedniej warstwy gdyż potrzebuję jej we wszystkich trzech warstwach, a raczej to ta metoda zawiera elementy wszystkich trzec warstw. Takiego czegoś MVC nie przewiduje.


Powinna ona należeć do warstwy kontrolera, powinna być jedną z jego akcji. W tym przypadku kontroler formularza powinien pobrać z modelu strukturę tabeli, wygenerować pola (np. w postaci obiektu czy tablicy) i przekazać to do widoku, aby widok ubrał to w kod html.


--------------------
lorem ipsum : polska społeczność zend framework
Go to the top of the page
+Quote Post
cicik
post 17.09.2006, 20:01:56
Post #7





Grupa: Zarejestrowani
Postów: 219
Pomógł: 5
Dołączył: 18.07.2006
Skąd: Piekary Śląskie

Ostrzeżenie: (0%)
-----


Cytat(cyphelf @ 17.09.2006, 20:44:40 ) *
Powinna ona należeć do warstwy kontrolera, powinna być jedną z jego akcji. W tym przypadku kontroler formularza powinien pobrać z modelu strukturę tabeli, wygenerować pola (np. w postaci obiektu czy tablicy) i przekazać to do widoku, aby widok ubrał to w kod html.


Po pierwsze formularze wcale nie odzwierciedlają pól w tabeli.
A po drugie gdybym zrobił tak jak mówisz to otrzymał bym coś o czym pisałem już wcześniej:

W widoku wyświetlającym formularz miałbym:
echo("<input ...>");
...
echo('<select ...>');

A w akcji walidującej:

if(!empty($dana1) && $dana2 >0 && ...)

Nie przekonacie mnie, że taka walidacja jest dobra.


W ten sposób kod odpowiedzialny za zachowanie formularza miałbym rozwalony po kilku klasach a coś takiego nie ma nic wspólnego z OOP i reusability.
Zasada jest prosta: chcesz aby formularz sie zwalidował to każ mu się zwalidować, chcesz aby się wyświetlił to każ mu się wyświetlić.

Jeżeli kod walidujący będzie inny od wyświetlającego to aby dodać nowe pole do formularza będę musiał modyfikować dwa pliki, jeżeli będzie to w jednej klasie to wystarczy dodać do obiektu formularza kolejne pole.

Według mnie zasady inżynierii programowania wymagają aby kod zamykać w funkcjonalne moduły.
Formularz i jego zachowanie jest pewnym modułem. Nie da się oddzielić od siebie dwóch zachowań formularza - jego "walidowalności" i "konstruowalności".

Te dwie czynności można oczywiście robic w różnych opcjach ale bezsensem według mnie jest implementowanie tych dwóch zachowań jako czegoś nie związanego ze sobą.


--------------------
CMS dla Twojej firmy
Wojciech Małota
Go to the top of the page
+Quote Post
060156
post 18.09.2006, 11:55:54
Post #8





Grupa: Zarejestrowani
Postów: 146
Pomógł: 0
Dołączył: 9.03.2006
Skąd: Columbus Georgia

Ostrzeżenie: (0%)
-----


W pelni podzielam Twoje uwagi o problemie, ktory opisales ..
Dlatego zastosowalem inne podjescie troche. Polega ono
na tym, ze dla kazdej zmiennej formularza mam druga zmienna
session ktora zawiera informacje o jego walidacji ...
Czyli robie submit formularza a service, ktory go processuje
ustawia zmienne walidacji oraz informacje ze jest blad
i formularze nie moze byc sprocessowany.
Na podstawie tych zmiennych sa wyswietlane informacje
o blednych polach w formularzu ...
pozdrawiam ..
Go to the top of the page
+Quote Post
cyphelf
post 18.09.2006, 12:53:19
Post #9





Grupa: Zarejestrowani
Postów: 68
Pomógł: 1
Dołączył: 27.03.2006

Ostrzeżenie: (0%)
-----


Możesz przechowywać w module listę pól formularza np. w postaci tablicy (przykład w uproszczeniu):
  1. <?php 
  2. $form[] = array(
  3. 'nazwa_pola' => 'imie',
  4. 'typ_pola' => 'input_text',
  5. 'format_danych' => 'string',
  6. 'dlugosc' => 20,
  7. 'wartosc_pola' => '',
  8. );
  9. ?>



Cytat
Po pierwsze formularze wcale nie odzwierciedlają pól w tabeli.
A po drugie gdybym zrobił tak jak mówisz to otrzymał bym coś o czym pisałem już wcześniej:

W widoku wyświetlającym formularz miałbym:
echo("<input ...>");
...
echo('<select ...>');


I teraz w widoku wyświetlającym generowałbyś w jakiejś pętli widok formularza, czyli jego kod HTML, na podstawie listy w takiej postaci jak wyżej. Dla tego przykładowego pola mógłby być wygenerowany kod <input type="text" name="imie" value='' maxlenth='20' />.

Cytat
A w akcji walidującej:

if(!empty($dana1) && $dana2 >0 && ...)


Tu walidowałbyś dane w pętli na podstawie listy pól formularza. W tym przypadku trzeba by sprawdzić czy pole ma wartość typu 'string' i czy długość tekstu jest mniejsza niż 20 znaków.

Cytat
Nie przekonacie mnie, że taka walidacja jest dobra.
W ten sposób kod odpowiedzialny za zachowanie formularza miałbym rozwalony po kilku klasach a coś takiego nie ma nic wspólnego z OOP i reusability.
Zasada jest prosta: chcesz aby formularz sie zwalidował to każ mu się zwalidować, chcesz aby się wyświetlił to każ mu się wyświetlić.


Jeśli chesz aby kontroler formularza zwalidował dane to niech je zwaliduje, możesz to zrobić bezpośrednio w kontrolerze używając funkcji strlen(), is_string() itp. albo napisać do tego jakąś klasę walidująca dane przychodzące. Jak kontroler ma wyświetlić formularz to przekazuje opis jego struktury do widoku i widok generuje na jej podstawie kod HTML formularza.

Cytat
Jeżeli kod walidujący będzie inny od wyświetlającego to aby dodać nowe pole do formularza będę musiał modyfikować dwa pliki, jeżeli będzie to w jednej klasie to wystarczy dodać do obiektu formularza kolejne pole.


Modyfikowałbyś jeden plik, a ściślej to listę pół formularza.

Cytat
Według mnie zasady inżynierii programowania wymagają aby kod zamykać w funkcjonalne moduły.
Formularz i jego zachowanie jest pewnym modułem. Nie da się oddzielić od siebie dwóch zachowań formularza - jego "walidowalności" i "konstruowalności".


Jak to się nie da? Walidowanie i konstruowanie to dwa inne zachowania takiego obiektu, a jeśli modelujemy zachowanie jako metodę klasy to byłyby to dwie metody w klasie kontrolera.

Cytat
Te dwie czynności można oczywiście robic w różnych opcjach ale bezsensem według mnie jest implementowanie tych dwóch zachowań jako czegoś nie związanego ze sobą.


Schemat działania w uproszczeniu wyglądał by tak:
1. Akcja Add kontrolera przekazuje listę pól do widoku i ten ubiera ją w kod HTML
2. Użytkownik wypełnia formularz i go wysyła.
3. Dane odbiera akcja Validate. Na podstawie listy pól sprawdza ona nadesłane dane. Jeśli są poprawne to przekazuje te dane do akcji Save. Jeśli jakieś dane nie są poprawne, to przypisuje do danego pola komunikat i listę przekazuje spowrotem do akcji Add, która wyświetla formularz wraz z komunikatami.
4. Akcja Save zapisuje dane w bazie danych.


--------------------
lorem ipsum : polska społeczność zend framework
Go to the top of the page
+Quote Post
cicik
post 18.09.2006, 13:39:54
Post #10





Grupa: Zarejestrowani
Postów: 219
Pomógł: 5
Dołączył: 18.07.2006
Skąd: Piekary Śląskie

Ostrzeżenie: (0%)
-----


Cytat(cyphelf @ 18.09.2006, 13:53:19 ) *
Możesz przechowywać w module listę pól formularza np. w postaci tablicy (przykład w uproszczeniu):
  1. <?php 
  2. $form[] = array(
  3. 'nazwa_pola' => 'imie',
  4. 'typ_pola' => 'input_text',
  5. 'format_danych' => 'string',
  6. 'dlugosc' => 20,
  7. 'wartosc_pola' => '',
  8. );
  9. ?>


Po co mam mieć jakąś daremną tablicę skoro generowanie formularza mam zrobione 200 razy lepiej na obiektach. Poza tym takową tablicę też gdzieś trzeba generować. Pewnie jakiejś funkcji/metodzie. I wracamy do punktu wyjścia... w której warstwie tą metodę umieścić.
Akurat to jak przechowywać pola formularza nie jest wogóle moim problemem.

Odpowiedzi w tym temacie coraz bardziej przekonują mnie, że MVC wcale nie jest takie cudne i choć rozwiązuje problem z ładowaniem jak najmniejszej ilości kodu to prowokuje inne.
Chyba zacznę opracowywać własne rozwiązanie, które zapożyczy z MVC jego najlepsze cechy a jednocześnie odrzuci ścisły rozdział na warstwy.
Np. każdy formularz może być jedną klasą, w której formularz będzie w konstruktorze składany z odpowiednich klocków (pól). Będą tam metody, które go wyświetlą (widok), zwalidują (kontroler) i zapiszą (model). Wydaje się to dość rozsądne. Rozwiązanie takie pozwala na dużą przenośność takowego formularza pomiędzy projektami (wystarczy skopiować jeden plik).


--------------------
CMS dla Twojej firmy
Wojciech Małota
Go to the top of the page
+Quote Post
bela
post 18.09.2006, 16:48:36
Post #11


Administrator PHPedia.pl


Grupa: Developerzy
Postów: 1 102
Pomógł: 2
Dołączył: 14.09.2003

Ostrzeżenie: (0%)
-----


Cytat(NuLL @ 17.09.2006, 20:10:30 ) *
Przepraszam za krotko odpowiedziec na php PRO ;-)

A moze by tak kazda akcja to pojedyncza klasa, modul to katalog - i tyle smile.gif

Ja preferuję rozwiązanie, że klasa to moduł, metoda to akcja. Wg mnie jest wygodniej bo nie trzeba za kazdym razem tworzyc pliku. A mówienie tu o wydajności jest po prostu smieszne, bo to groszowa sprawa. Mam w projekcie kontrolery po kilkaset linijek i nie zauwazylem zadnego wplywu dlugosci na szybkosc aplikacji, za to na szybkosc tworzenie widac wyraznie.

A co do głownego watku, chodzi o to gdzie umiejscowic walidowanie formularzy? Ja bym zaimplementował to jako intercepting filter, szczegolnie wersje implementacji jako dekorator jest bardzo sensowna. Temat o tym wzorcu kilka razy sie pojawial, sa w nim linki do blue printow suna i msdn. Zreszta po wpisaniu 'intercepting filter' w googlu dostaniesz te wyniki na samym początku.


--------------------
Go to the top of the page
+Quote Post
cicik
post 18.09.2006, 16:56:09
Post #12





Grupa: Zarejestrowani
Postów: 219
Pomógł: 5
Dołączył: 18.07.2006
Skąd: Piekary Śląskie

Ostrzeżenie: (0%)
-----


Cytat(bela @ 18.09.2006, 17:48:36 ) *
A co do głownego watku, chodzi o to gdzie umiejscowic walidowanie formularzy?


Nie nie chodzilo o to.
Chodzi o to gdzie umiescic metode generujaca obiekt formularza.
Wydawalo mi sie, ze dosyc doglebnie to wyjasnilem.


--------------------
CMS dla Twojej firmy
Wojciech Małota
Go to the top of the page
+Quote Post
hawk
post 19.09.2006, 11:22:38
Post #13





Grupa: Zarejestrowani
Postów: 521
Pomógł: 0
Dołączył: 3.11.2003
Skąd: 3city

Ostrzeżenie: (0%)
-----


Po co w ogóle metoda generująca obiekt formularza?
  1. <?php
  2. $form = new AddUserForm();
  3. ?>

Skoro formularz musi być używany w kilku miejscach aplikacji (wyświetlanie i walidacja), to zgodnie z OOP należy funkcjonalność zamknąć nie w osobną metodę, ale w osobną klasę.

Takie podejście jest również jak najbardziej zgodne z MVC. Przykład: Struts.
Go to the top of the page
+Quote Post
NuLL
post 19.09.2006, 23:21:16
Post #14





Grupa: Zarejestrowani
Postów: 2 262
Pomógł: 21
Dołączył: 3.05.2004
Skąd: Sopot, Krakow, W-wa

Ostrzeżenie: (0%)
-----


@hawk - ty zyjesz smile.gif

@cinek - nie lepiej napisac wtyczke do szablonu - generowanie formularza to sprawa widoku wg mnie :-)


--------------------
Javascript, Coffeescript, Node.js, Mongo, CouchDb, chmury, workery & inne bajery - zycie jest zbyt krotkie aby miec nudna prace :)
Go to the top of the page
+Quote Post
cicik
post 20.09.2006, 05:56:15
Post #15





Grupa: Zarejestrowani
Postów: 219
Pomógł: 5
Dołączył: 18.07.2006
Skąd: Piekary Śląskie

Ostrzeżenie: (0%)
-----


Cytat(NuLL @ 20.09.2006, 00:21:16 ) *
@cinek - nie lepiej napisac wtyczke do szablonu - generowanie formularza to sprawa widoku wg mnie :-)


Ale jego walidacja juz nie, a niektorzy lubia miec takie rzeczy kompleksowo zalatwione jednyhm obiekcie.


--------------------
CMS dla Twojej firmy
Wojciech Małota
Go to the top of the page
+Quote Post
jezoo
post 22.09.2006, 17:37:20
Post #16





Grupa: Zarejestrowani
Postów: 92
Pomógł: 3
Dołączył: 4.04.2006

Ostrzeżenie: (0%)
-----


jezeli chodzi o formularze to moze sie podepne, bo mam metode w sowjej klasie nastepujaca:
  1. <?php
  2. class JakasTam {
  3.  var $f = array();
  4.  
  5. public function Form() {
  6. ?>
  7. <form action="sm_install.php" method="post" onSubmit="return checkForm();" name="fI0">
  8. <input type="hidden" name="location" value="<?=$this->f[5]?>" />
  9.  
  10. <div class="InstHeader">Proszę podać wymagane dane do kontynuacji instalacji</div><br /><br />
  11.  
  12. <table align="center">
  13. <tr><th><?=$this->f[1];?></th><td align="center"><input type="text" name="<?=$this->f[1];?>" align="right"></td></tr>
  14. <tr><th><?=$this->f[2];?></th><td align="center"><input type="text" name="<?=$this->f[2];?>" align="right"></td></tr>
  15. <? if($this->f[3]==NULL || $this->f[3]==" "){
  16.  
  17. }else{?>
  18. <tr><th><?=$this->f[3];?></th><td align="center"><input type="text" name="<?=$this->f[3];?>" align="right"></td></tr>
  19. <? } ?>
  20. <tr><th><?=$this->f[4];?></th><td align="center"><input type="password" name="<?=$this->f[4];?>" align="right"></td></tr>
  21. <tr><td align="center" colspan="2"><input type="submit" value="Dalej"></td></tr>
  22. </table>
  23. </form>
  24. <?
  25. }
  26. }


i moj problem jest taki, ze moge jedynie wyswietlic tyle pol ile mam zdefiniowanych w metodzie, a wiec jezeli bede mial np:
  1. <?php
  2. $obiekt = new JakasTam();
  3.  
  4. $obiekt->f[1]="Costam1";
  5.  
  6. $obiekt->f[2]="Costam2";
  7. $obiekt->f[4]="Costam3";
  8. $obiekt->Form();
  9. ?>


to sila rzeczy wyswietli mi 3 pola, jak chce miec 4 to tylko uzupelniam f[3] i jes ok, i bul jest mianowicie taki, ze jak chce miec wiecej niz 4 pola to musze kolejne pola dopisywac w metodzie.

a moje pytanie jest takie, mozna zrobic w ten sposob zeby zdefiniowac ilosc tworzonych pol i ich typ, ale co z ich nazwami i etykietami?? to mnie zastanawia, w jaki sposob mozna taki problem rozwiac, bo szczerze mowiac, skrobanie <input type""> to juz mnie do oslabi a palce to mi posluszenstwa odmawiaja winksmiley.jpg

Ten post edytował jezoo 10.10.2006, 07:57:11
Go to the top of the page
+Quote Post
NuLL
post 24.09.2006, 14:15:27
Post #17





Grupa: Zarejestrowani
Postów: 2 262
Pomógł: 21
Dołączył: 3.05.2004
Skąd: Sopot, Krakow, W-wa

Ostrzeżenie: (0%)
-----


Ja to rozwiazuje troche inaczej. Szablon wyglada tak - jest to kod XML a nie znaczniki Smarty czy cos winksmiley.jpg
  1. <form:start id='loginForm'>
  2. Login: <form:input name='login'><form:errorSpan for='login'><br/>
  3. Haslo: <form:password name='pass'><form:errorSpan for='pass'><br/>
  4. <form:checkbox name='remember'><label for='remember'>Zapamietaj mnie</label><br>
  5. <input type='submit' value='Go'>
  6. <:form:end>

Klasa akcji
  1. <?php
  2. class loginAction extends genericAction
  3. {
  4. public function perform()
  5. {
  6. if($this->input->login && $this->input->pass)
  7. {
  8.  //tu mnie zaloguj ;-]
  9. }
  10. }
  11. }
  12. ?>

I klucz programu czyli definicja danych przychodzacych z formularza
  1. <?php
  2. class loginFormInputDef extends inputDef
  3. {
  4. protected function buildIt()
  5. {
  6.  $this->setParameters('loginForm',iHttpRequest::POST);
  7.  
  8.  $this->addField('login',inputField::REQUIRED,array(inputField::STRING),array('min'=>3,'max'=>25);
  9.  $this->addField('pass',inputField::REQUIRED,array(inputField::ALPHANUMERIC),array('min'=>5);
  10.  $this->addField('remember',inputField::OPTIONAL,inputField::INTEGER,array('range'=>array(1,0));
  11. }
  12. }
  13. ?>

Klasa zwracajaca obiekt akcji zamiast samej akcji zwraca obiekt klasy actionWrapper, ktory zajmuje sie caloscia walidacji oraz przypisanie bledow oraz bylych wartosci do systemu formularzy. Calosc wykonuje sie automatycznie - jesli istnieje definicja danych forumularzowych i sa dane wyslane to nastepuje walidacja. Jesli akcja jest zdefiniowana tylko jako akcja ktora odbiera formularz actionWrapper w wypadku znalezienia bledow w walidacji wogole nie stworzy obiektu akcji ani tymbardziej nie uruchomi metody perform(). Nie wiem czy to zgodne z MVC czy nie - wg mnie blisko Rkingsmiley.png Korzystam z tego od dlugiego czasu i jest to swietna sprawa guitar.gif

Ten post edytował NuLL 24.09.2006, 14:19:57


--------------------
Javascript, Coffeescript, Node.js, Mongo, CouchDb, chmury, workery & inne bajery - zycie jest zbyt krotkie aby miec nudna prace :)
Go to the top of the page
+Quote Post
macbirdie
post 25.09.2006, 13:02:21
Post #18





Grupa: Zarejestrowani
Postów: 28
Pomógł: 0
Dołączył: 7.09.2006
Skąd: Poznań

Ostrzeżenie: (0%)
-----


cicik - nie wnikałem we wszystkie odpowiedzi, ale Twoje pytanie narzuca mi rozwiązanie kwestii podziału na model i widok w wykonaniu standardu XForms. W modelu jest wykaz wszystkich pól, określenie reguł walidacji, nadanie polom aliasów po których odwołujemy się w prezentacji. Prezentacja to już oczywiście opis, jak co ma na tym formularzu wyglądać i gdzie się znaleźć. Obejrzyj, przekontempluj, może Ci się coś nasunie. winksmiley.jpg

Ten post edytował macbirdie 26.09.2006, 17:23:54


--------------------
NotePad++ / Eclipse 3.3 (+PDT+PyDev+WTP) / VS 2005 Standard (+WTL 8.0+WM 2003 SDK/WM 5.0 SDK) / Glassfish / php 5.2.3 / Apache 2.2.x / MySQL 5.0.x / PostgreSQL 8.2.x / cvsd / violin 2.0 / piano 0.7-pre :P
Go to the top of the page
+Quote Post
mihaup
post 29.11.2006, 08:06:16
Post #19





Grupa: Zarejestrowani
Postów: 33
Pomógł: 0
Dołączył: 2.11.2006

Ostrzeżenie: (0%)
-----


Cytat(cyphelf @ 17.09.2006, 19:44:40 ) *
Powinna ona należeć do warstwy kontrolera, powinna być jedną z jego akcji. W tym przypadku kontroler formularza powinien pobrać z modelu strukturę tabeli, wygenerować pola (np. w postaci obiektu czy tablicy) i przekazać to do widoku, aby widok ubrał to w kod html.


Nic dodać, nic ująć:)
Go to the top of the page
+Quote Post
Sh4dow
post 29.11.2006, 11:41:18
Post #20





Grupa: Zarejestrowani
Postów: 569
Pomógł: 0
Dołączył: 17.08.2003
Skąd: Dąbrowa Górnicza

Ostrzeżenie: (0%)
-----


Moje rozwiazanie działające od jakiegos czasu dosc wygodne, tylko nameczyłem sie zeby wszystko chodziło poprawnie

Dynamiczny formularz składa sie z 2 tablic w bazie danych
Pierwsza zawieraz dane o formularzu, druga zawiera dane formularza wpisane przez usera dla jakiegos ID naprzyklad dla user_id.
aby wygenerowac formularz potrzebujesz
  1. Identyfikator, wystarczy ID
  2. Opis, moze byc nazwa przy polu formularza, ale nie koniecznie, zalezy jak ci pasuje
  3. dane o validacji, string, int, select, dir() (to ostatnie to zdefiniowana funkcja do walidacji oraz do tworzenia danych dla pol np.select)
  4. default_value, czyli defaultowa wartosc pola jesli jest nie wypełnione lub aby przy dodawaniu nowego elementu przez formularz była jakaś wartość juz dodana, dla typu walidacji rexp albo date mozna wpisac wyzazenia okreslające wyrazenie regularne lub format dat, dla pola select mozna pisac poprostu uproszczona tablice z kluczami i wartosciami dla rozwijalnych menu lub radio butonów
  5. flaga określająca czy pole jest wymagane i bez jego poprawnego wypełnienia zwracamy błąd/wyjątek
  6. przy stringach lub intach mozna dodac pole o ich długości ale to zalezy jak komu wygodnie
druga tablica to proste
  1. user_id
  2. form_field_id
  3. form_field_value
sa dwie metody publiczne, jedna pobiera dane do generowania formularza dla wybranych ID lub dla wszystkich pól.
Wewnatrz metody prywatne pobieraja dane z tablic, parsuja wszystkie dane tworzac konkretna tablice. Druga metoda do pobierania danych dla danego user_id oraz dla wybranych lub wszystkich ID formularza.
Roznica miedzy tablicami jest taka ze druga ma wiecej o 2 pola, 'value' oraz 'real_value' pola roznia sie wtedy gdzi chodzi o pola typu select gdzie w tablicy łączonej mamy klucz tablicy z pola default_value, wtedy klucz 'real_value' posiada wartosc dla klucza który jest podany w polu 'default_value'. chyba zagmatwałem wiec juz tłumacze na przykładzie
dane tablicy łączonej:
Kod
user_id | form_field_id | form_field_value
       1|              1|                1

tablica z danymi formularza
Kod
id | name | validate | default_value | require | lenght
1 | 'test' | 'select' | 1 => 'test1';2 => 'test2';3 => 'test3'| 1 | null


metoda zwraca wartosci dla value => 1 a dla 'real_value' => 'test1'
oczywiscie musisz sie trzymac jakis standardów jakie sobie ustalisz, wtedy nie powinno byc problemów.

Drugą częścią jest jakiś moduł/funkcja w widoku która bedzie generowac z tej tablicy gotowy formularz. Ja wykonałem funkcje w smarty, gdzie podaje praktycznie 2 parametry, jeden to dane do wygenerowania pola, drugi parametr to flaga błędu, słuzy jedynie do graficznego zaznaczenia bledu, ktora jest nie wymagana wszedzie.

Trzeci element układanki to metoda Walidująca. Sa dwa sposoby, jeden to podac nazwe tablicy _POST w ktorej znajduja sie wysłane formularze, lub tez przekazac juz bezposrednio tablice. Podajesz tablice ID'ków ktore maja być poddane walidacji. Po walidacji otrzymujesz true lub false. Jesli true, uzywasz specjalnej metody ktora zwraca tablice ktora masz pozniej zapisac. Jesli masz false to masz metode zwracającą flagi dla ID'ków które sa błęde, oraz metode która zwróci ci tablice do generowania formularza z danymi ktore wpisal użytkownik.

To sa główne założenia całego obiektu, lub obiektów. Sposob walidacji, sprawdzania itd to kazdy ma swoje sposoby. To jest jeden, w miare uniwersalny sposob na walidacje, generowanie i ogolna obsluge takich formularzy. Odpowiedni panel moze zautomatyzowac ci do maxymum tworzenie generowanie i walidacje formularzy. Wszystko zalezy od tego kto co chce.
Zalety to mozliwosc definiowania gotowych metod walidujących, np gotowymi validacjami moga byc url, email, zip_code (jako kod pocztowy). Dodanie pola do formularza do dodanie kolejnego ID przy pobieraniu danych. Mozna tworzyc grupy pól, mozna dodac kolumne z opisem, komunikatem w przypadku błędu. Mozna generowac komunikat błędu na podstawie pola walidacji.
Wszystko w jednym. Okreslac ID'ki dla formularza, jesli akcja ma walidowac przekazujesz to do walidacji, jesli poprawnie zapis, jesli nie zrwacasz tablice do ponownego generowania. Jesli wyswietlasz formularz pobieraz dane dla formularza lub z tymi samymi idekami pobieraz dane dla danego powiedzmy user_id.

Tutaj problem nie dotyczy modelu MVC ale proby implementacji odpowiedniego rozwiązania.. Takie jest moje zdanie i sposob rozwiazanie tego powyzej. guitar.gif


--------------------
Warsztat: Linux: PHP, MySQL, Apache, NetBeans, C++, Qt-Creator
Użytkownik, słowo którego specjaliści IT używają, gdy chcą powiedzieć idiota
Zarządzaj swoim budżetem domowym
Go to the top of the page
+Quote Post

2 Stron V   1 2 >
Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 16.04.2024 - 14:29