1

XML ファイルを読み取り、MySQL データベースにデータを追加するインポート スクリプトがあります。xml ファイルには、Match-Data と関連するイベントが含まれています。

次のエンティティがあります

  • MatchList (ベストネームではありませんが、別のトピック)
  • マッチイベント

私の質問に関連する関係:

MatchList の内側 (裏側)

/**
 * @OneToMany(targetEntity="MatchEvent", mappedBy="match", orphanRemoval=true)
 */
private $events;

public function __construct($uId)
{
    $this->setId($uId);
    $this->events = new ArrayCollection();
}

MatchEvent 内 (所有側)

/**
 * @ManyToOne(targetEntity="MatchList", inversedBy="events")
 * @JoinColumn(name="match_id", referencedColumnName="id")
 */
private $match;

import-script 内には、一致ごとにループがあります。ループ内で、現在その試合に割り当てられているすべてのイベントを削除したいと考えています。そして、xml-file からこの一致に新しいイベントを追加したい直後。

イベントはデータベースから完全に削除する必要があります。試合への言及だけではありません。

簡単な例

XMLコンテンツ

Match1
  EventA
  EventC
  EventF

輸入前

Match1
  EventA
  EventB

インポート後、次のようになります

Match1
  EventA
  EventC
  EventF

したがって、イベントは

  • 削除 + 追加 (イベント A)。
  • 削除 (イベント B)
  • 追加 (EventF)

これは、XML にイベントの更新または修正が含まれているためです。したがって、信頼できる唯一の方法は、割り当てられたすべてのイベントを削除し、現在有効なイベントを最新の xml から追加することです。

私の問題は、すぐに追加することと組み合わせて、削除する部分です。独自の各タスクが機能しています。

さまざまな方法を試しましたが(教義のドキュメントも読んでいます)、うまくいきません。

私が試したいくつかのバリアントでスクリプトの関連部分をたどります(コメントアウト)(コード全体ではありません。「...」を見てください。これで問題/間違いを理解するのに十分だと思います)

try
{
    foreach($matches as $matchNode)
    {
        $match = new \MatchList($matchNode['uID']);
        ...
        $previousEvents = $match->getEvents();
        foreach($previousEvents as $previousEvent)
        {
            $match->removeEvent($previousEvent);
            //$previousEvent->setMatch(null);
            //$this->em->remove($previousEvent);
            //$this->em->persist($previousEvent);
        }

        foreach($teamData->Goal as $goal)
        {
            ...
            $event = new \MatchEvent($match);
            $event->setPlayer($player);
            $event->setType($goal['Type']);
            $event->setPeriod($goal['Period']);

            $this->em->persist($event);
            $match->addEvent($event);
        }
        ...
        $this->em->persist($match);
    }
    $this->em->flush();
}
catch(Exception $e){}

何を試しても、期待どおりに機能しませんでした。ときどきエラー (Missing cascade persist) が発生するか、エラーは発生しませんが、削除もされません。一度に 1 つのタスク (削除または追加) を実行した場合にのみ機能します。

逆側にのみ加えられた変更は教義によって保存されないことを知っているので、MatchEvent エンティティで remove を呼び出そうとしました。または、ArrayCollection 全体を設定解除し、orphanRemoval でエンティティも削除しようとしました。

私はしようとして立ち往生しています。誰かが私が間違っていることと正しい方法を理解するのを手伝ってくれることを願っています.

ありがとうございました

編集

私が試したすべてのバリエーションを追加すると役立つかもしれません。

バリアント 1)

直後にエンティティを追加しない場合: DB からイベントを削除する (GOOD)

直後にエンティティを追加: エラー: エンティティの永続操作をカスケードするように構成されていない関係 'MatchList#events' を通じて、新しいエンティティが見つかりました: MatchEvent@XYZ. (悪い)

$previousEvents = $match->getEvents();
foreach($previousEvents as $previousEvent)
{
    $this->em->remove($previousEvent);
}

バリアント 2)

直後にエンティティを追加しない場合: DB からイベントを削除する (GOOD)

直後にエンティティを追加: エラー: エンティティの永続操作をカスケードするように構成されていない関係 'MatchList#events' を通じて、新しいエンティティが見つかりました: MatchEvent@XYZ. (悪い)

$previousEvents = $match->getEvents();
foreach($previousEvents as $previousEvent)
{
     $previousEvent->setMatch(null);
     $this->em->remove($previousEvent);
     $this->em->detach($previousEvent);
}

バリアント 3)

直後にエンティティを追加しない場合: エラー: エンティティの永続操作をカスケードするように構成されていない関係 'MatchList#events' を通じて、新しいエンティティが見つかりました: MatchEvent@XYZ. (悪い)

直後にエンティティを追加: 削除さえ機能しなかったため、試行されませんでした。

$previousEvents = $match->getEvents();
foreach($previousEvents as $previousEvent)
{
     $previousEvent->setMatch(null);
     $this->em->detach($previousEvent);
}

これはうまくいくはずです、または私はこれを誤解しています: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/faq.html#i-call-clear-on-a-one-to-多くのコレクションですが、エンティティは削除されていません

バリアント 4)

直後にエンティティを追加しない場合: イベントが削除されず、すべてのイベントが match_id NULL で追加挿入されるため、DB のデータが 2 倍になります。(悪い)

直後にエンティティを追加: 削除さえ機能しなかったため、試行されませんでした。

$previousEvents = $match->getEvents();
foreach($previousEvents as $previousEvent)
{
     $previousEvent->setMatch(null);
     $this->em->detach($previousEvent);
     $this->em->persist($previousEvent);
}
4

1 に答える 1