PHP - 工作单元应该放在MVC应用程序中的哪个位置?

时间:2015-05-06 21:05:17

标签: php model-view-controller domain-driven-design unit-of-work

问题的背景信息

在我的index.php文件中,我有这个:

$service_factory = new ServiceFactory(new MapperFactory($db), new DomainFactory);

我对UnitOfWork应该如何使用我的应用程序的理解是这样的(状态是指脏,干净等):

  • Mapper - 标记对象的状态
    • $user->markNew();$uow->registerNew($user);
  • 域名 - 可以检查其当前状态。例如:$this->isDirty();
  • 服务 - 调用commit()以完成交易
    • $this->uow->commit()$mapper->commit()

我的UnitOfWork的提交功能看起来像这样(随意改进):

public function commit()
{
    // Inserts the new objects
    foreach ($this->newObjects as $newObject) {
        $mapper = $this->mapperFactory->createFromDomainObject($newObject);
        $mapper->insert($newObject);
    }

    // Update the dirty objects
    foreach ($this->dirtyObjects as $updateObject) {
        $mapper = $this->mapperFactory->createFromDomainObject($updateObject);
        $mapper->update($updateObject);
    }

    // Delete the removed
    foreach ($this->deletedObjects as $deletedObject) {
        $mapper = $this->mapperFactory->createFromDomainObject($deletedObject);
        $mapper->delete($deletedObject);
    }
}

选项#1 - ServiceFactory

Pro :如果我有一个服务调用另一个服务,我不必担心不会在彼此之间传递Domain对象,因为它们将共享UnitOfWork的相同实例。 / p>

Con :我必须将UnitOfWork对象一直传递给mapper对象,这将是以下多个级别:ServiceFactory - >服务 - > MapperFactory - > Mapper ...... Ew。这对我来说并不合适。 此外,由于UnitOfWork需要MapperFactory,我的index.php将更改为:

$uow = new UnitOfWork(new MapperFactory($db));
$mapper_factory = new MapperFactory($db, $uow);
$service_factory = new ServiceFactory($mapper_factory, new DomainFactory, $uow);

正如你所看到的,它就像是一堆UnitOfWorks和MapperFactories,只是不太漂亮。

选项#2 - 服务

Pro :我不会有一个丑陋的index.php文件。我只想为每个Service对象创建一个新的UnitOfWork实例。在我的ServiceFactory里面看起来像这样:

/**
 * Create method
 *
 * This will create a new Service class if it hasn't 
 * already been instantiated, and return it.
 *
 * @param string $name          The class name
 * @return mixed
 */
public function create($name)
{
    $class = '\\MyApp\\Service\\' . $name;
    if ( array_key_exists($class, $this->cache) === false) {
        if (class_exists($class)) {
            $uow = new UnitOfWork($this->mapperFactory);
            $this->cache[$class] = new $class(
                $this->mapperFactory, 
                $this->domainFactory,
                $uow
            );
        } else {
            throw new Exception(sprintf('Service class %s does not exist.', $class));
        }
    }
    return $this->cache[$class];
}

这对我来说似乎更清洁了。

Con :我无法互相呼叫服务。但是,我正处于这个项目的开始阶段,这是我第一次尝试某种正确的" MVC应用程序,所以我不确定我是否会让服务很多或者根本不相互调用。

选项#3 - MapperFactory

专业:不是我能看到的任何东西,但它仍然是一种选择。在我的index.php中我可以拥有:

$uow = new UnitOfWork($db);
$service_factory = new ServiceFactory(new MapperFactory($db,$uow), new DomainFactory);

我的UnitOfWork类可以扩展MapperFactory类,因此不需要创建MapperFactory的两个实例。我会将UnitOfWork的相同实例传递给每个Mapper。

Con :我必须通过这样的方式在我的Service类中提交事务:

$this->mapperFactory->unitOfWork->commit();

我喜欢的功能调用太多了。另外,我不确定如何在没有引用UnitOfWork对象的情况下允许域对象检查其状态。

也许我有些遗漏的东西,但我们非常感谢任何建议或有用的见解!

1 个答案:

答案 0 :(得分:2)

工作单元控制通常会放在DDD中的应用程序服务中,所以我猜这意味着选项#2。

请注意,您的整个问题可能是由于设计过于复杂。

  • 太多Factories通常是代码气味 - 特别是DomainFactory一个:)是否有特定的理由使用它们?

  • 通过传递域对象来创建(对象/关系,我猜)映射器实例似乎是人为的。此外,MapperFactory的含义并不明显。它是否创建了映射器?是映射和创建吗?

  • 您是否尝试从头开始实施自己的工作单元?可能会重新发明轮子,大多数ORM框架都内置了这个功能。虽然我不知道PHP。