我有两个实体,分别用于产品和翻译:
class ProductEntity
{
/**
* @Id
* @var string
* @Column(type="string", length=3)
*/
protected $code;
/**
* @OneToMany(targetEntity="ProductTranslationEntity", mappedBy="product")
*/
private $translations;
public function __construct()
{
$this->translations = new ArrayCollection();
}
/.../ getters and setters
public function addTranslation(ProductTranslationEntity $productTranslation)
{
$this->translations->add($productTranslation);
}
public function clearTranslations()
{
$this->translations->clear();
}
}
。
class ProductTranslationEntity
{
/**
* @ManyToOne(targetEntity="ProductEntity", inversedBy="translations")
* @JoinColumn(name="product_code", referencedColumnName="code", onDelete="CASCADE")
* @Id
*/
private $product;
/**
* @var string
* @Column(type="string", name="language_code", length=5)
* @Id
*/
protected $languageCode;
/**
* @var string
* @Column(type="string", name="product_name", length=128)
*/
protected $productName;
/.../ getters and setters
}
我喜欢用这样的数组将所有翻译替换为新的翻译:
['en' => ['name' => 'name_en'], 'de' => ['name' => 'name_de']];
因为在此数组中,我设置了所有受支持的语言,所以我看到的最有效的方法是删除所有现有翻译并放入新的翻译:
$product // Existing product entity
$product->clearTranslations();
$this->entityManager->flush($product);
foreach ($translations as $code => $translation) {
$t = new ProductTranslationEntity();
$t->setProduct($product);
$t->setLanguageCode($code);
$t->setProductName($translation['name']);
$this->entityManager->persist($t);
$product->addTranslation($t);
}
$this->entityManager->flush($product);
此解决方案不起作用,因为在第一个$this->entityManager->flush($product);
之后,数据库中仍然存在翻译,因此我得到有关重复项的错误。
我的解决方案做错了什么?也许还有另一种方法可以解决此类问题?
答案 0 :(得分:1)
这可能有点过载,但仍然不使用对数据库的额外请求:
$current_translations = $product->getTranslations();
foreach ($translations as $code => $translation) {
$translation_found = false;
foreach ($current_translations as $current_translation) {
if ($current_translation->getLanguageCode() === $code) {
// you've found the translation - replace value
$current_translation->setProductName($translation['name']);
$translation_found = true;
break;
}
}
if (!$translation_found) {
// translation with such code not found - add a new one
$t = new ProductTranslationEntity();
$t->setProduct($product);
$t->setLanguageCode($code);
$t->setProductName($translation['name']);
$this->entityManager->persist($t);
$product->addTranslation($t);
}
}
$this->entityManager->persist($product);
答案 1 :(得分:1)
使用orphanRemoval = true:
/**
* @OneToMany(targetEntity="ProductTranslationEntity", mappedBy="product", orphanRemoval=true)
*/
private $translations;
答案 2 :(得分:0)
如学说文档所述:
仅对关联的反面所做的更改将被忽略。 确保更新双向关联的两端(或在 从教义的角度来看,至少是拥有方。
因此,要正确清除产品的翻译,您应该将Product实体内部的clearTranslations()函数更改为:
public function clearTranslations()
{
foreach ($this->translations as $translation) {
$translation->setProduct(null);
}
$this->translations->clear();
}
,以便您还可以在删除前更新关联的拥有方。