正如标题所示,我在实现3结构模型(域对象,数据映射器和服务)时遇到了一些小问题。
过去当有人在我的网站上注册时,我只会做
$user->register($firstName, $lastName, $emailAddress, $username...);
并且该方法将按照这样的步骤运行
1. Check if the form sent was valid.
2. Check if all the required fields were filled.
3. Check the if the lengths of strings were valid and the range of integers etc.
4. Check if the input is in the correct format (regex).
5. Check if the username is already taken and if the email address already exists
in the database
6. etc. etc.
一切正常,但我正试图摆脱这样做,因为我希望我的代码更可重用和可测试。
现在,通过这个3结构模型,域对象和数据映射器应该通过服务进行通信,以使它们彼此隔离,所以这是我对用户服务的想法
class UserService {
public function register($firstName, $lastName, $email...) {
$userDO= $this->domainObjectFactory->build('User');
$mapper = $this->dataMapperFactory->build('User');
// Is this where I start doing my validation like in the steps above???
// And if this is where I start doing my checks, when I get to the part
// where I have to check if the username they want is already taken how
// how do I do that check?
}
}
然后实际运行我会从我的控制器那样做
$userService = $this->serviceFactory->get('user');
$result = $userService->register($_POST['firstName']....);
逻辑(if和else)必须放在register()
类的UserService
方法中吗?因为如果他们进入域对象,当我到达需要数据库进行某些检查的阶段时,如果用户名已经存在,我将如何访问数据库?我真的不知道,因为域对象不应该知道有关数据源的任何信息。
必须有一种方法来访问数据库以进行小型查询,例如检查用户名或电子邮件地址是否已经存在以及是否需要执行其他一些小查询。
我有很多实体/域对象需要做大量的小查询,过去我的模型可以从任何方法中访问数据库并且可以执行这些查询但是这似乎不允许这样做3结构模型,我很想找出正确的方法,因为必须有办法。
我飞行它直到我发现模型是一个分为3个结构的层。
非常感谢任何帮助或推动正确的方向,尤其是现实生活中的好例子。互联网似乎缺乏针对我特定问题的那些。
感谢。
答案 0 :(得分:1)
我正在经历你现在正在做的同样的事情(有趣的是,对于这个确切的问题 - 用户注册/授权)。
我的一条建议是,您不应将模型限制为仅3层(在本例中为3个类)。模型应该是所需的类,以便在保持SRP(单一责任原则)完整性的同时完成工作。
例如,您可能还希望使用UserTableGateway类来补充UserDataMapper,并使用UserCollection类来允许潜在的分页功能或一般用户列表。所有这些都可以成为模型和UserService层的一部分。
要回答有关注册过程特定逻辑的问题,是的,最合适的地方是UserService类的注册方法。
所有这些,你可能想在这里考虑一下你的域名结构。 UserService是最适合注册的地方(通过扩展,登录,恢复密码,更改密码等)?
也许这些事情可能是与账户相关的完全不同的模型的一部分。服务类可能是这样的:
class Account
{
// Think of this as AccountService, it will have a number of collaborators,
// including an Authenticator class for loggin in, a Session class for managing the session
// and of course various persistence classes for storing the user, session and credentials
public function register(UserInterface $user) {}
public function login($email, $password) {}
public function logout(UserInterface $user, $session_id) {}
public function changePassword($user_id, $old_password, $new_password) {}
public function recoverPassword($user_id, $email) {}
}
鉴于UserService可能会负责其他许多其他事情,因此您可以将与用户帐户相关的所有内容保存在自己的服务类中。
从概念上讲,帐户与用户不同,如果它在概念上有所不同,那么它应该拥有自己的类。
现在,就获得帐户服务类所需的依赖关系而言,在我理解复杂系统设计的这个阶段,这超出了我的范围。
答案 1 :(得分:0)
这是一个有趣的问题。我想你的用户数据映射器有找到&的方法。根据某些条件(如用户名)加载用户。因此,在这种情况下,我会通过尝试查找具有提供的用户名的用户(如果存在)来检查UserService :: register内部:
if ($mapper->findUserByUsername($username)) {
// username is already taken, handle this special case
}
顺便说一句,我不知道你是否读过这本书,但是一本非常好的指南是马丁的福勒书 - Patterns of Enterprise Application Architecture。你会发现许多问题都有很好的答案。