1

什么是使用 ZF2 和 Doctrine 实现业务逻辑模型的“正确方法”,同时创建干净的 OOP 和 MVC 结构,并为模型提供对 EntityManager 的访问权限?

尽管我很想将 Doctrine Repositories 用于所有业务逻辑,但我知道它们应该主要用于执行复杂的查询。我也知道 ZF2 中的模型可以通过多种方式提供依赖项(EntityManager):ZF2:依赖注入以正确的方式完成 http://zend-framework-community.634137.n4.nabble.com/ZF2-Injecting-对象到控制器或从服务定位器获取对象 td4656872.html

为了说明现实生活中的问题,我们如何为简单的网上商店功能创建模型层:

首先,我们将拥有实体

/**
 * @Entity(repositoryClass="App\Repository\ProductRepository")
 * @Table(name="products")
 */
class Product { ... }

/**
 * @Entity(repositoryClass="App\Repository\ProductgroupRepository")
 * @Table(name="productgroups")
 */
class Productgroup { ... }

以及为我们提供更详细查询功能的存储库

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() { ... }
    ...
}

但是我们把这样的业务逻辑放在哪里呢?

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
- ...

例如,是否应该将 Productgroup 业务模型创建为在服务级别注入 EntityManager 的类?--

class Productgroup implements ServiceLocatorAwareInterface
{
    public function removeProductFromProductgroup( $productgroup, $product) { }
    public function addProductToProductgroup( $productgroup, $product) { }
}

还是应该扩展原始实体以访问其内部结构?--

class Productgroup extends \Application\Entity\Productgroup 
    implements ServiceLocatorAwareInterface
{
    public function removeProductFromProductgroup( $productgroup, $product) { }
    public function addProductToProductgroup( $productgroup, $product) { }
}

如果是这样,它是否也应该有某种设置状态方法?公共函数集($product){$this->populate($product);}

4

2 回答 2

1

关于在哪里有业务逻辑,显然是模型。我不建议扩展您的实体,因为任何与设置/获取实体对象无关的逻辑都应该在您的实体之外。

所以答案是肯定的,我会将实体管理器注入模型中。但是,您是否使用服务定位器或其他方法进行 DI 取决于您。

您正在思考的问题实际上是关于 OOP、DI、DiC 等的。请阅读专家关于 DI 的一些最佳博客文章。我在下面列出了它们:

将依赖注入提升到不同的级别真的取决于您。如果您查看 Martin Fowler 的博客,您可以了解构造函数注入、setter 注入和为您执行注入的 DiC。您必须为您的系统接听电话。对我有用的是,在模块依赖中,我进行构造函数注入(以便依赖项清晰可见)。任何作为服务的东西,都会通过 DiC 或 ServiceLocator 从我的模块外部调用。

反对服务定位器模式的唯一论据是它将依赖注入隐藏到其配置中,并且不清晰可见。

于 2013-10-25T15:32:22.587 回答
0

我将数组集合用于此类任务。这个对象有各种非常有用的方法,比如 clean()、contains() 等。

我倾向于将我的 oneToOne、oneToMany 等关系存储在 arrayCollections 中。

在您的实体中,您必须使用构造函数来启动集合。

use Doctrine\Common\Collections\ArrayCollection;

/**
 * @ORM\OneToMany(targetEntity="yourModule\Entity\yourEntity", mappedBy="yourRelation", cascade={"persist"})
 */
protected $yourCollection;

public function __construct()
{
   $this->yourCollection = new ArrayCollection();
}
//once I have the collection I usually create methods like add, remove, etc methods like so:
public function addToCollection($toAdd) {
   $this->yourCollection->add($toAdd);
}

public function removeFromCollection($toRemove) {
   $this->yourCollection->removeElement($toRemove);
}

//etc.....
于 2013-10-24T07:53:21.900 回答