Cytat(thek @ 15.10.2009, 09:24:26 )

Zauważ, że przykładową klasą Użytkownik mieszasz już nieco strukturę. Są w niej bowiem funkcje z różnych "warstw". I tak:
Walidacja -> Model
Rejestracja -> Model
Logowanie -> Kontroler
Wylogowanie -> Kontroler
Nowe hasło -> Model
Zmień hasło -> Model
Zmień dane -> Model
Pokaż rabat -> Widok
Problem w tym, że nawet to jest w sposób, który nie do końca jest prawidłowy. Dlaczego?Bo część z tych operacji jest wykonywana poprzez więcej niż 1 "warstwę". Przykładowo Pokaż rabat jest tak naprawdę Widokiem, ale musi posłużyć się metodami Modelu by uzyskać te dane. Tak naprawdę więc nie ma w klasie usera żadnego widoku. Jest za to jeden wielki model danych użytkownika, którego metodami posługują się inne klasy. Nie ma czegoś takiego jak logowanie czy wylogowanie, bo to kontroler zupełnie innej klasy. Tak naprawdę w klasie użytkownik masz metody służące do jego dodania, usunięcia, wyciągnięcia pewnych lub wszystkich danych bądź ich zmiany. Rabat jest tutaj czymś zupełnie obcym i można powiedzieć, że jest osobną klasą. Walidacja nie jest osobną metodą, gdyż musi być implementowana w każdej z metod odpowiedzialnych za edycję. Nie napiszesz nigdy zunifikowanej wersji musiałbyś dla każdego typu pola pisać osobną metodę walidacji go. Inaczej bowiem waliduje się adres e-mail a inaczej adres www lub konkretne pole liczbowe czy znakowe. Poza tym czasem jakieś pola przy edycji w określonych przypadkach walidujesz, a inne nie, gdyż nie są nawet wypełniane. Jak wyobrażasz sobie choćby metodę walidacji z jedną metodą gdy raz posyłamy ją tylko do zmiany hasła, a innym razem do dodawania usera?
Najprościej rzecz ujmując istnieją jakby dwie klasy użytkownik. Jedna to kontroler, druga to model. User_Kontroler może wywołać metodę rejestracja, która zainicjuje User_Model łącząc ją ze źródłem danych, zwaliduje dane i gdy zwróci błąd (banalne hasło, login już istnieje, nieprawidłowe dane w formularzu lub nieprawidłowy ich format) poinformuje User_Kontroler o tym. Jeśli zaś wszystko ok to doda do źródła danych i zrobi ewentualnie coś jeszcze.
Sklep internetowy podziel na role wpierw i pomyśl co Ci potrzebne. Na pewno użytkownik, na pewno produkt i koszyk To minimum, ale w zależności od stopnia komplikacji rozszerzy się to zapewne o inne. Nie ma jasnej i gotowej odpowiedzi o podział, gdyż niemal każdy inaczej widzi go, choć teoretycznie każdy korzysta z tej samej definicji

Bo mnie zaraz coś trafi. Nie myl koledze.
Walidacja -> Model - bzdura - kontroler
Rejestracja -> Model - bzdura - kontroler
Logowanie -> Kontroler - no wreszcie coś rozsądnego
Wylogowanie -> Kontroler - i znowu coś rozsądnego
Nowe hasło -> Model - bzdura! - kontroler
Zmień hasło -> Model - bzdura! - kontroler
Zmień dane -> Model - bzdura! - kontroler
Pokaż rabat -> Widok - bzdura! - kontroler
Nie myl pojęć
Aplikacja ma być podzielona na warstwy a nie klasy. Poza tym są klasy do łączenia się z bazą danych i do wykonywania zapytań. Więc to one są Model'em. Widok to będzie mechanizm parsujący templatkę, a wszystko co się między nimi odbywa jest kontrolerem. Stworzenie zapytania (stringa) może być częścią kontrolera albo modelu - Twoja sprawa jak to zrobisz. Ale już walidacja w php (czy wszystkie dane zostały wpisane) jest czystym kontrolerem.
Podział na klasy w sklepie (według mnie):
klasa Modelu - do łączenia z bazą, tworzenia zapytań
klasa Widoku - na przykład smarty
klasa użytkownika (z wszelkimi niezbędnymi metodami)
klasa koszyka
klasa zamówienia
klasa modułu (za chwilę to wyjaśnię)
klasa dostawy (wprowadzanie świeżego towaru do sklepu)
To chyba wszystko co Ci jest potrzebne
Co do modułu. Na stronę moim zdaniem trzeba spojrzeć jak na wielki moduł, w którym są ładowane różne inne moduły.
Może obrazek


Każdy z zaznaczonych na obrazku modułów składa się dokładnie z tego samego
1. tworzysz moduł
2. napełniasz go danymi
3. parsujesz template
Teraz załóżmy że budujesz klasę w PHP która będzie się nazywać modul
<?php
class modul{
public $smarty = '';
public $module = '';
public $page = '';
public $top = '';
public $bottom = '';
public $conn = null;
public $queries = null;
public $tables = null;
public $parameters = null;
public function __construct($module, $connections, $top = 1, $bottom = 1){
//tu coś się dzieje
$this->CreateConnections($connections);
$this->ReadQueries();
}
public function getPage(){
$this->page = $this->smarty->fetch($this->module.'.tpl');
}
public function CreateConnections($connections){
//tworzy połączenia do baz danych
}
public function ReadQueries(){
//zaczytuje zapytania do wykonania w module
}
public function constructQuery($i, $j){
//to jest niezbędne do obsługi silnika DB
}
public function executeQuery($i){
//wykonuje konkretne zapytanie
}
public function assignVar($name = '', $value = ''){
$this->smarty->assign($name, $value);
}
public function display(){
echo $this->top.$this->page.$this->bottom; }
}
?>
to jest przykład z modelu MVC
teraz tak. Każdy z modułów na stronie może robić dokładnie to samo jak już pisałem wcześniej.
Założmy taki newsletter
<?php
class Newsletter extends modul{
public function __construct($connections){
parent::contruct('newsletter', $connections, 0, 0);
//dodałem zera do konstrukcji rodzica bo one akurat wskazują czy nagłowek i stopka mają być dodane do modułu. to jest fragment strony więc nie potrzeba nam ani nagłówka ani stopki
//newsletter zawsze będzie się wyświetlał tak samo, więc gdzie to wywoływać parsowanie? gdzie indziej? a po co? 
$this->getPage();
//jeszcze ważna rzecz trzeba pamiętać, ze ktoś może się chcieć dopisać
if(isset($_POST['save']) && $_POST['save'] == 'newsletter'){ $this->addToNewsleetter();
}
}
public function addToNewsletter(){
//tu dopisujemy do newslettera osoby :)
}
}
?>
a teraz sama strona - założmy index w którym załóżmy że wystepuje newsletter
<?php
class index extends module{
public function __construct($connections){
parent::contruct('index', $connections);
//jak widać teraz nagłowek i stopka zostaną do strony dołączone ;)
//tu oczywiście inne rzeczy mogą się jeszcze dziać
}
}
?>
I na końcu sklejenie tego wszystkiego w całość
<?php
require_once('includes/application.php'); //w tym pliku trzymam wszystkie dane niezbędne do połączenia i na przykład funkcję __autoload
$index = new index($connections);
$newsletter = new Newsletter($connections);
$index->assignVar('newsletter', $newsletter->page);
$index->getPage();
$index->display();
?>
i templatka (index.tpl)
<div>
{newsletter}
</div
Mam nadzieję, że rozumiesz o co mi chodzi ^^