使用 post-persist 为附加字段获取自动生成的 ID
get autogenerated id for additional field, using post-persist
我有一个带有自动生成 ID 的产品,还有一个产品代码字段,它根据用户选择获取值,并结合自动生成的密钥来生成产品代码。但是,我无法在插入新产品时获取自动生成的 ID。
我使用了 first 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 return 时它可以工作。
但是,下面的代码已更新为 post_persist。但是我无法将刷新功能与 lifecycleeventargs 一起实现。
我收到以下错误
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;
}
}
默认情况下,仅当实体刷新到数据库时才设置 id。这意味着,您必须在刷新实体然后再次刷新后生成产品代码。 doctrine 不能使用一些奇特的魔法在它真正从数据库中收到回复之前确定 id,所以没有其他方法。 (如果你想在实体中做所有这些,我无法想象另一种实用和干净的方法来做到这一点)
更新
您应该使用 PostPersist(同时保留 PreUpdate)。
The postPersist event occurs for an entity after the entity has been made persistent. It will be invoked after the database insert operations. Generated primary key values are available in the postPersist event. (source)
所以,生成的主键在那里可用。但是,这只是 在 刷新实体之后。因此,您必须再次刷新 才能将产品代码也写入数据库。
创建适当的事件处理程序(因为 "setProductcode" 是 setter,而不是事件处理程序,至少在名称方面如此)
/**
* 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
}
(免责声明:此答案自首次创建以来经过大量编辑,部分相关评论没有相关参考)
如果它只是其他列的串联,您真的需要保留产品代码吗?只使用高效的 getter 怎么样?
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 个解决方案来在另一个字段中设置自动生成 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
}
另一个解决方案是使用事件订阅者。
<?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 对这两种解决方案的解释和指导。
我有一个带有自动生成 ID 的产品,还有一个产品代码字段,它根据用户选择获取值,并结合自动生成的密钥来生成产品代码。但是,我无法在插入新产品时获取自动生成的 ID。
我使用了 first 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 return 时它可以工作。 但是,下面的代码已更新为 post_persist。但是我无法将刷新功能与 lifecycleeventargs 一起实现。
我收到以下错误
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;
}
}
默认情况下,仅当实体刷新到数据库时才设置 id。这意味着,您必须在刷新实体然后再次刷新后生成产品代码。 doctrine 不能使用一些奇特的魔法在它真正从数据库中收到回复之前确定 id,所以没有其他方法。 (如果你想在实体中做所有这些,我无法想象另一种实用和干净的方法来做到这一点)
更新
您应该使用 PostPersist(同时保留 PreUpdate)。
The postPersist event occurs for an entity after the entity has been made persistent. It will be invoked after the database insert operations. Generated primary key values are available in the postPersist event. (source)
所以,生成的主键在那里可用。但是,这只是 在 刷新实体之后。因此,您必须再次刷新 才能将产品代码也写入数据库。
创建适当的事件处理程序(因为 "setProductcode" 是 setter,而不是事件处理程序,至少在名称方面如此)
/**
* 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
}
(免责声明:此答案自首次创建以来经过大量编辑,部分相关评论没有相关参考)
如果它只是其他列的串联,您真的需要保留产品代码吗?只使用高效的 getter 怎么样?
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 个解决方案来在另一个字段中设置自动生成 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
}
另一个解决方案是使用事件订阅者。
<?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 对这两种解决方案的解释和指导。