使用后置

时间:2019-05-04 07:50:06

标签: symfony entity

我有一个带有autogenarete id的产品,还有一个productcode字段,该字段根据用户的选择与自动生成的键结合使用以生成产品代码来获取值。但是,插入新产品时,我无法获取自动生成ID。

我第一次使用了prepersist和preupdate,但是插入新产品时并没有获取ID。仅在更新时它会获取ID

/**
 * @ORM\PrePersist
 * @ORM\PreUpdate
 */
public function setProductcode() 
{


  $option1 = $this->option1;   
  $option2 = $this->option2; 
  $id = $this->id;

  $whole = $option1.''.$option2.''.$id;    

  $this->productcode = $whole;


}

我尝试使用postpersist,并将我的字段更改为nullablae true,但将产品代码保存为null。

/**
 * @var string
 *
 * @ORM\Column(type="string", length=191, unique=true, nullable=true)
 */
private $productcode;

我将postload和postpersist一起使用,并且确实将产品代码显示为输出..但它没有将其保存在数据库中。

 * @ORM\PostLoad
 * @ORM\PostPersist

我如何获取实体中的ID并将其放在其他字段中?预先感谢!


编辑

我做了一个easyadminsubcriber,当我使用pre_persist返回时,它可以工作。 但是,下面的代码已更新为post_persist。但我无法在实现lifelifeeventargs的同时实现flush函数。

我又收到以下错误

Argument 2 passed to App\EventSubscriber\EasyAdminSubscriber::setProductcode() must be an instance of Doctrine\Common\Persistence\Event\LifecycleEventArgs, string given, called in 

下面是我的post_persist代码

<?php 
# src/EventSubscriber/EasyAdminSubscriber.php
namespace App\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\EventDispatcher\GenericEvent;
use App\Entity\Product;
use Doctrine\Common\Persistence\Event\LifecycleEventArgs;
class EasyAdminSubscriber implements EventSubscriberInterface
{


    public static function getSubscribedEvents()
    {
        return array(
            'easy_admin.post_persist' => array('setProductcode'),
        );
    }


    /**
     * @param LifecycleEventArgs $args
     */
    public function setProductcode(GenericEvent $event, LifecycleEventArgs $args)
    {

      $entityManager = $args->getEntityManager();


        $entity = $event->getSubject();



        if (!($entity instanceof Product)) {
            return;
        }


        $whole = 'yooo'; 


        $entityManager->flush();

        $entity->setProductcode($whole);

        $event['entity'] = $entity;
    }
}

3 个答案:

答案 0 :(得分:2)

默认情况下,仅当实体被丢弃到数据库时才设置ID。这意味着,您必须先刷新实体然后再次刷新,然后生成产品代码。教义不能在实际从数据库收到回信之前就使用一些奇特的魔术来确定id,因此实际上并没有另一种方法。 (如果您想完成所有这些实体操作,那么我将无法想象另外一种实用而干净的方法来实现这一点)

更新

您应该使用PostPersist(同时保留PreUpdate)。

  

使实体具有持久性后,该实体就会发生postPersist事件。数据库插入操作后将调用它。生成的主键值在postPersist事件中可用。 (source

因此,生成的主键在那里可用。但是,这只是在刷新实体后 。因此,您还必须再次刷新 ,以将产品代码也写入数据库。

创建适当的事件处理程序(因为“ setProductcode”是设置程序,而不是事件处理程序,至少在名称上是如此)

/**
 * PostPersist triggers after the _creation_ of entities in db
 * @ORM\PostPersist
 */
public function postPersist(LifecycleEventArgs $args) {
    $this->setProductcode();
    // need to flush, so that changes are written to database
    $args->getObjectManager()->flush();
}   

/**
 * PreUpdate triggers before changes are written to db
 * @ORM\PreUpdate
 */
public function preUpdate() {
    $this->setProductcode(); 
    // don't need to flush, this happens before the database calls
}

(有关更多信息,请参见https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html#lifecycle-callbacks-event-argument

(免责声明:此答案自创建之初就经过大量编辑,部分关联注释没有相关参考文献

答案 1 :(得分:2)

如果仅仅是其他列的连接,您真的需要保留产品代码吗?仅仅使用高效的吸气剂怎么办?

public function getProductcode() 
{
  if(!empty($this->productcode)){
    return $this->productcode;
  }

  if(empty($this->id)){
    return "to be determined";
  }

  $this->productcode = $this->option1 . $this->option2 . $this->id;

  return $this->productcode;
}

答案 2 :(得分:0)

好的,所以我现在有2个解决方案可以在另一个字段中设置自动生成的ID(不使用控制器)。第一个直接在实体文件本身中,如@jakumi答案所示。

   public function setProductcode()
    {

      $part = $this->producttype->gettypenumber();
      $id1 = $this->id;
      $part = sprintf("%03d", $id1);

      $whole = $part1.''.$part2;    

      return $this->productcode= $whole;

    }


/**
 * PostPersist triggers after the _creation_ of entities in db
 * @ORM\PostPersist
 */
public function postPersist(LifecycleEventArgs $args) {


    $this->setPoductcode();
    // need to flush, so that changes are written to database
    $args->getObjectManager()->flush();
}   

/**
 * PreUpdate triggers before changes are written to db
 * @ORM\PreUpdate
 */
public function preUpdate() {


    $this->setProductcode();
    // don't need to flush, this happens before the database calls
}

另一种解决方案是使用eventsubscriber。

<?php 
# src/EventSubscriber/EasyAdminSubscriber.php
namespace App\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\EventDispatcher\GenericEvent;
use Doctrine\ORM\EntityManagerInterface;
use App\Entity\Product;
use Doctrine\Common\Persistence\Event\LifecycleEventArgs;
class EasyAdminSubscriber implements EventSubscriberInterface
{




    public function __construct(EntityManagerInterface $em) {

        $this->em = $em;
    }



    public static function getSubscribedEvents()
    {
        return array(
            'easy_admin.post_persist' => array('setProductcode'),
        );
    }



    public function setProductcode(GenericEvent $event)
    {


        $entity = $event->getSubject();

        if (!($entity instanceof Product)) {
            return;
        }


        $this->em->flush();

        $entity->setProductcode();

        $this->em->flush();

    }
}

以及带有postpersist和preupdate的我的实体代码

/**
 * @ORM\PostPersist
 * @ORM\PreUpdate
 */
public function setProductcode() 
{


    $part1 = $entity->getProducttype()->getTypenumber();
    $id1 = $entity->getId();
    $part2 = sprintf("%03d", $id1);
    $whole = $part1.$part2; 

  $this->productcode = $whole;


}

感谢@Jakumi提供这两种解决方案的说明和准则。