将业务逻辑与 PHP 原则 2 分开

Separating business logic from PHP Doctrine 2

我使用 symfony 2.3 和 php 学说 2。

程序有以下型号:

我非常喜欢这个class的设计。我想了很多。 一切都很棒。但!存在一个问题:添加和删除方法中的操作必须在事务中执行。

PHP 原则 2 中的交易代码如下所示:

<?php
$em->getConnection()->beginTransaction();
try {
    //... do some work
    $em->getConnection()->commit();
} catch (Exception $e) {
    $em->getConnection()->rollback();
    throw $e;
}

但是我如何在 BadOrderList 中调用这段代码?

我花了很多时间去掉依赖数据库(和相应的PHPDoctrine 2),然后重新创建呢? 现在依赖隐藏在 classes BadOrderEntryRepository 和 BadOrderEntryManager 中。

如何在classBadOrderList中隐藏对事务机制的依赖?

您可以将 class 转换为服务,并在将服务容器注入 class 后随心所欲地调用它。 您可以在此处找到有关 dependency injection 的更多信息:

$injectedContainerOfService->get("id_of_your_service")

经过我们的讨论,我对你的问题有了答案。 问题实际上不是 "How to hide the dependence on the transaction mechanism in class BadOrderList?",而是 如何将模型与持久层分离?(在该特定情况下为 Doctrine2)。

我试着用一些代码来说明我的建议

class BadOrderEntry
// Bad - is too bad word to describe an order here. Why is it bad? Is it Declined? Cancelled?
{
   private $order;
   // some code
}
class BadOrderEntryFactory 
{ 
   // If there is not to much processing to build BadOrderEntry better use factory method like BadOrderEntry::fromOrder($order); 
}
class BadOrderEntryRepository 
{ 
   // here is some read model 
}
class BadOrderEntryManager  
// ITS a part of our model and shouldn't be coupled to ORM
{
  public function save(BadEntry $be) 
  {
    // some model events, model actions
    $this->doSave($be); // here we should hide our storage manipulation
  }

  protected function doSave($be) // it can be abstract, but may contain some basic storage actions  
  { 
  }

  // similar code for delete/remove and other model code
}
class ORMBadOrderEntryManager extends BadOrderEntryManager 
// IT'S NOT the part of your model. There is no business logic. There is only persistent logic and transaction manipulation
{ 
  protected $entityManager;

  // some constructor to inject doctrine entitymanager

  protected doSave($be)
  {
    $em = $this->entityManager;
    $em->getConnection()->beginTransaction(); // suspend auto-commit
    try {
      $em->persist($be);
      $em->flush();
      $em->getConnection()->commit();
    } catch (Exception $e) {
      $em->getConnection()->rollback();
      throw $e;
    }
  }
}
// You can also implement ODMBadOrderEntryManager, MemcacheBadOrderEntryManager etc.

因此,如果我们谈论目录结构,您的所有模型都可以从 bundle 中移出并在任何地方使用。您的 Bundle 结构将如下所示:

BadEntryBundle
|
+ Entity
| |
| --- BadOrderEntryEntity.php
|
+ ORM
| |
| --- ORMBadOrderEntryManager.php 

然后您只需将 ORMBadOrderEntryManager 注入 BadOrderEntryList