9

Symfony2 と Doctrine を使用しています

セッションにシリアル化/非シリアル化され、複数の画面で使用される教義エンティティがあります。このエンティティには、多数の 1 対多の関連付けがあります。

ドクトリン エンティティには、たとえば次の 1 対多があります。

class Article {

...

    /**
     * @ORM\OneToMany(targetEntity="image", mappedBy="article", cascade=  {"merge","detach","persist"})
     */
    protected $images;

    public function __construct()
    {
        $this->images = new ArrayCollection();
    }

    .....
}

article エンティティは、次のように保存および取得されます。

    public function saveArticle($article)
    {
        $articleSerialized = serialize($article);
        $this->session->set('currentArticle',$articleSerialized);
    }

    public function getArticle()
    {
        $articleSerialized = $this->session->get('currentArticle');
        $article = unserialize($articleSerialized);
        $article = $this->em->merge($article);

        return $article;
    }

エンティティをセッションとの間で何度でも保存およびロードし、それをエンティティ マネージャにマージして保存することができます。これは、新しいエンティティの場合のみです。

ただし、データベースからエンティティをロードしてセッションに保存すると、問題が発生します。

他の投稿から、保存されたエンティティをシリアル化解除した後、 $em->merge($entity); を実行する必要があることを知っています。

エンティティをマージし、新しいサブエンティティ (1 対多) を追加して保存できます。

$article = $this->getArticle(); //Declared above, gets article from session

$image = new Image();
$image->setFilename('image.jpeg');
$article->addImage($image);

$this->saveArticle($article); //Declared above, returns the article to session

ただし、最初のマージと画像の追加の後、サブエンティティを追加できません。2 番目の画像を追加しようとすると、次のエラーが返されます。

A managed+dirty entity <<namespace of entity>>
image@0000000067078d7400000000221d7e02 can not 
be scheduled for insertion.

要約すると、エンティティにいくつでも変更を加えてセッションに保存できますが、サブエンティティを追加するときに $em->merge を複数回実行すると、新しいサブエンティティがダーティとしてマークされます。

エンティティがダーティとマークされる理由を知っている人はいますか? エンティティ自体をリセットする必要がありますか? もしそうなら、どうすればそれを行うことができますか?

4

1 に答える 1

11

とった。

将来この問題に遭遇する可能性のある人のために:

永続化されていないサブエンティティを持つエンティティをマージすることはできません。それらはダーティとしてマークされます。

IE

2 つの画像が既に DB に保存されている記事があるかもしれません。

ARTICLE (ID 1) -> IMAGE (ID 1)
               -> IMAGE (ID 2)

記事をセッションにシリアル化して保存する場合は、シリアル化を解除してマージします。大丈夫です。

新しいイメージを追加してセッションにシリアル化すると、問題が発生します。これは、永続化されていないエンティティをマージできないためです。

ARTICLE (ID 1) -> IMAGE (ID 1)
               -> IMAGE (ID 2)
               -> IMAGE (NOT YET PERSISTED)

私がしなければならなかったのは:

記事のシリアル化を解除した後、永続化されていない画像を削除し、それらを一時配列に格納します (ID を確認します)。次に、記事をマージし、永続化されていない画像を再度追加します。

        $article = unserialize($this->session->get('currentArticle'));

        $tempImageList = array();

        foreach($article->getImages() as $image)
        {
            if(!$image->getId()) //If image is new, move it to a temporary array
            {
                $tempImageList[] = $image;
                $article->removeImage($image);
            }
        }

        $plug = $this->em->merge($article); //It is now safe to merge the entity

        foreach($tempImageList as $image)
        {
            $article->addImage($image); //Add the image back into the newly merged plug
        }

        return $article;                        

その後、必要に応じてさらに画像を追加し、最終的に記事を DB に永続化するまでこのプロセスを繰り返します。

これは、複数ページの作成プロセスを実行したり、AJAX を介して画像を追加したりする必要がある場合に知っておくと便利です。

于 2012-12-05T23:18:00.497 に答える