域对象和 DAO。如何从域对象中进行查询,但仍然有两个对象不知道彼此存在
Posted
技术标签:
【中文标题】域对象和 DAO。如何从域对象中进行查询,但仍然有两个对象不知道彼此存在【英文标题】:Domain Object and DAO. How to do queries from within the Domain Object but still having both objects not know each other exists 【发布时间】:2012-12-17 00:58:26 【问题描述】:好的,我的 DomainObject/Model 名为 $user
和我的 $userDAO
对象。
到目前为止,当我需要执行 CRUD 操作(例如获取 $user
对象)时,我已经阅读过:
$user = $userDAO->fetchById($userId);
这将返回我的 $user
对象。
显然 DomainObject 不应该知道 DAO 对象存在,反之亦然,但是如果用户正在注册并且我运行 $user->register()
方法会怎样
$user->register($firstName, $lastName, $emailAddress, $username, $password etc.);
在该方法的某个地方,我需要检查所选用户名是否已被使用,并且与电子邮件地址相同。
我能想到的唯一方法是在我的$user
对象中拥有一个$userDAO
对象的实例,然后进行如下验证:
if($this->userDAO->isUsernameTaken($username))
// the username is already in use
else
// continue on
但这会打破 DomainObject 不应该知道数据库内容的规则,反之亦然,但我认为 DomainObject 并不真正了解数据库内容,因为所有查询都在 DAO 对象中,它只是持有对对象的引用,但它不明确知道该对象中发生了什么。我是对还是错?
如果我做错了,我应该如何运行像 $user->register()
这样的方法,它需要在其中调用一些需要访问数据源但 DomainObject/Model 的数据库查询不允许知道专家说的任何数据源?
我今天在 Google 上浏览了页码,我以为我永远不必再浏览了,但我仍然找不到任何非常可靠的现实生活示例来说明该做什么,我开始发疯了,因为它放慢一切。
任何帮助将不胜感激。谢谢。
【问题讨论】:
【参考方案1】:如果您从分层架构的角度考虑应用程序的架构,则需要在域层和 DAO 层之上再构建一层,让这两层保持原样。这个新层被一些人称为服务层或应用层。该服务层的工作是执行用例,例如“注册”一个新用户。例如,服务层中的一个类可能是 UserService,它执行与用户相关的用例,
class UserService
private UserDao userDao;
// constructor
userSercie()
// registers a user
register($firstName, $lastName, $emailAddress, $username, $password etc.)
$user = $userDAO->fetchByName($username);
if($user != null)
// the username is already in use
else
// continue on
// other service methods such as
为什么我们需要服务层?正是为了应对像您这样的问题,我们需要服务层。这样你可以看到我们可以保持不同模块之间的关注点分离。
【讨论】:
啊,是的,这就是我所缺少的,谢谢。但有一件事,如果$fetchByName()
方法在数据库中找到具有该用户名的行,它将返回一个$user
对象?如果我想检查提供的电子邮件地址是否已经存在,我是否使用了$fetchByEmail()
方法?
我使用了 fetchByName 这个名字,它通常是 CRUD 中的一个方法,除了 fetchById。但是,无论如何,这是一个例子来说明我关于服务方法的外观和行为的观点。当然,你可以有更多的 DAO 方法,例如 fetchByEmail() 等。但是,一般情况下,像 userDAO->isUsernameTaken($username) 这样的东西是不对的,执行这个检查不是 DAO 的责任,应该在服务层,使用 DAO,正如我已经展示的那样。
好的,谢谢,但不是只能执行userDAO->isUsernameTaken($username)
,它执行一个返回布尔值的小简单查询,正确的做法是$user = $userDAO->fetchByName($username);
,如果一行将创建一个用户对象已返回,然后我通过执行if($user != null)
来检查用户名是否存在?对我来说,这似乎真的效率低下和矫枉过正。当我开始这样做时,我已经可以看到我将不得不让函数一直返回对象,而不仅仅是布尔值。
你意识到检查不是线程安全的吧?捕获唯一的数据库约束异常可能会更好。以上是关于域对象和 DAO。如何从域对象中进行查询,但仍然有两个对象不知道彼此存在的主要内容,如果未能解决你的问题,请参考以下文章
关于如何从域 (ORM) 对象映射到数据传输对象 (DTO) 的建议
将 wordpress 从域迁移到另一个域 - 但 URL 仍重定向到旧域