我正在尝试导入一批记录(账单(,但我有一个多对一关系(与客户(。 如何填写该关系的数据库列?
我在实体中使用类似fromArray
的函数,在该实体中传递字段列表和一条记录的值(数据源是 CSV(。然后在该函数中,我只需将每个列值分配给相应的属性。但是,属性 Customer 是一个对象,因此我需要传入一个我没有的对象。
我考虑过将实体管理器注入我的实体,但这被认为是一种糟糕的做法,所以我有点卡住了。
我还尝试添加一个额外的属性customerId
希望它会强制写入值,但它似乎坚持关系值而不是属性值。
这是我的代码:
class Bill
/**
* @var string
*
* @ORMColumn(name="docId", type="string", length=25, nullable=false)
* @ORMId
*/
private $id;
/**
* @var float|null
*
* @ORMColumn(name="amount", type="float", precision=10, scale=0, nullable=true)
*/
private $amount;
/**
* @ORMManyToOne(targetEntity="AppEntityCustomer", inversedBy="bills")
* @ORMJoinColumn(name="customerId", referencedColumnName="customerId", nullable=false)
*/
private $customer;
public function getCustomer(): ?Customer
{
return $this->customer;
}
public function setCustomer( $customer): self
{
$this->customer = $customer;
return $this;
}
//this is where we import
public static function fromCSVRecord($header, $line)
{
$object = new self;
foreach($header as $key => $field){
try{
switch($field){
case 'customerId':
//get the customer here from EM but we don't have EM
$customer = $em->getRepository(Customer::class)->find($line[$key]);
$object->setCustomer($customer);
break;
default:
$object->$field = $line[$key];
break;
}
}catch(Exception $e){
dd($line[$key]);
}
}
return $object;
}
}
我希望有一种简单的方法可以使用ORM导入记录值,而无需将实体管理器注入实体类。
你的问题是你试图把这个责任交给错误的类。你需要实体内部的实体管理器的巨大代码气味,你正确地感知到,正在把你困在执行该操作的错误位置。
将其移动到存储库。无论如何,这是一个更合乎逻辑的位置来处理这个问题,并且您已经有可用的实体管理器。
class BillRepository extends ServiceEntityRepository
{
//..
public function addFromCSVRecord($header, $line) {
$em = $this->getEntityManager();
$bill = new Bill();
foreach ($header as $key => $field) {
try {
switch ($field) {
case 'customerId':
$customer = $em->getRepository(Customer::class)->find($line[$key]);
// alternatively, if you are certain of the incoming data and you do not want to hit the DB...
// $customer = $this->getEntityManager()->getReference(Customer:class, $line[$key]);
$bill->setCustomer($customer);
break;
default:
$bill->$field = $line[$key];
break;
}
} catch (Exception $e) { dd($line[$key]); }
}
// return $object;
$em->persist($bill);
$em->flush();
}
}
我保留了大部分逻辑,因为我在您的方法中找到了它,因为我不知道具体细节。虽然更改了实际持久化数据return
,但对addFromCsvRecord()
的单个调用将在数据库中创建并持久化您的新对象。
请注意,在我的回答中,我将向您展示如何使用EntityManager::getReference()
为客户生成对象引用。如果您可以信任输入文件,这将稍微快一些,因为您无需为该对象命中数据库。