在持久化之前创建机器可读的名称

时间:2014-01-23 01:57:21

标签: php symfony doctrine-orm

在Symfony2 / Doctrine项目中,我有一个名为Developer的实体,特别包括那些字段:

 1. firstName
 2. lastName
 3. machineName

创建Developer项的表单仅显示firstName和lastName字段。我希望当用户根据另外两个字段创建一个Developer项时自动生成machineName。

例如,John Doe会提供john_doeJérémy Arçouille会提供jeremy_arcouille

所以我的问题是:

  1. 这个(很常见的)案例是否有一般的最佳做法?
  2. 我是否需要自己编写代码或者它是非常标准的东西?
  3. 如果(2 == true)放置那段代码的最佳位置(服务?utils?)?
  4. 我是应该从控制器还是从实体调用这部分代码?
  5. 注意:因为它是相当一部分代码,我希望它可以重用,我不想进入prePersist生命周期回调

    我曾经为这个问题开发了一个完整的解决方案并且运行良好,但实际上是非常蹩脚和意大利式的,所以我宁愿现在以适当的Symfony2方式做更多的事情。

    感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

在这种情况下,您可以尝试至少两种方法。

  1. 创建prePresists event listener。该解决方案非常易于实现,从应用程序的角度透明地工作,并且可以与现有代码一起使用。

    1. 定义您的侦听器服务:

      use Doctrine\Common\EventSubscriber;
      use Doctrine\ORM\Events;
      use Doctrine\ORM\Event\LifecycleEventArgs;
      
      class MyEventListener implements EventSubscriber
      {
          public function __construct(/* ... */)
          {
              /* you can use other services here */
          }
      
          public function prePersist(LifecycleEventArgs $event)
          {
              $developer = $event->getEntity();
      
              if (!($developer instanceof Developer) || $developer->hasMachineName()) {
                  return;
              }
      
              ...
              $developer->setMachineName(...);
          }
      
          public function getSubscribedEvents()
          {
              return array(Events::prePersist);
          }
      }
      
    2. 在Symofny的服务容器中声明它

      <service id="..." class="...">
          <!-- <argument ... /> -->
          <tag name="doctrine.event_subscriber" />
      </service>
      
    3. 你已经完成了。

  2. 为您的应用程序创建适当的域/ bussines层。这需要更多工作,迫使您遵循一些通用准则,但使您的代码更灵活,更易于维护。简而言之,不是直接在控制器中使用Doctrine的ObjectManager,而是创建一个专门用于处理域对象的全新服务器层。此层sholud包含一个服务,该服务负责使用save(Developer $dev)方法保持开发人员。从第一种方法开始,此方法应与MyEventListener完全相同。

  3. PS。您不应该执行任何复杂操作或从实体中引用外部类。

答案 1 :(得分:0)

好的,这就是我现在提出来的。

我在MyBundle \ Utils \ MachinesNames.php中创建了一个类文件,其中包含一个由Developer实体的类调用的方法:

// MyBundle\Utils\MachineNames.php
class MachinesNames
{
    public static function createDeveloperName(array $nameArray)
    {
        // code goes here

        return $machineName;
    }

    public static function createActivityName(array $nameArray)
    {
        // other stuff...

        return $machineName;
    }
}


// MyBundle\Entity\Developer.php
class Developer
{
    public function setMachineName()
    {
        $nameArray = array(
            'firstName' => $this->getFirstName(),
            'lastName' => $this->getLastName(),
        );

        $machineName = MachineNames::createDeveloperName($nameArray);

        $this->setName($machineName);
    }
}

在具有生命周期回调的prePersist上调用此函数。

有何评论?有没有更好的办法?你会怎么做?