0

doctrine2 には OneToMany 関連付けがあります: One Application <=> Many ApplicationCost

// Application.php

/**
 * @ORM\OneToMany(targetEntity="ApplicationCost", mappedBy="application", orphanRemoval=true)
 */
protected $costs;

// ApplicationCost.php

/**
 * @ORM\ManyToOne(targetEntity="Application", inversedBy="costs")
 * @ORM\JoinColumn(name="application_id", referencedColumnName="id")
 */
protected $application;

Application エンティティには、集計フィールドsumCostsがあります。

/**
 * @ORM\Column(type="decimal", scale=2)
 */
protected $sumCosts;

addCost と removeCost が呼び出されると更新されます。

// Application.php
public function addCost(ApplicationCost $cost)
{
    if (!$this->costs->contains($cost)) {
        $this->sumCosts += $cost->getBalance();
        $this->costs[] = $cost;
        $cost->setApplication($this);
    }

    return $this;
}

public function removeCost(ApplicationCost $cost)
{
    if ($this->costs->contains($cost)) {
        $this->sumCosts -= $cost->getBalance();
        $this->costs->removeElement($cost);
    }
}

User が既存の ApplicationCost を編集でき、その親 Application を変更できると仮定すると、この集計フィールドが最新であることを確認するにはどうすればよいですか?

私のアプローチは次のとおりです。

// ApplicationCost.php
public function setApplication(Application $application = null)
{
    if ($this->application !== null) {
        $this->application->removeCost($this);
    }

    if ($application !== null) {
        $application->addCost($this);
    }

    $this->application = $application;

    return $this;
}

それはいいですか?それとも、ここで大きな間違いを犯していて、sumCosts が同期していない可能性がありますか?

編集: Doctrine の Aggregate Fields cookbook を読み、バージョン管理を行いました (そしてロック機構を使用しています)。私の質問は並行性に関するものではありません。


編集:いくつかのテストを作成しました

public function testSumCosts()
{
    $app = new Application();

    $costA = new ApplicationCost();
    $costA->setBalance(150);

    $costB = new ApplicationCost();
    $costB->setBalance(100);

    $costC = new ApplicationCost();
    $costC->setBalance(50);

    $app->addCost($costA);
    $app->addCost($costB);
    $app->addCost($costC);

    $app->removeCost($costC);

    $this->assertEquals(250, $app->sumCosts(), 'Costs are summed correctly');
}

public function testCostsChangeApplication()
{
    $appA = new Application();
    $appB = new Application();

    $costA = new ApplicationCost();
    $costA->setBalance(100);

    $costB = new ApplicationCost();
    $costB->setBalance(50);

    $appA->addCost($costA);
    $appB->addCost($costB);

    $costA->setApplication($appB);
    $costB->setApplication(null);

    $this->assertEquals(0, $appA->sumCosts(), 'Costs are removed correctly');
    $this->assertEquals(100, $appB->sumCosts(), 'Costs are added correctly');
}

addEntryに追加$cost->setApplication($this);すると、両方のテストが緑色になります。何かを見逃したのではないかと思いますが。

4

1 に答える 1