I've read the Fowler's article about "Anemic Domain Model" (link: http://www.martinfowler.com/bliki/AnemicDomainModel.html), and I agree with his point of view.
I've tried to create an application where Entities are simple POPO, but in this way, I have a fat service layer, whereas put some logic into entities would be the simplest solution.
So I would have an architecture like this:
^
| Twig
| Controller | API
| Service
| Model
| Entity
Where:
Entity: would be simple POPO, just a bag of setter and getter
Model: would be Entity Object decorated with business logic
Service: contains all business logic which involve more than one Entity (here I would place also validation task), and acts like a converter entity -> model
Controller | API: just matches Request with Service, ParamConvert and check autorization
Twig: presentation layer
My problem is how to hide entity layer to controllers and works only with model. In order to decorate my entities with business logic, I thought build a service that uses repository and decorates results (I can't find another way to achieve that).
So, a stupid example:
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());
}
...
}
And upper layers are made in the usual way. I know it's not a good solution, but I can't find a better way to have a Model layer. And I really don't like to have something like:
$articleService->isAvailable($article);
instead of a more OO:
$article->isAvailable();