Symfony - ArrayCollection - 更新或创建
Symfony - ArrayCollection - Update or Create
- Symfony 4.3
- 目标:导入 CSV 列表 employees/company 并保存到数据库中。
我有实体公司:
<?php
// src/Entity/Company.php
class Company
{
/**
* @ORM\OneToMany(targetEntity="App\Entity\Employee", mappedBy="company")
*/
private $employees;
public function __construct()
{
$this->employees = new ArrayCollection();
}
public function getEmployees()
{
return $this->employees;
}
和员工实体:
<?php
// src/Entity/Employee.php
class Employee
{
/**
* @ORM\ManyToOne(targetEntity="App\Entity\Company", inversedBy="employees")
*/
private $company;
public function getCompany()
{
return $this->company;
}
public function setCompany(?Company $company)
{
$this->company = $company;
return $this;
}
下面是我对正在导入的 CSV 的每一行的循环:
<?php
// $csv = array made from the CSV file
// e.g. $csv[0]['employee_name'] = "John Doe"
// e.g. $csv[0]['employee_mail'] = "john.doe@bmw.com"
// e.g. $csv[0]['employee_company_name'] = "BMW"
// e.g. $csv[0]['employee_company_id'] = 77
foreach($csv as $key => $value)
{
if($company = $this->em->getRepository(Company::class)->find($value['employee_company_id']))
{
// if the employee doest not exist, create it
// IN MY TESTS, HERE IS MY PROBLEM
// DON'T KNOW HOW TO LOOP INSIDE THE EMPLOYEES LIST USING the MAIL
if ($company->getEmployees()->contains($value['employee_mail']))
{
// This employee for this company exists, let's update it
}
else
{
// This employee for this company does not exist, let's create it
}
}
else
{
// Create the company
}
我不知道如何在公司员工列表中循环,以决定是否必须编辑(员工已经存在)或创建新员工。也许我不应该使用 ArrayCollection::contains 方法?
天真的方法是只查看员工存储库。
$employee = $em->getRepository(Employee::class)->findOneBy([
'company' => $company,
'email' => $value['employee_mail'],
]);
if($employee) {
// exists -> update
} else {
// create
}
根据公司员工比例,循环浏览公司员工可能更好:
$employee = null;
foreach($company->getEmployees() as $_employee) {
if($_employee->getEmail() == $value['employee_mail']) {
$employee = $_employee;
break; // short circuit the loop
}
}
// rest is the same
如果您的 csv and/or 数据库中有 非常多的员工,可能 会更好一起跳过 ORM 并直接进入数据库。否则,如果你有一个巨大的数据库/csv,你可能想偶尔清除实体管理器。
您应该首先存储您的员工列表:
$employees = $company->getEmployees()
然后你在 $employees 中循环:
foreach($employees as $employee ) //supposedly you have 'email' property
{
if ($employee->getEmail() == $value['employee_mail'])
{
//your code here
}
}
别忘了添加:
* @ORM\OneToMany(targetEntity="App\Entity\Employee", mappedBy="company", fetch="EAGER")
更新:
$qb = $repository->createQueryBuilder('a')
->where(':employee_mail OF a.emplyee_email')
->setParameter('employee_mail ', $value['employee_mail']);
->andWhere(':comapanyId MEMBER OF a.company_id');
->setParameter('comapanyId ', $value['employee_company_id']);
->getQuery()
->execute()
如果公司中不存在该员工,这将 return 为 null,您应该根据需要在代码中实现它。
因为Employees
是一个Doctrine ArrayCollection,你可以在它上面使用exists
方法。此方法接受一个闭包作为参数,它循环遍历集合中的所有元素,并在条件匹配时 returns true
。
if ($company->getEmployees()->exists(function ($key, Employee $employee) use ($value) {
return $employee->getEmail() === $value['employee_mail'];
})) {
// Employee exists, update
} else {
// Employee does not exist
}
或者,如果您想立即 create/update 记录,您可以执行以下操作。此 returns 如果 Employee
存在,如果不存在则创建一个新的 Employee
对象
$employee = $company
->getEmployees()
->filter(function (Employee $employee) use ($value) {
return $employee->getEmail() === $value['employee_mail'];
})
->first() ?? new Employee();
- Symfony 4.3
- 目标:导入 CSV 列表 employees/company 并保存到数据库中。
我有实体公司:
<?php
// src/Entity/Company.php
class Company
{
/**
* @ORM\OneToMany(targetEntity="App\Entity\Employee", mappedBy="company")
*/
private $employees;
public function __construct()
{
$this->employees = new ArrayCollection();
}
public function getEmployees()
{
return $this->employees;
}
和员工实体:
<?php
// src/Entity/Employee.php
class Employee
{
/**
* @ORM\ManyToOne(targetEntity="App\Entity\Company", inversedBy="employees")
*/
private $company;
public function getCompany()
{
return $this->company;
}
public function setCompany(?Company $company)
{
$this->company = $company;
return $this;
}
下面是我对正在导入的 CSV 的每一行的循环:
<?php
// $csv = array made from the CSV file
// e.g. $csv[0]['employee_name'] = "John Doe"
// e.g. $csv[0]['employee_mail'] = "john.doe@bmw.com"
// e.g. $csv[0]['employee_company_name'] = "BMW"
// e.g. $csv[0]['employee_company_id'] = 77
foreach($csv as $key => $value)
{
if($company = $this->em->getRepository(Company::class)->find($value['employee_company_id']))
{
// if the employee doest not exist, create it
// IN MY TESTS, HERE IS MY PROBLEM
// DON'T KNOW HOW TO LOOP INSIDE THE EMPLOYEES LIST USING the MAIL
if ($company->getEmployees()->contains($value['employee_mail']))
{
// This employee for this company exists, let's update it
}
else
{
// This employee for this company does not exist, let's create it
}
}
else
{
// Create the company
}
我不知道如何在公司员工列表中循环,以决定是否必须编辑(员工已经存在)或创建新员工。也许我不应该使用 ArrayCollection::contains 方法?
天真的方法是只查看员工存储库。
$employee = $em->getRepository(Employee::class)->findOneBy([
'company' => $company,
'email' => $value['employee_mail'],
]);
if($employee) {
// exists -> update
} else {
// create
}
根据公司员工比例,循环浏览公司员工可能更好:
$employee = null;
foreach($company->getEmployees() as $_employee) {
if($_employee->getEmail() == $value['employee_mail']) {
$employee = $_employee;
break; // short circuit the loop
}
}
// rest is the same
如果您的 csv and/or 数据库中有 非常多的员工,可能 会更好一起跳过 ORM 并直接进入数据库。否则,如果你有一个巨大的数据库/csv,你可能想偶尔清除实体管理器。
您应该首先存储您的员工列表:
$employees = $company->getEmployees()
然后你在 $employees 中循环:
foreach($employees as $employee ) //supposedly you have 'email' property
{
if ($employee->getEmail() == $value['employee_mail'])
{
//your code here
}
}
别忘了添加:
* @ORM\OneToMany(targetEntity="App\Entity\Employee", mappedBy="company", fetch="EAGER")
更新:
$qb = $repository->createQueryBuilder('a')
->where(':employee_mail OF a.emplyee_email')
->setParameter('employee_mail ', $value['employee_mail']);
->andWhere(':comapanyId MEMBER OF a.company_id');
->setParameter('comapanyId ', $value['employee_company_id']);
->getQuery()
->execute()
如果公司中不存在该员工,这将 return 为 null,您应该根据需要在代码中实现它。
因为Employees
是一个Doctrine ArrayCollection,你可以在它上面使用exists
方法。此方法接受一个闭包作为参数,它循环遍历集合中的所有元素,并在条件匹配时 returns true
。
if ($company->getEmployees()->exists(function ($key, Employee $employee) use ($value) {
return $employee->getEmail() === $value['employee_mail'];
})) {
// Employee exists, update
} else {
// Employee does not exist
}
或者,如果您想立即 create/update 记录,您可以执行以下操作。此 returns 如果 Employee
存在,如果不存在则创建一个新的 Employee
对象
$employee = $company
->getEmployees()
->filter(function (Employee $employee) use ($value) {
return $employee->getEmail() === $value['employee_mail'];
})
->first() ?? new Employee();