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

Php 在持久化之前创建机器可读名称,php,symfony,doctrine-orm,Php,Symfony,Doctrine Orm,在Symfony2/Doctrine项目中,我有一个名为Developer的实体,特别包括以下字段: 1. firstName 2. lastName 3. machineName 用于创建开发人员项的表单仅显示firstName和lastName字段。我希望在用户创建开发人员项时,根据其他两个字段自动生成machineName 例如,John Doe会给John_Doe,Jérémy Arçouille会给jeremy_arcouille 所以我的问题是: 对于这种(相当常见的)情况,

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

 1. firstName
 2. lastName
 3. machineName
用于创建开发人员项的表单仅显示firstName和lastName字段。我希望在用户创建开发人员项时,根据其他两个字段自动生成machineName

例如,
John Doe
会给
John_Doe
Jérémy Arçouille
会给
jeremy_arcouille

所以我的问题是:

  • 对于这种(相当常见的)情况,是否有一般的最佳实践
  • 我必须从我自己的代码还是很标准的代码
  • 如果(2==true),那么放置代码主干的最佳位置(服务?utils?)是什么
  • 我应该从控制器还是从实体调用这部分代码
  • 注意:因为它将是代码的相当一部分,并且我希望它是可重用的,所以我不想将其放入prePersist生命周期回调中

    我曾经为这个问题制定了一个完整的解决方案,效果很好,但确实很差劲,像意大利面条一样,所以现在我宁愿用正确的Symfony2方式做更多的东西


    谢谢你的帮助。

    好的,这是我目前的想法

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

    // 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上调用此函数


    有什么评论吗?有更好的办法吗?您是如何做到这一点的?

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

  • 创造。此解决方案非常容易实现,从应用程序的角度来看,其工作透明,并且可以与现有代码一起使用

  • 定义侦听器服务:

    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);
        }
    }
    
  • 在Symofny的服务容器中声明它

    <service id="..." class="...">
        <!-- <argument ... /> -->
        <tag name="doctrine.event_subscriber" />
    </service>
    
    
    
  • 你完了

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


  • 注:你不应该做任何复杂的操作,也不应该从你的实体中引用外部类。

    +1为了清楚地写出这个问题,你可以创建一个服务并将它注入到生命周期回调侦听器服务中?你可以使用php iconv:
    iconv('UTF-8',ASCII//TRANSLIT',è')非常感谢!关于你的观点#2,有什么资源/指南/教程可以让我参考吗?我这样问是因为适当的域/业务层的概念听起来很有趣,我想了解更多。再次感谢。