学说中的外键(Symfony)。如何将新的 child 绑定到现有的 parent?
Foreign Key in Doctrine (Symfony). How do I bind a new child to an already existing parent?
有一个地区和城市数据库。 regions 和 cities 表之间的关系是 one-to-many。下面是我向数据库添加新城市的代码。它给出了一个错误:
https://i.stack.imgur.com/LZPjz.png
我在网上只找到了一个解决方案——不仅在城市上,而且在地区上都使用“$entity_manager-> persist()”。但是在这种情况下,Doctrine 复制了数据库中已经存在的区域。
Symfony 文档确实涵盖了添加新的 child 和新的 parent,但我不需要。
在控制器中:
/**
* @Route("/admin/insert/city", name="city")
*/
public function city(Request $request)
{
// get list of regions
$regions_in_database = $this->getDoctrine()->getRepository(Region::class)->findAll();
// add the regions into an array
$regions = [];
foreach ($regions_in_database as $region) {
$regions[(string)$region->getName()] = clone $region;
}
// Create Form
$city = new City();
$insert_city = $this->createForm(InsertCityType::class, $city, [
'regions_array' => $regions,
]);
// Checking for the existence of regions
if (!$regions_in_database) {
$insert_city->addError(new FormError("Отсутствуют регионы!
Пожалуйста, перейдите по ссылке /insert/region и добавьте соответствующий регион"));
}
// Отправка формы
$insert_city->handleRequest($request);
if ($insert_city->isSubmitted() && $insert_city->isValid()) {
// Check if there is already such a city in the database
$repository = $this->getDoctrine()->getRepository(City::class);
$city_in_database = $repository->findOneBy(
[
'name' => $city->getName(),
'region' => $city->getRegion(),
]
);
// If the city is in the database, throw an error
if ($city_in_database) {
$insert_city->addError(new FormError('Такой город уже существует!'));
}
else {
$entity_manager = $this->getDoctrine()->getManager();
$entity_manager->persist($city);
$entity_manager->flush();
$city = new City();
$insert_city = $this->createForm(InsertCityType::class, $city, [
'regions_array' => $regions,
]);
}
}
return $this->render('admin/insert/city/city.html.twig', [
'insert_city' => $insert_city->createView(),
]);
}
表格Class:
class InsertCityType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('region', ChoiceType::class, [
'choices' => $options['regions_array'],
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Cities::class,
'regions_array' => null,
]);
$resolver->setAllowedTypes('regions_array', 'array');
}
}
形式:
https://i.stack.imgur.com/1hGv0.png
地区Class:
/**
* Regions
*
* @ORM\Table(name="regions")
* @ORM\Entity
*/
class Regions
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255, nullable=false)
*/
private $name;
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
}
城市Class:
/**
* Cities
*
* @ORM\Table(name="cities", indexes={@ORM\Index(name="region", columns={"region"})})
* @ORM\Entity
*/
class Cities
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255, nullable=false)
*/
private $name;
/**
* @var \Regions
*
* @ORM\ManyToOne(targetEntity="Regions", inversedBy="cities")
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="region", referencedColumnName="id")
* })
*/
private $region;
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getRegion(): ?Regions
{
return $this->region;
}
public function setRegion(?Regions $region): self
{
$this->region = $region;
return $this;
}
}
按照以下步骤操作:创建一个新城市,获取正确的区域,然后将新城市添加到该区域并将其保存到您的数据库中。
为此,在您的区域实体中添加城市列表,如下所示:
/**
* @var ArrayCollection
*
* @ORM\OneToMany(targetEntity="City", mappedBy="region", cascade={"persist"})
*/
private $cities; // This attribut will not appear in your database
public function __construct() {
$this->cities = new ArrayCollection();
}
使用此命令生成资产和 getters php bin/console make:entity --regenerate
。
现在,您可以在区域中添加城市:
$theRegion = fetchMyRegion(); // Fetch the region that you want
$theRegion->addCity($myCity); // Don't forget 'cities' attribut is a ArrayCollection
$entity_manager->persist($theRegion); // City object saves automatically in your database
$entity_manager->flush(); // The new city is now created and linked to the region
有一个地区和城市数据库。 regions 和 cities 表之间的关系是 one-to-many。下面是我向数据库添加新城市的代码。它给出了一个错误:
https://i.stack.imgur.com/LZPjz.png
我在网上只找到了一个解决方案——不仅在城市上,而且在地区上都使用“$entity_manager-> persist()”。但是在这种情况下,Doctrine 复制了数据库中已经存在的区域。
Symfony 文档确实涵盖了添加新的 child 和新的 parent,但我不需要。
在控制器中:
/**
* @Route("/admin/insert/city", name="city")
*/
public function city(Request $request)
{
// get list of regions
$regions_in_database = $this->getDoctrine()->getRepository(Region::class)->findAll();
// add the regions into an array
$regions = [];
foreach ($regions_in_database as $region) {
$regions[(string)$region->getName()] = clone $region;
}
// Create Form
$city = new City();
$insert_city = $this->createForm(InsertCityType::class, $city, [
'regions_array' => $regions,
]);
// Checking for the existence of regions
if (!$regions_in_database) {
$insert_city->addError(new FormError("Отсутствуют регионы!
Пожалуйста, перейдите по ссылке /insert/region и добавьте соответствующий регион"));
}
// Отправка формы
$insert_city->handleRequest($request);
if ($insert_city->isSubmitted() && $insert_city->isValid()) {
// Check if there is already such a city in the database
$repository = $this->getDoctrine()->getRepository(City::class);
$city_in_database = $repository->findOneBy(
[
'name' => $city->getName(),
'region' => $city->getRegion(),
]
);
// If the city is in the database, throw an error
if ($city_in_database) {
$insert_city->addError(new FormError('Такой город уже существует!'));
}
else {
$entity_manager = $this->getDoctrine()->getManager();
$entity_manager->persist($city);
$entity_manager->flush();
$city = new City();
$insert_city = $this->createForm(InsertCityType::class, $city, [
'regions_array' => $regions,
]);
}
}
return $this->render('admin/insert/city/city.html.twig', [
'insert_city' => $insert_city->createView(),
]);
}
表格Class:
class InsertCityType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('region', ChoiceType::class, [
'choices' => $options['regions_array'],
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Cities::class,
'regions_array' => null,
]);
$resolver->setAllowedTypes('regions_array', 'array');
}
}
形式:
https://i.stack.imgur.com/1hGv0.png
地区Class:
/**
* Regions
*
* @ORM\Table(name="regions")
* @ORM\Entity
*/
class Regions
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255, nullable=false)
*/
private $name;
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
}
城市Class:
/**
* Cities
*
* @ORM\Table(name="cities", indexes={@ORM\Index(name="region", columns={"region"})})
* @ORM\Entity
*/
class Cities
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255, nullable=false)
*/
private $name;
/**
* @var \Regions
*
* @ORM\ManyToOne(targetEntity="Regions", inversedBy="cities")
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="region", referencedColumnName="id")
* })
*/
private $region;
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getRegion(): ?Regions
{
return $this->region;
}
public function setRegion(?Regions $region): self
{
$this->region = $region;
return $this;
}
}
按照以下步骤操作:创建一个新城市,获取正确的区域,然后将新城市添加到该区域并将其保存到您的数据库中。
为此,在您的区域实体中添加城市列表,如下所示:
/**
* @var ArrayCollection
*
* @ORM\OneToMany(targetEntity="City", mappedBy="region", cascade={"persist"})
*/
private $cities; // This attribut will not appear in your database
public function __construct() {
$this->cities = new ArrayCollection();
}
使用此命令生成资产和 getters php bin/console make:entity --regenerate
。
现在,您可以在区域中添加城市:
$theRegion = fetchMyRegion(); // Fetch the region that you want
$theRegion->addCity($myCity); // Don't forget 'cities' attribut is a ArrayCollection
$entity_manager->persist($theRegion); // City object saves automatically in your database
$entity_manager->flush(); // The new city is now created and linked to the region