2012-09-12 11 views
6

私はuserオブジェクトの例を取るつもりです。Web MVC:Modelレイヤーを構造化する方法は?

私はuserというオブジェクトを持っていますが、これには様々なクラス変数(擬似、電子メールなど)が含まれています。 )ゲッターやセッター、そしておそらくdbを扱わない関数があります。

私はDAOクラスを持っています。このクラスは、さまざまなMySQL/PDOクエリ(レコードの作成、更新、取得情報の作成など)を通じてデータベースを直接扱うオブジェクトです。

userオブジェクトにDAOオブジェクトと直接対話させない理由はありますか?言い換えれば、Controllerが、userインスタンスに関連するデータベースクエリを(例えば、登録プロセス中に)要求する場合、user内の関数を呼び出すだけで、それ自体がDAOの関数を呼び出すか、 ?

コントローラーが第3クラスを呼び出してDAOと通信し、userインスタンスをargとして渡す例があります。代わりに、userインスタンスを作成し、DAOを扱うことで、この3番目のレイヤーが担当することもあります。 DAOを処理するために使用されたすべての関数は、userオブジェクト内に存在する可能性があります。私は何が欠けていますか?

答えて

2

私はあなたがアダプタを呼び出すクラス(データベースやXMLデータソースとやりとりするかもしれない)を持っているモデルのための何らかの種類のアダプタやゲートウェイを記述して、その結果をあなたのモデル(つまり一致する各ユーザーの結果をUserモデルのインスタンスに割り当てます)。

これまでは、1つのアイテムを表すモデルがある場所で説明した方法を取り上げ、DAOを使用してこれらのアイテムをデータソース(データベースなど)に保存して取得し、ロジックを実行するコントローラとを含む。だから、非常に基本的なバージョン:

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); 
     } 
    } 
} 

希望すると便利です。

+0

-1:そのコードのどれもコントローラ内に配置されていません。プレゼンテーション層にドメインビジネスロジックがあります。 'User'' classはカプセル化や振舞いを提供しません。 –

+0

ああ.. 'UsersDAO'のあなたのコード例は、実際にはDAOではないデータマッパーです(http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html)。 DAOはストレージと直接対話しません。 –

+0

@tereško解決策を回答として投稿してください。また、プレゼンテーションレイヤーの例を投稿していないときに、プレゼンテーションレイヤーにドメインビジネスロジックがあるとはどういうことがわかりません。 –

3

MVCデザインパターンを遵守している場合は、Userインスタンスがコントローラに存在するために、の理由がないと、が存在します。プレゼンテーション層に漏れるのではなく、モデル層の一部でなければなりません。

あなたが呼んで「コントローラ」は、データストレージ関連構造(mappersrepositories、DAOを)上domain objectsの間の相互作用を処理するデータモデル層の一部であるべきサービスの実際より多くがあるようです。

基本的に、あなたが欠けているのは、懸念の正確な分離です。

コントローラは、ドメインビジネスロジックを処理するのではなく、認識またはユーザー管理サービスにデータを渡すだけです。上記のサービスはUserオブジェクトを初期化し、データを検証して保存しようとします。コントローラーはこれを認識してはいけません。

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.の場合はthis postとなります。

+1

downvote人は、推論を説明する必要があります。 –

+0

クラス定数を使用する利点は何ですか? View :: STATE_POSTのように?あなたはコントローラとビュー以外の他の場所でそれを使いますか?ちょうど$ this-> view-> setState( 'post')を使うのはなぜですか? – Andrew

+0

なし、古いです。それは、私がまだすべてのフレームワークに間違っていて、コントローラが何か意見を伝えなければならないと思ったときでした。 –

関連する問題