我在验证引用其他模型的模型时遇到了问题。
我有一个“用户”模型和一个“配置文件”模型。我想创建配置文件,但我需要检查用户是否真的存在。
在我的配置文件模型中,我有一个方法“validateUser”,但我要么必须向数据库中的特定表写入查询,要么必须创建一个用户模型对象并调用存在(id)。
这两种选择似乎都有很多缺点。表名可能会改变我必须检查所有使用它的模型。对于用户模式对象,我必须在配置文件模型中创建一个对象或注入它。
解决这个问题的最佳方法是什么?
在现实世界的情况下,验证很少是一个简单的过程。相反,您有几个不相关的问题:
如果您使用活动记录来表示您的域模型 (不要与 MVC 中的 M 混淆),那么所有这三个方面都将成为单个对象的责任。
这就是你现在所拥有的。
最好的选择是将所有这些职责分开(所有这些都是SRP)。基本上,您所做的是将当前设置划分为不同的结构组:
域对象:用于处理域实体的特定规则
数据映射器:用于存储抽象
services:用于域对象和映射器(或其他域对象)之间的交互
由于您的问题有些令人困惑(用户和配置文件以及保存和验证,然后一些东西不存在),我不确定我是否理解正确,但这里有一个小例子:
public function createProfile( $id, $email, $name )
{
$account = new Account;
$account->setId( $id );
$accountMapper = new AccountMapper( $pdo ); // explained below
if ( $accountMapper->fetch( $account ) === false )
{
$this->errors[] = .. something about missing account
return;
}
$profile = new Profile;
$profile->setEmail( $email )
->setName( $name );
if ( $profile->isValid() === false )
{
$this->errors[] = .. something about invalid profile
return;
}
try
{
$profileMapper = new ProfileMapper( $pdo ); // explained below
$profileMapper->store( $profile );
}
catch ( Exception $e )
{
$this->errrors[] = .. something about failing to create profile
return;
}
$account->addProfile( $profile );
$accountMapper->store( $account );
}
这是一个极其简化的例子。尤其是在映射器被初始化的地方,因为现实世界中的那部分将由某个工厂处理。有点像这篇文章中描述的。
这里的重点是域数据的验证和数据库完整性的保险是分开进行的。用于与数据库交互的底层 API 实际上会返回错误代码是您违反UNIQUE KEY
或FOREIGN KEY
任何其他约束,然后您可以使用它来确定出了什么问题。
该方法本身将是服务的一部分(在这种情况下 - 一些管理用户帐户的服务)。
注意:如果您的应用程序需要在每个操作中执行多个 SQL 交互,并且这些交互需要作为具有回滚能力的事务来完成,那么,您应该考虑实现Units of Work ,而不是直接使用数据映射器。要了解 UoW,您必须阅读Patterns of Enterprise Application Architecture,因为它是一个非常广泛的主题。