2012-09-12 18 views
6

Prenderò l'esempio di un oggetto user. Un utente deve essere registrato, registrato, disconnesso, modificato (ad es., Cambio di email), ecc.Web MVC: come strutturare il livello Modello?

Quindi da una parte ho un oggetto user, che include una varietà di variabili di classe (pseudo, email, ecc.) insieme a getter e setter e forse alcune funzioni che non si occupano del db.

Sull'altra ho una classe DAO che è l'oggetto che gestisce direttamente il database tramite una varietà di query MySQL/PDO (crea record, aggiorna, recupera informazioni, ecc.).

C'è qualche motivo per non avere l'oggetto user interagire direttamente con l'oggetto DAO? In altre parole, quando Controller richiede una query di database relativa a un'istanza user esistente (ad esempio, durante il processo di registrazione), deve semplicemente chiamare una funzione in user che a sua volta chiama una funzione in DAO o dovrebbe esserci un livello intermedio tra ?

Ho visto esempi in cui il controller chiama una terza classe per interagire con il DAO e passa un'istanza user come arg. A volte invece, questo terzo livello è responsabile della creazione dell'istanza user e della gestione dello DAO. Mi sembra che tutte le funzioni utilizzate per gestire lo DAO possano risiedere all'interno dell'oggetto user. Cosa mi manca?

risposta

2

Penso che si stia descrivendo una sorta di adattatore o gateway per i modelli, in cui si ha una classe che chiama un adattatore (potrebbe interagire con un database o un'origine dati XML) e quindi assegna i risultati alle istanze di il tuo modello (cioè assegna ciascun risultato utente corrispondente a un'istanza del tuo modello User).

In passato, ho preso l'approccio che hai descritto in cui sono presenti modelli che rappresentano un elemento e quindi un DAO per salvare e recuperare questi elementi in un'origine dati (sia esso un database o qualsiasi altra cosa), e il controller che fa la logica. Quindi, una versione estremamente semplice:

UsersDAO.php

class UsersDAO extends DAO 
{ 
    public function save(User $user) 
    { 
     return is_null($user->id) ? $this->insert($user) 
            : $this->update($user); 
    } 

    public function insert(User $user) 
    { 
     $sql = "INSERT INTO `users` (`username`, `password`) 
       VALUES (:username, :password)"; 

     $stmt = $this->db->prepare($sql); 
     $stmt->bindParam(':username', $user->username); 
     $stmt->bindParam(':password', $user->password); 
     $stmt->execute(); 
    } 
} 

User.php

class User 
{ 
    public $id; 
    public $username; 
    public $password; 
    public $email; 
} 

UsersController.php

class UserController extends Controller 
{ 
    public function register() 
    { 
     $usersDao = new UserDAO; 

     if ($_POST) { 
      $user = new User; 
      $user->username = $_POST['username']; 
      $user->password = $_POST['password']; 

      $userDao->save($user); 
     } 
    } 
} 

Spero che questo aiuti.

+0

-1: nessuno di quel codice si trova nel controller. Hai una logica di business del dominio nel livello di presentazione. E tu "utente" "classe" non fornisce incapsulamento o comportamento. –

+0

Oh .. e il tuo esempio di codice di 'UsersDAO' è in realtà un data mapper, [non un DAO] (http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html). I DAO non interagiscono direttamente con lo storage –

+0

@ tereško Sentiti libero di pubblicare la tua soluzione come risposta. Inoltre, non sono sicuro di come si possa dire che ho una logica di business del dominio nel livello di presentazione quando non ho nemmeno pubblicato un esempio del livello di presentazione. –

3

Se si aderisce al modello di progettazione MVC, quindi è non motivo per l'istanza User nel controller. Dovrebbe essere parte del livello del modello, invece di passare al livello di presentazione.

Sembra che quello che si chiama "controller" è in realtà più di un servizio, che dovrebbe essere una parte dello strato del modello, che gestisce l'interazione tra domain objects sulle strutture di memorizzazione dei dati relativi (mappers, repositories, DAO).

Fondamentalmente, ciò che ti manca è la corretta separazione delle preoccupazioni.

Il controller deve semplicemente passare i dati al riconoscimento o ad un servizio di gestione utenti, invece di gestire la logica di business del dominio. Detto servizio dovrebbe inizializzare l'oggetto User, convalidare i dati e provare a salvarlo. Il controller non dovrebbe essere a conoscenza di nulla di tutto ciò.

Something like this:

class SomeController 
{ 
    // ---- snip ---- 

    public function postRegister($request) 
    { 
      $accounts = $this->serviceFactory->create('AccountManagement'); 
      $account->create($request->getPost('username'), 
          $request->getPost('email'), 
          $request->getPost('password'), 
          $request->getPost('password2')); 

      $this->view->setState(View::STATE_POST); 
    } 

    // ---- snip ---- 
} 

class AccountManagement extends Service 
{ 
    // ---- snip ---- 

    public function addUser($username, $email, $password, $repeated_password) 
    { 

     $user = $this->domainObjectFactory->create('User'); 

     $user->setNickname($username); 
     $user->setEmail($email); 
     $user->setPassword($password); 
     $user->matchRepeatedPassword($repeated_password); 

     if ($user->isValid()) 
     { 
      $dao = $this->DAOFactory->create('User'); 
      $dao->save($user); 
     } 

     // additional code for saving the error state 
     // if domain object turns out to be invalid 
     // or DAO returns an error 
    } 

    // ---- snip ---- 
} 

P.S. si potrebbe trovare rilevante this post.

+1

Le persone che downvotano dovrebbero spiegare il ragionamento. –

+0

qual è il vantaggio dell'uso delle costanti di classe? come Visualizza :: STATE_POST? Lo usi in altri posti, ad eccezione del controller e della vista? Perché non usare solo $ this-> view-> setState ('post'); – Andrew

+0

Nessuno, è un messaggio obsoleto. È stato quando ero ancora fuorviato da tutte le schifezze del framework e pensavo che i controllori dovessero dire qualcosa alle opinioni. –

Problemi correlati