2017-10-17 8 views
0

私はZend\Formデータから自動水和によって作成された複雑な/ネストされたオブジェクトを持っています。今度はそれをDoctrine 2で保存したいと思います。最善のケースは、persist(...)と、トップレベルの1つのflush(...)です。しかし、このようには動作しません。だから私は次の問題があります:エンティティが存在しない場合にのみ、関係の一方の端と他方の端を永続化する方法はありますか?

オブジェクトはUserOrderです。関係は1:nです(従って、1UsernOrdersです)。 Userは既に存在します。 UserJoe試みが複数のOrder(例えばその二次)を保存するときに、エラーが発生します。

新しいエンティティがに設定されていない関係 "... \注文番号のユーザーによって発見されましたエンティティのカスケード永続操作:... \ User @ 000000003ba4559d000000005be8d831この問題を解決するには:この未知のエンティティのEntityManager#persist()を明示的に呼び出すか、カスケードを設定すると、この関連付けが@ManyToOne(..、cascade = {"persist"})などのマッピングで保持されます。どのエンティティが問題を引き起こしているのかわからない場合は、 '... \ User #__ toString()'を実装してヒントを得てください。

オールライトは、(それがここでは意味がありませんが、とにかく、ちょうどそれを試して)、私はcascade={"persist"}を追加します。与えられたUserが存在しない場合は

class Order 
{ 
    ... 
    /** 
    * @var User 
    * 
    * @ORM\ManyToOne(targetEntity="User", cascade={"persist"}) 
    */ 
    protected $user; 
    ... 
} 

は、今では、動作します:OrderUserが作成されます。

しかし、エラーが発生し、Userが存在する場合:

の実行中に例外が発生したと '(ユーザー名、役割、作成、更新)VALUESユーザー。INSERT INTO(、、、????') params [ "myusernameと指定"、 "メンバー"、NULL、NULL]:

SQLSTATE [23000]:整合性制約違反:キーのための1062年の重複エントリー 'myusernameと指定' 'username_UNIQUE' どのように処理するか

サビいいえ、Userはまだ保存されていない場合にのみ保存されますか?

+0

あなたはsymfonyのフォーム(または唯一の検証コンポーネント)と、このオブジェクトを検証していますか? [UniqueEntity Constraints](https:// symfony)を見てください。 – Matteo

+0

ご意見ありがとうございますが、私はSymfonyではなく、 'Zend \ Form'を使用しています。検証のために、私はZendバリデーション関数を使用します。 – automatix

+0

Doctrineエラーに遭遇するたびに、「エンティティの操作をカスケードするように構成されていない「... \ Order#user」という関係で新しいエンティティが見つかりました」というメッセージが表示されます。小さい。 英語でエラーが表示されるのは、オーダーが保存されているが、関連付けられているユーザーが永続化されていないということです。つまり、割り当てられているユーザーは、データベースにあるエンティティとしてDoctrineに知られていません。コードを慎重にチェックして、実際に適切なユーザーを割り当てていること、および有効なユーザーであることを確認します。 – MEmerson

答えて

0

解決策は、参照するエンティティを保存する前にUserを保持することです。それはまだ存在しない場合は、それを作成する必要があります(persist編とflush編)最初:それは実際にこのケースでは意味がありませんので、

$user = $this->entityManager->getRepository(User::class)->findOneBy(
    ['username' => $dataObject->getUser()->getUsername()] 
); 
if (! $user) { 
    $this->entityManager->persist($dataObject->getUser()); 
    $this->entityManager->flush($dataObject->getUser()); 
    $user = $this->entityManager->getRepository(User::class)->findOneBy(
     ['username' => $dataObject->getUser()->getUsername()] 
    ); 
} 
$dataObject->setUser($user); 

$this->entityManager->persist($dataObject); 
$this->entityManager->flush(); 

そしてcascade={"persist"}は、使用すべきではありません。


EDIT

あるいはさらに簡単:

$user = $this->entityManager->getRepository(User::class)->findOneBy(
    ['username' => $dataObject->getUser()->getUsername()] 
); 
if ($user) { 
    $dataObject->setUser($user); 
} else { 
    $this->entityManager->persist($dataObject->getUser()); 
} 

$this->entityManager->persist($dataObject); 
$this->entityManager->flush(); 
関連する問題