php - Symfony - 创建新实体而不是更新现有实体
问题描述
我有以下结构:
包含指向属性及其值的链接的类别属性:
<?php
class CategoryProperty
{
// ...
/**
* @var Property
*
* @ORM\ManyToOne(targetEntity="App\Entity\Property")
* @ORM\JoinColumn(onDelete="cascade", nullable=false)
*/
private $property;
/**
* Набор значений свойства доступных в product builder, null если любое значение.
*
* @var PropertyValueEntry
* @Assert\Valid
*
* @ORM\OneToOne(targetEntity="App\Entity\Properties\PropertyValues\PropertyValueEntry",
* cascade={"persist", "remove"})
*/
private $propertyValue;
// ...
}
带有鉴别器映射的抽象属性值类型:
<?php
/**
* @ORM\Entity
* @ORM\InheritanceType("JOINED")
* @ORM\DiscriminatorColumn(name="type", type="integer")
* @ORM\DiscriminatorMap({
* "1": "StringValue",
* "2": "IntegerValue",
* "3": "BooleanValue",
* "4": "TextValue",
* "6": "EnumValue",
* "7": "SetValue",
* "9": "LengthValue",
* "10": "AreaValue",
* "11": "VolumeValue",
* "12": "MassValue",
* })
* @ORM\Table(name="properties_values__value_entry")
*/
abstract class PropertyValueEntry
{
/**
* @var Property
*
* @ORM\ManyToOne(targetEntity="App\Entity\Property")
*/
private $property;
public function __construct(Property $property)
{
$this->property = $property;
}
public function getProperty(): Property
{
return $this->property;
}
/**
* @return mixed
*/
abstract public function getValue();
/**
* @param mixed $value
*/
abstract public function setValue($value): void;
}
以及一个示例具体值类型:
<?php
/**
* @ORM\Entity
* @ORM\Table(name="properties_values__integer_value")
*/
class IntegerValue extends PropertyValueEntry
{
/**
* @var int
* @Assert\NotNull
*
* @ORM\Column(type="integer")
*/
private $value = 0;
public function getValue(): int
{
return $this->value;
}
/**
* @param int|null $value
*/
public function setValue($value): void
{
if (!\is_int($value)) {
throw new InvalidArgumentException('BooleanValue accepts integer values only');
}
$this->value = $value;
}
}
由于某种原因,提交表单时,不会更新 IntegerValue 的值,而是创建一个新实体,并在 properties_values__value_entry / properties_values__integer_value 中创建新行。我尝试通过 $this->em->persist($entity) 进行跟踪,其中 $entity 是 CategoryProperty,并且似乎 IntegerValue 被标记为脏并重新创建。如何跟踪发生这种情况的原因?我的表单处理非常标准:
<?php
public function editAction(): Response
{
$id = $this->request->query->get('id');
$easyadmin = $this->request->attributes->get('easyadmin');
$entity = $easyadmin['item'];
$isReload = 'reload' === $this->request->request->get('action');
$editForm = $this->createForm(CategoryPropertyType::class, $entity, [
'category' => $this->getCatalog(),
'is_reload' => $isReload,
]);
$deleteForm = $this->createDeleteForm($this->entity['name'], $id);
$editForm->handleRequest($this->request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
if (!$isReload) {
$this->em->persist($entity);
$this->em->flush();
return $this->redirectToReferrer();
}
}
return $this->render($this->entity['templates']['edit'], [
'form' => $editForm->createView(),
'entity' => $entity,
'delete_form' => $deleteForm->createView(),
]);
}
更新 #1 我已经尝试过的:通过 ID 从实体管理器中检索类别属性
$entity = $this->em->find(CategoryProperty::class, $id);
总而言之,这似乎与我根据选择创建了一个动态表单这一事实有关。当我添加一个类别属性时,我会显示一个带有属性类型列表(整数、字符串、面积、体积等)的下拉列表,并在选择后显示该属性的新表单。尽管这可以正常工作并且可以毫无问题地添加新属性,但似乎编辑相同属性的代码缺少某些内容,而不是更新它重新创建它。
解决方案
可能性#1:直接从实体管理器加载实体
您似乎根本没有检索要修改的现有实体。
$entity = $easyadmin['item'];
这不应该使用 Doctrine 来检索现有实体吗?例如:
if (!($entity = $this->getRepository(CategoryProperty::class)->findOneById($id))) {
throw $this->createNotFoundException("Category property not found.");
}
半相关:您可能还想检查是否指定了整数 ID,这$id = $this->request->query->get('id');
是非常假设的:
if (intval($id = $this->request->query->get('id')) < 1) {
throw $this->createNotFoundException("Category property not specified.");
}
可能性 2:缺少具有一对一关系的标识符引用
我认为您可能会得到重复,因为CategoryProperty
不保留对 a 的任何引用PropertyValueEntry
。
/**
* Набор значений свойства доступных в product builder, null если любое значение.
*
* @var PropertyValueEntry
* @Assert\Valid
*
* @ORM\OneToOne(targetEntity="App\Entity\Properties\PropertyValues\PropertyValueEntry", cascade={"persist", "remove"})
*/
private $propertyValue;
但是PropertyValueEntry
与 没有反比关系CategoryProperty
。
单向的一对一是可以的,但它必须有一个@ORM\JoinColumn
指令来确保外来的标识符PropertyValueEntry
是持久的。否则,编辑表单将没有任何信息来知道PropertyValueEntry
它需要编辑哪个现有(或派生)。这就是为什么您的“properties_values__value_entry”表单字段被重置为PropertyValueEntry
在提交表单时创建的新实例(或派生实例)。
您尚未显示实体类的来源,Property
因此我无法检查您的实体关系中是否存在任何进一步的问题。
推荐阅读
- php - 使用 unset 从数组中删除创建值
- css - 在最新的 Create React App 中使用 LESS CSS
- html - 我的 scss 没有覆盖框架 css UIkit
- javascript - 如何在formgroup中设置数组的值
- elastic-stack - 错误:在 Chart.yaml 中找到,但在图表/目录中丢失:elasticsearch、kibana、filebeat、logstash
- webassembly - 在 WebAssembly 中如何评估“i32”类型的值?
- c# - ffmpeg 抛出 System.AccessViolationException
- kotlin - 如何在 Kotlin 中指定 Mockito 模拟 extraInterfaces(使用 nhaarman mockitokotlin2)
- javascript - Windows 脚本宿主在运行 JavaScript 时出错
- python - 尝试追加时Python不断返回空白列表?