2017-07-12 5 views
0

Symfony2.8のDoctrine ManyToManyエンティティリレーションに関する問題に直面しています。 私は多くの経験エンティティで構成することができるエンティティトリップを持っています。へのセッションでオブジェクトを入れて、Symfony2 ManyToMany関係も既存の関連エンティティを保存します

namespace MyBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 
use Knp\DoctrineBehaviors\Model as ORMBehaviors; 
use Symfony\Component\Validator\Constraints as Assert; 

/** 
* Experience 
* 
* @ORM\Table(name="experience") 
* @ORM\Entity(repositoryClass="MyBundle\Repository\ExperienceRepository") 
*/ 
class Experience 
{ 

    use ORMBehaviors\Translatable\Translatable; 
    use ORMBehaviors\Timestampable\Timestampable; 


    /** 
    * @var int 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @ORM\ManyToMany(targetEntity="MyBundle\Entity\Trip", mappedBy="experiences") 
    */ 
    private $trips; 

    // other fields 

    /** 
    * Constructor 
    */ 
    public function __construct() 
    { 
     $this->trips = new \Doctrine\Common\Collections\ArrayCollection(); 
    } 

    // other setters and getters 

    /** 
    * Add trip 
    * 
    * @param \MyBundle\Entity\Trip $trip 
    * 
    * @return Experience 
    */ 
    public function addTrip(\MyBundle\Entity\Trip $trip) 
    { 
     $this->trips[] = $trip; 

     return $this; 
    } 

    /** 
    * Remove trip 
    * 
    * @param \MyBundle\Entity\Trip $trip 
    */ 
    public function removeTrip(\MyBundle\Entity\Trip $trip) 
    { 
     $this->trips->removeElement($trip); 
    } 

    /** 
    * Get trips 
    * 
    * @return \Doctrine\Common\Collections\Collection 
    */ 
    public function getTrips() 
    { 
     return $this->trips; 
    } 
} 

はコントローラでは、ユーザーが新しいトリップを生成できます。

namespace MyBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 
use Knp\DoctrineBehaviors\Model as ORMBehaviors; 
use Symfony\Component\Validator\Constraints as Assert; 

/** 
* Trip 
* 
* @ORM\Table(name="trip") 
* @ORM\Entity(repositoryClass="MyBundle\Repository\TripRepository") 
* @ORM\HasLifecycleCallbacks 
*/ 
class Trip 
{ 
    use ORMBehaviors\Timestampable\Timestampable; 
    /** 
    * @var int 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id;  

    // other fields 

    /** 
    * @ORM\ManyToMany(targetEntity="MyBundle\Entity\Experience", inversedBy="trips") 
    * @ORM\JoinTable(name="experience_trip", 
    * joinColumns={ 
    *  @ORM\JoinColumn(name="trip_id", referencedColumnName="id") 
    * }, 
    * inverseJoinColumns={ 
    *  @ORM\JoinColumn(name="experience_id", referencedColumnName="id") 
    * } 
    *) 
    */ 
    private $experiences; 

    /** 
    * Constructor 
    */ 
    public function __construct() 
    { 
     $this->experiences = new \Doctrine\Common\Collections\ArrayCollection(); 
    } 

    // other setters and getters 

    /** 
    * Add experience 
    * 
    * @param \MyBundle\Entity\Experience $experience 
    * 
    * @return Trip 
    */ 
    public function addExperience(\MyBundle\Entity\Experience $experience) 
    { 
     $this->experiences[] = $experience; 

     return $this; 
    } 

    /** 
    * Remove experience 
    * 
    * @param \MyBundle\Entity\Experience $experience 
    */ 
    public function removeExperience(\MyBundle\Entity\Experience $experience) 
    { 
     $this->experiences->removeElement($experience); 
    } 

    /** 
    * Get experiences 
    * 
    * @return \Doctrine\Common\Collections\Collection 
    */ 
    public function getExperiences() 
    { 
     return $this->experiences; 
    } 

} 

私は経験実体を持っている他の側では:

は、ここに私の旅行の定義です実際の結社になるまでそれを思い出してください。

/** 
* @Route("/add-experience", name="add_experience") 
*/ 
public function addExperienceAction(Request $request) 
{ 
    $experienceId = $request->query->get('experience'); 
    $em = $this->getDoctrine()->getManager(); 

    $experience = $em->getRepository('MyBundle:Experience')->find($experienceId); 
    if (!$experience || !get_class($experience) == 'MyBundle:Experience') { 
     $response = array("message" => "Experience not found", "success" => false); 

     return new Response(json_encode($response)); 
    } 

    $session = $request->getSession(); 
    $trip = $session->get('trip'); 
    // This service only construct parameters 
    $searchParameters = $this->get('mybundle.search')->buildSearchParameters(); 
    if (!$trip) { 
     $trip = new Trip(); 
     $trip->setStartDate($searchParameters['startDate']); 
     $trip->setEndDate($searchParameters['endDate']); 
    } 

    $trip->addExperience($experience); 
    $trip->setClient($this->getUser()); /** user can be null */ 
    $em->persist($trip); 
    $em->flush(); 

    $session->set('trip', $trip); 

    $response = array("message" => "Experience n.$experienceId added correctly", "success" => true); 

    return new Response(json_encode($response)); 
} 

問題です。 最初の呼び出しでは、チャームのように動作し、experience_tripエントリを追加しても問題ありません。 2回目の呼び出しで は、異なるexperieceで、旅の永続化は、エラーを投げ、経験のエンティティのカスケードを探しています:

A new entity was found through the relationship 'MyBundle\Entity\Trip#experiences' that was not configured to cascade persist operations for entity: . To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}).

この理由は、生成、cascade={"persist"}を使用して、実際には、新しい経験エンティティを追加しようとしていますフィールドの一意性に起因する経験の重複に関するSQL例外。

同じモデルがSonata TripAdminクラスによって正しく管理されていて、TripThinkingで新しいエクスペリエンスを追加することなく、ExperienceTripエンティティを作成しないようにしています。 experience_tripテーブルでは、私は正しい関連を正しく見ることができます。

旅行を保存する理由は、2度目は新しい体験を挿入しようとしていますか?

ありがとう、私の英語のために申し訳ありません。

答えて

0

解決策は自分で見つけましたが、this commentにも感謝しています。

セッション内のエンティティは何らかの理由でデタッチされており、有効なエンティティではありません。だから、それをもう一度加えてみてください。

+0

特に:$ trip = $ session-> get( 'trip'); $ trip = $ em-> getRepository( 'MyBundle:Trip') - > find($ trip-> getId())のようなものが必要です。 – robdex

関連する問題