ManyToOne 原则仅更改连接实体的值而不是创建新实体
ManyToOne doctrine only changes the values of connected Entity instead of creating an new one
我有一个大(简单)问题。
我有一个用户实体,其地理位置 属性 作为多对一关系
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
/**
* User
*/
class User implements AdvancedUserInterface, \Serializable
{
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Location", cascade= {"persist"})
* @ORM\JoinColumn(name="location_id", referencedColumnName="id")
*/
private $geolocation;
我有一个像这样的位置实体:
/**
* Location
*
* @ORM\Table(name="location")
* @ORM\Entity(repositoryClass="AppBundle\Entity\Repository\LocationRepository")
*/
class Location
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @Assert\NotBlank()
* @ORM\Column(name="latitude", type="float", scale=12, precision=18)
*/
private $latitude;
/**
* @var string
*
* @Assert\NotBlank()
* @ORM\Column(name="longitude", type="float", scale=12, precision=18)
*/
private $longitude;
/**
* @var string
*
* @Assert\NotBlank()
* @ORM\Column(name="address", type="string", length=255)
*/
private $address;
现在的问题是,我想更改(更新)用户的位置。为此,我有一个 FormType:
$builder->add('geolocation', 'jquerygeolocation', array();
'jquerygeolocation' FormType 是使用
创建的 FormType
data_class' => 'AppBundle\Entity\Location'
但是当我想更改(更新)用户位置时,我遇到了一个大问题。如果该位置甚至不在数据库中,我想保留一个新位置,并且我想将现有位置与用户连接。但是学说只会改变连接位置的值。
例如:
之前:
之后:
可以看到,id是一样的。只有一个更新。没有我猜的逻辑。
有人可以帮我解决这个问题吗?
谢谢迈克尔。
有了这些关系,您通常会提供现有位置的选择列表和创建新位置的单独机制。通过在您的用户表单中嵌入位置实体表单,任何更新都将始终应用于已与用户关联的位置实体。
如果您希望它按照问题中的描述工作,您需要在您的控制器中(或者更好的是在控制器使用的业务逻辑服务中)编写一些自定义代码来处理它。
假设它是唯一标识位置的地址,那么您将需要这样的东西(在控制器中处理请求之后,以便您拥有包含提交数据的用户实例):
$em = $this->getDoctrine()->getManager();
$locationRepo = $em->getRepository('AppBundle:Location');
$location = $locationRepo->findOneByAddress($user->getGeolocation()->getAddress());
if (!$location)
{
$location = new Location();
$location->setLongitude($user->getGeolocation()->getLongitude());
$location->setLatitude($user->getGeolocation()->getLatitude());
$location->setAddress($user->getGeolocation()->getAddress());
$em->persist($location);
}
$user->setLocation($location);
$em->flush($user);
很好。这正是我所猜测的。但解决方案并不像这样容易。除了您的解决方案之外,您还必须防止更新旧位置实体。否则旧值与新位置相同。为此,我在实体中使用了生命周期回调:
Location.php
/**
* @ORM\PreUpdate
*/
public function preventUpdate(PreUpdateEventArgs $args)
{
$address = $args->getOldValue('address');
$latitude =$args->getOldValue('latitude');
$longitude = $args->getOldValue('longitude');
$locality = $args->getOldValue('locality');
$country = $args->getOldValue('country');
$locationArray = array(
'address' => $address,
'latitude' => $latitude,
'longitude' => $longitude,
'locality' => $locality,
'country' => $country
);
$this->update($locationArray);
}
在 Location.php 实体中使用以下函数:
public function update($location)
{
$data = $location;
$this->address = $data['address'] ?: null;
$this->latitude = $data['latitude'] ?: null;
$this->longitude = $data['longitude'] ?: null;
$this->locality = $data['locality'] ?: null;
$this->country = $data['country'] ?: null;
}
现在的问题是,我永远无法更新位置。
好的,我现在还不知道是否需要它。
但是,如果有没有这种消极方面的另一种解决方案,我将不胜感激。
我有一个大(简单)问题。
我有一个用户实体,其地理位置 属性 作为多对一关系
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
/**
* User
*/
class User implements AdvancedUserInterface, \Serializable
{
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Location", cascade= {"persist"})
* @ORM\JoinColumn(name="location_id", referencedColumnName="id")
*/
private $geolocation;
我有一个像这样的位置实体:
/**
* Location
*
* @ORM\Table(name="location")
* @ORM\Entity(repositoryClass="AppBundle\Entity\Repository\LocationRepository")
*/
class Location
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @Assert\NotBlank()
* @ORM\Column(name="latitude", type="float", scale=12, precision=18)
*/
private $latitude;
/**
* @var string
*
* @Assert\NotBlank()
* @ORM\Column(name="longitude", type="float", scale=12, precision=18)
*/
private $longitude;
/**
* @var string
*
* @Assert\NotBlank()
* @ORM\Column(name="address", type="string", length=255)
*/
private $address;
现在的问题是,我想更改(更新)用户的位置。为此,我有一个 FormType:
$builder->add('geolocation', 'jquerygeolocation', array();
'jquerygeolocation' FormType 是使用
创建的 FormTypedata_class' => 'AppBundle\Entity\Location'
但是当我想更改(更新)用户位置时,我遇到了一个大问题。如果该位置甚至不在数据库中,我想保留一个新位置,并且我想将现有位置与用户连接。但是学说只会改变连接位置的值。
例如:
之前:
之后:
可以看到,id是一样的。只有一个更新。没有我猜的逻辑。
有人可以帮我解决这个问题吗?
谢谢迈克尔。
有了这些关系,您通常会提供现有位置的选择列表和创建新位置的单独机制。通过在您的用户表单中嵌入位置实体表单,任何更新都将始终应用于已与用户关联的位置实体。
如果您希望它按照问题中的描述工作,您需要在您的控制器中(或者更好的是在控制器使用的业务逻辑服务中)编写一些自定义代码来处理它。
假设它是唯一标识位置的地址,那么您将需要这样的东西(在控制器中处理请求之后,以便您拥有包含提交数据的用户实例):
$em = $this->getDoctrine()->getManager();
$locationRepo = $em->getRepository('AppBundle:Location');
$location = $locationRepo->findOneByAddress($user->getGeolocation()->getAddress());
if (!$location)
{
$location = new Location();
$location->setLongitude($user->getGeolocation()->getLongitude());
$location->setLatitude($user->getGeolocation()->getLatitude());
$location->setAddress($user->getGeolocation()->getAddress());
$em->persist($location);
}
$user->setLocation($location);
$em->flush($user);
很好。这正是我所猜测的。但解决方案并不像这样容易。除了您的解决方案之外,您还必须防止更新旧位置实体。否则旧值与新位置相同。为此,我在实体中使用了生命周期回调:
Location.php
/**
* @ORM\PreUpdate
*/
public function preventUpdate(PreUpdateEventArgs $args)
{
$address = $args->getOldValue('address');
$latitude =$args->getOldValue('latitude');
$longitude = $args->getOldValue('longitude');
$locality = $args->getOldValue('locality');
$country = $args->getOldValue('country');
$locationArray = array(
'address' => $address,
'latitude' => $latitude,
'longitude' => $longitude,
'locality' => $locality,
'country' => $country
);
$this->update($locationArray);
}
在 Location.php 实体中使用以下函数:
public function update($location)
{
$data = $location;
$this->address = $data['address'] ?: null;
$this->latitude = $data['latitude'] ?: null;
$this->longitude = $data['longitude'] ?: null;
$this->locality = $data['locality'] ?: null;
$this->country = $data['country'] ?: null;
}
现在的问题是,我永远无法更新位置。 好的,我现在还不知道是否需要它。 但是,如果有没有这种消极方面的另一种解决方案,我将不胜感激。