6

我将以一个user对象为例。用户需要注册、登录、注销、编辑(例如,电子邮件更改)等。

所以一方面我有一个user对象,它包括各种类变量(伪、电子邮件等)以及 getter 和 setter,也许还有一些不处理 db 的函数。

另一方面,我有一个DAO类,它是通过各种 MySQL / PDO 查询(创建记录、更新、检索信息等)直接处理数据库的对象。

是否有任何理由不让user对象直接与对象交互DAO?换句话说,当Controller请求与现有user实例相关的数据库查询时(例如,在注册过程中),它应该简单地调用一个函数,user其中它本身调用一个函数DAO,还是应该在两者之间有一个层?

我已经看到控制器调用第三个类与 DAO 交互并将user实例作为 arg 传递的示例。有时,第三层负责创建user实例并处理DAO. 在我看来,用于处理的所有函数DAO都可以驻留在user对象内部。我错过了什么?

4

2 回答 2

3

如果您遵循 MVC 设计模式,那么实例没有理由位于控制器中。User它应该是模型层的一部分,而不是泄漏到表示层。

看起来你所说的“控制器”实际上更像是一种服务,它应该是模型层的一部分,它处理数据存储相关结构(映射器存储库、DAO)上域对象之间的交互。

基本上,您缺少的是正确的关注点分离。

控制器应该只是将数据传递给识别或一些用户管理服务,而不是处理域业务逻辑。所述服务应该初始化User对象、验证数据并尝试保存它。控制器不应该知道这些。

像这样的东西:

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

PS你可能会发现这篇文章相关。

于 2012-09-12T20:16:47.040 回答
2

我认为您正在为模型描述某种适配器或网关,其中您有一个调用适配器的类(它可能与数据库或 XML 数据源交互),然后将结果分配给模型的实例(即将每个匹配的用户结果分配给User模型的一个实例)。

过去,我采用了您所描述的方法,其中您有代表一个项目的模型,然后是一个 DAO 将这些项目保存并检索到数据源(无论是数据库还是其他),以及控制器做逻辑。所以一个非常基本的版本:

用户DAO.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();
    }
}

用户.php

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

用户控制器.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);
        }
    }
}

希望这可以帮助。

于 2012-09-12T18:30:07.920 回答