我阅读了Fowler关于“贫血领域模型”的文章(链接:http://www.martinfowler.com/bliki/AnemicDomainModel.html),并且我同意他的观点。
我尝试创建一个应用程序,其中实体是简单的POPO,但这样做将导致服务层过于臃肿,而将一些逻辑放入实体中将是最简单的解决方案。
因此,我的架构应该像这样:
^
| Twig
| Controller | API
| Service
| Model
| Entity
定义:
实体:是一个简单的POPO类,只包含一些setter和getter方法。
模型:是对实体对象进行业务逻辑装饰的类。
服务:包含所有涉及多个实体的业务逻辑(这里还会执行验证任务),并充当实体->模型的转换器。
控制器|API:将请求与服务匹配,并执行ParamConvert和授权检查。
Twig:表示层。
我的问题是如何将实体层隐藏起来,只与模型层交互。 为了对实体进行业务逻辑装饰,我考虑构建一个使用仓库并装饰结果的服务(我无法找到其他实现方式)。
下面是一个愚蠢的例子:
namespace ...\Entity\Article;
class Article {
private $id;
private $description;
// getter and setter
}
namespace ...\Model\Article;
class Article {
private $article; // all methods will be exposed in some way
private $storeService; // all required services will be injected
public function __construct($article, $storeService) {
$this->article = $article;
$this->storeService = $storeService;
}
public function getEntity() {
return $this->article;
}
public function isAvailable() {
return $storeService->checkAvailability($this->article);
}
...
}
class ArticleService {
private $storeService; // DI
private $em; // DI
private $repository; // Repository of entity class Article
public function findById($id) {
$article = $this->repository->findById($id);
return new \Model\Article($article, $storeService);
}
public function save(\Model\Article $article) {
$this->em->persist($article->getEntity());
}
...
}
并且上层按照通常的方式制作。我知道这不是一个好的解决方案,但我找不到更好的方法来拥有模型层。而且我真的不喜欢有这样的东西:
$articleService->isAvailable($article);
使用更面向对象的方式:
$article->isAvailable();