2015-07-01 64 views
0

我有一個很大(簡單)的問題。ManyToOne原則只改變連接實體的值而不是創建新實體

我有一個地理位置屬性作爲一個多對一關係

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' 

但是,當我想改變(更新)用戶位置我有一個很大的問題。如果該位置甚至不在數據庫中,並且我想要將現有位置與用戶連接,我想要保留一個新位置。但相反,學說只會改變連接位置的值。

例如:

前: Bevor update

後:After update

正如你所看到的,ID是一樣的。只有一個更新。我猜的邏輯沒有什麼。

有人可以幫助我這個。

謝謝邁克爾。

回答

1

通過這些關係,您通常會提供現有位置的選擇列表和單獨的機制來創建新位置。將位置實體表單嵌入到用戶表單中時,任何更新都將始終應用於已與用戶關聯的位置實體。

如果你想要這個工作,因爲在這個問題說明你需要編寫一些自定義代碼在你的控制器(或控制器使用的業務邏輯的服務更好)來處理它。

假設它是唯一標識一個位置,然後(讓你有一個包含提交的數據的用戶實例處理控制器請求後),你需要像這樣的地址:

$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); 
0

非常好。這正是我猜到的。但解決方案並非如此簡單。除了您的解決方案之外,您還必須防止舊位置實體的更新。否則,舊值與新位置相同。要做到這一點,我用了一個生命週期回調的實體:

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); 
} 

與裏面的位置下面的函數。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; 
} 

現在的問題是,我永遠無法更新位置。 好吧,我現在還沒有,如果我需要它。 但是,如果沒有這個消極方面,還有其他解決方案,我將不勝感激。

+1

您應該可以在「舊」位置上調用$ em-> detach($ location)以防止它被更新。 – redbirdo

+0

酷!謝謝!那很棒! – Slowwie

相關問題