What is "the right way" to implement business logic Models with ZF2 and Doctrine, while creating a clean OOP and MVC structure, and providing the Models with access to the EntityManager?
Althought I am tempted to use the Doctrine Repositories for all the business logic, I know they should primarily be used to perform complex queries. I also know that a model in ZF2 can be provided with dependencies (EntityManager) in several ways: ZF2: Dependency injection done the proper way http://zend-framework-community.634137.n4.nabble.com/ZF2-Injecting-objects-to-a-controller-or-getting-objects-from-the-service-locator-td4656872.html
To illustrate the problem in real life, how do we create a Model layer for a simple Web shop functionality:
Firstly, we would have the Entities
/**
* @Entity(repositoryClass="App\Repository\ProductRepository")
* @Table(name="products")
*/
class Product { ... }
/**
* @Entity(repositoryClass="App\Repository\ProductgroupRepository")
* @Table(name="productgroups")
*/
class Productgroup { ... }
And the Repositories which give us more detailed query capabilities
class ProductRepository extends EntityRepository {
public function isAvailable() { ... }
public function getQuantity() { ... }
public function getProductImages() { ... }
public function getRelatedProducts() { ... }
...
}
class ProductgroupRepository extends EntityRepository {
public function getAvailableProducts() { ... }
public function getAllProducts() { ... }
...
}
But where do we place the business logic such as this?
Products functionalities:
- createNewProduct( $data ), eg. update prices, retrieve new quantities, generate a new image gallery, notify the administrator, ...
- deleteProduct(), eg. delete corresponding files and existing associations, put product into archive
- ...
Productgroups functionalities:
- removeProductFromProductgroup( $product), eg. update ordering in group, remove associations, ...
- addProductToProductgroup( $product ), eg. update ordering in group, create associations, ...
- deleteProductgroup(), eg. delete productgroup, set all it's products as uncategorized
- ...
Should the Productgroup business model be created, for example, as a class which is injected with the EntityManager at the service level? --
class Productgroup implements ServiceLocatorAwareInterface
{
public function removeProductFromProductgroup( $productgroup, $product) { }
public function addProductToProductgroup( $productgroup, $product) { }
}
Or should it maybe also extend the original entity so as to have access to its internal structure? --
class Productgroup extends \Application\Entity\Productgroup
implements ServiceLocatorAwareInterface
{
public function removeProductFromProductgroup( $productgroup, $product) { }
public function addProductToProductgroup( $productgroup, $product) { }
}
And if so, should it also have some kind of a set state method ? public function set( $product ) { $this->populate( $product ); }