我有描述产品的实体。每个产品可能都有翻译(ProductTranslation
实体)。产品具有主键:code
,在翻译实体(product_code
)中用作外键。在翻译实体中,product_code
和language_code
的组合用作键。
这些是我的实体:
<?php
declare(strict_types=1);
namespace Entity;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Class Product
* @package Entity
* @Entity @Table(name="product")
*/
class Product
{
/**
* @Id
* @var string
* @Column(type="string", length=3)
*/
protected $code;
/**
* @OneToMany(targetEntity="ProductTranslation", mappedBy="product", cascade={"persist", "remove"})
*/
private $translations;
public function __construct()
{
$this->translations = new ArrayCollection();
}
public function getCode(): string
{
return $this->code;
}
public function setCode(string $code): void
{
$this->code = $code;
}
public function getTranslations()
{
return $this->translations;
}
public function addTranslation(ProductTranslation $productTranslation)
{
$this->translations->add($productTranslation);
}
public function setTranslations($translations): void
{
$this->translations = $translations;
}
public function clearTranslations()
{
$this->translations->clear();
}
}
和:
<?php
declare(strict_types=1);
namespace Entity;
/**
* Class ProductTranslation
* @package Entity
* @Entity @Table(name="product_translation")
*/
class ProductTranslation
{
/**
* @ManyToOne(targetEntity="Product", inversedBy="translations", cascade={"persist", "remove"})
* @JoinColumn(name="product_code", referencedColumnName="code")
* @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;
public function getLanguageCode(): string
{
return $this->languageCode;
}
public function setLanguageCode(string $languageCode): void
{
$this->languageCode = $languageCode;
}
public function getProductName(): string
{
return $this->productName;
}
public function setProductName(string $product): void
{
$this->productName = $product;
}
public function getProduct(): Product
{
return $this->product;
}
public function setProduct($product): void
{
$this->product = $product;
}
}
我喜欢编辑产品,包括产品代码,这是我的代码。
$newTranslations = ['en' => 'name_en', 'de' => 'name_de', 'fr' => 'name_fr'];
$newData = ['originalCode' => 'pr1', 'code' => 'pr2', 'translations' => $newTranslations];
/** @var Product $product */
$product = $entityManager->getRepository(Product::class)->findOneBy(['code' => $newData['originalCode']]);
$product->setCode($newData['code']);
$currentTranslations = $product->getTranslations();
// for update existing translation or create new if doesn't exist
foreach ($newData['translations'] as $code => $translation) {
$found = false;
/** @var ProductTranslation $currentTranslation */
foreach ($currentTranslations as $currentTranslation) {
if ($currentTranslation->getLanguageCode() == $code) {
$currentTranslation->setProductName($translation);
$found = true;
break;
}
if (!$found) {
$newTranslation = new ProductTranslation();
$newTranslation->setProduct($product);
$newTranslation->setLanguageCode($code);
$this->entityManager->persist($newTranslation);
$product->addTranslation($newTranslation);
}
}
$entityManager->flush($product);
运行此代码时,我得到:
Fatal error: Uncaught Doctrine\DBAL\Driver\Mysqli\MysqliException: Cannot delete or update a parent row: a foreign key constraint fails (`doctrine`.`product_translation`, CONSTRAINT `FK_1846DB70FAFD1239` FOREIGN KEY (`product_code`) REFERENCES `product` (`code`)) in /var/www/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php on line 69
我一直在尝试解决它的许多方法(使用cascase进行实验,在编辑翻译时将产品设置为循环等),但是没有任何效果。我的做法有什么不妥?