我希望在我的PHP项目中使用MVC模式。我还想在Model层中使用Dao-Service模式,因为它使数据库引擎易于交换,并将业务逻辑保持在DB交互之外。
现在,我听说验证应该发生在Model层,因为控制器只负责传输数据。这很合理。
然而,它应该在Service层还是实体本身中实现呢?
方法1:在实体中进行验证
class Post extends Entity
{
protected $title;
public function getTitle()
{
return $this->title;
}
public function setTitle($newTitle)
{
if (strlen($newTitle) == 0)
throw new ValidationException('Title cannot be empty.');
$this->title = $newTitle;
}
}
class PostService
{
public static function saveOrUpdate(Post $post)
{
PostDao::saveOrUpdate($post);
}
}
优点:
- 如果我做错了什么,我会立即知道,
- 所有东西都在一个地方,这似乎是一件好事。
缺点:
- 由于使用了复杂的setter和getter,有很多样板代码,
- 将一些业务逻辑添加到实体中,这似乎是一件不好的事情(特别是如果验证非常复杂-例如需要查询数据库/其他服务),
- 序列化和反序列化可能会变得困难。
方法二:在服务中进行验证
class Post extends Entity
{
public $title;
}
class PostService
{
public static function saveOrUpdate(Post $post)
{
if (strlen($post->title) == 0)
throw new ValidationException('Title cannot be empty.');
PostDao::saveOrUpdate($post);
}
}
优点:
- 将业务逻辑保留在服务中,这似乎是一件好事,
- 样板代码最小化。
缺点:
- 当事情出错并且实际上出了什么问题时,我不会立即知道。
- 我无法保证在保存到数据库之前实际进行验证。例如:我必须在两个例程中保存帖子,忘记在其中一个例程中使用
PostService :: saveOrUpdate
代理并直接通过PostDao :: saveOrUpdate
进行操作。这种情况下,验证不会在该例程中进行,并且项目的唯一希望现在是单元测试或者我自己在代码中发现它。因此,在这方面,代码更难维护。
您有任何提示吗?我有什么遗漏吗?到目前为止,该项目只是在草图阶段,所以我准备好迎接任何挑战。
execute()
方法将抛出具有特定错误代码的异常。删除用作外键并带有ON DELETE RESTRICT
约束的行也会引起类似的反应。在PGSQL中,您将拥有更多功能。这些都将在映射器内处理,映射器可以缓存异常并在它尝试存储的域对象上设置“错误状态”。 - tereško