php - 可以将域实体的可变属性存储为值对象吗?

标签 php architecture separation-of-concerns

我希望能够更改和传递我的 UserEntity 的某些部分,并且某些部分应该保持不变。

例如,我从不想更改我的 UserEntity 的 ID,但电子邮件或密码之类的东西可能会经常更改,并且也可以被 UserEntity 之外的其他对象使用。

其中一个实例是创建 UserEntity 时。由于没有 id 就不能存在 UserEntity,因此我的 Controller 可以创建一个 UserData 对象来标准化 UserEntity 属性。映射器在数据库中创建一个实体后,它会创建一个新的 UserEntity 并在构造函数中传入 id 和 UserData 对象。

当 UserEntity 需要电子邮件或密码等信息时,它可以只查看其 UserData。

看起来更便携,但这是不是太过分了?有更好的解决方案吗?

注意

  • 我认为这可能是好的原因:可变字段的值需要标准化...有时这些字段需要在实体本身之外传递。例如,在创建实体之前。通过创建一个可以传递的值对象,我们提供了一个标准化点来从任何地方分配这些值,以及可以在实体外部传递的东西。

  • “标准化”是指我的信息无论存在何处都需要统一。例如,email 需要始终为 n 长度且格式有效,name 始终需要为 n长度等。我的目标是我希望能够在一个地方设置这些“规则”......并且由于 UserEntity 的这些属性(可变的)存在于实体本身之外,有时,他们有可能在自己的值(value)对象中独立生活。

最佳答案

我不认为有“唯一正确的方法”来做到这一点(无论您读到什么)...如果它在您的模型中有意义,那么它对我来说听起来不错。当您说“其中许多字段需要标准化”以及为什么不能将其作为 UserEntity 的一部分来完成时,我不确定您的意思到底是什么,但无论如何。也就是说,您很有可能在没有完全独立的对象类的情况下完全完成您想要做的事情。

评论/批评:

您的建议并不真正符合严格的“对象”模型,即 UserData 仅由真正属于 UserEntity 的属性组成,并且与这些属性没有其他潜在关系。

我不太确定为什么您需要一个单独的对象在实体外部传递...如果您需要数据,为什么不能传递 UserEntity 并从那里访问它?在将数据传递给 UserEntity 构造函数之前,您需要对数据执行哪些操作,而通过将数据收集到一个 stdClass 实例中然后在 UserEntity 中处理它无法轻松完成?


如果是我,我会做类似以下的事情(例如,创建一个新用户):

<?
// assume an appropriately defined UserEntity class...

// I'm using stdClass just to keep the parameters together to pass all at once
// I'm assuming some basic user data passed from the browser
$user_data = (object) array(
    'email' => $_REQUEST['email'],
    'name' => $_REQUEST['name'],
    'password' => $_REQUEST['password'],
    'confirm_password' => $_REQUEST['confirm_password']
);

/*
validateData is static so it can be called before you create the new user
It takes the $user_data object to validate and, if necessary, modify fields.
It also takes a $create flag which indicates whether the data should be
checked to make sure all of the necessary fields are there to create the user
with.  This allows you to call it on update with the $create flag unset and it
will pass validation even if it's missing otherwise required fields.
It returns $result, which indicates pass or failure, and the potentially modified
$user_data object
*/
$create = TRUE;
list($result, $user_data) = UserEntity::validateData($user_data, $create);

// equivalence allows you to pass back descriptive error messages
if ($result === TRUE) {
    // create the user in the database, get back $user_id...
    $user = new UserEntity($user_id, $user_data);
}
else {
    // return error to user
}

// access user data either individually, or if you want just make a getter
// for the entire group of data, so you can use it just like you would a
// separate UserData object
send_double_opt_in($user->getUserData());
?>

编辑以解决提供的更多信息:

您说这些属性存在于 UserEntity 之外,并且它们有可能独立存在...您是说这些属性可以被收集、使用和丢弃,甚至不需要用于 UserEntity 对象?如果是这种情况,那么一个单独的对象将完全适合该数据。如果不是,如果数据始终从属于现有或 future 的 UserEntity,那么这些属性将永远不会“独立存在”......让我们称之为“全局数据”的观点。当您将整个系统视为一个整体,而不仅仅是时时刻刻的代码时,数据很可能“属于”UserEntity 类。

至于静态方法,我看不出有什么特别的理由要避免使用它们(很明显),但要避免使用它们。许多其他架构会稍微复杂一些,但这里有一些选择:

  1. 验证构造函数中的数据。问题是如果它没有通过验证,您将不得不删除数据库条目。丑。
  2. 将数据库交互以及数据验证移至构造函数中。这可能会违反您首选的对象模型,您只需要在对象创建后检查它的状态(即设置一个公共(public)属性 $this->status = 'error'; 或类似的东西那是为了告诉你发生了一些你必须处理的坏事)。
  3. 创建一个独立函数来验证数据。丑陋,因为这是一个与 UserEntity 和/或其数据特别相关的函数。
  4. 或者,只需像您建议的那样创建一个单独的 UserData 对象并完成它。与步骤 # 2 非常相似,您必须使用某种 $status 属性来指示验证失败。

关于php - 可以将域实体的可变属性存储为值对象吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9747865/

相关文章:

asp.net-mvc - 如何在 POST 操作中将 View 模型映射回域模型?

php - 将数组键分组到数字范围内,可能吗?

java - 如何使用 com.google.appengine.api.datastore.Text

javascript - Jquery ui 选项卡仅在单击时加载 iframe

.net - Microsoft Orleans 和联合托管客户

architecture - VS2015 Enterprise Reverse Engineer Code to UML

architecture - 什么是信息架构? (什么)与编程有关系吗?

asp.net-mvc-3 - ASP.NET MVC 需要正数作为输入,在模型中保存为负数 - 验证失败

php - 如何查询一对多数据库关系并正确显示行?

ruby-on-rails - 在设计 Rails 数据库模式时如何避免使用关注点?