#symfony #doctrine
#symfony #доктрина
Вопрос:
У меня есть следующие ассоциации с Doctrine:
Charge:
id
amount
adjustmentItems
Adjustment
id
date
adjustmentItems
AdjustmentItem
id
adjustment
charge
amount
Есть обвинения, и есть корректировки. Каждая корректировка состоит из элементов adjustmentItems, которые являются корректировками одного или нескольких сборов.
При добавлении новой корректировки я добавляю корректировки и связанные с ними элементы с помощью десериализации. Т. е.:
$adjustment =
["date" => "2020-12-14",
"items" => [
["charge" => 84, "amount" => 600],
["charge" => 85, "amount" => 200],
]
];
Все работает хорошо, за исключением того, что я проверяю обвинения, используя Assert /Valid для AdjustmentItem::charge .
При проверке начисления я проверяю, чтобы убедиться, что сумма всех корректировок не превышает сумму начисления.
Однако Charge::getAdjustmentItems() не показывает только что созданные adjustmentItems (хотя adjustmentItem показывает, что он заряжается, и при сохранении все работает, как ожидалось).
$adjustment->getAdjustmentItems()->first()->getCharge()->getAdjustmentItems()->toArray()
является:
[]
Как я могу получить плату за «просмотр» элементов из десериализации перед сохранением для проверки?
Источник:
<?php
namespace AppEntityTestFin;
use AppRepositoryTestFinChargeRepository;
use DoctrineCommonCollectionsArrayCollection;
use DoctrineCommonCollectionsCollection;
use DoctrineORMMapping as ORM;
use SymfonyComponentValidatorConstraints as Assert;
use SymfonyComponentValidatorContextExecutionContextInterface;
/**
* @ORMEntity(repositoryClass=ChargeRepository::class)
* @ORMTable(name="`test_financials_charge`")
*/
class Charge
{
/**
* @ORMId()
* @ORMGeneratedValue()
* @ORMColumn(type="integer")
*/
private $id;
/**
* @ORMColumn(type="integer")
*/
private $amount;
/**
* @ORMOneToMany(targetEntity=AdjustmentItem::class, mappedBy="charge")
*/
private $adjustmentItems;
public function __construct()
{
$this->adjustmentItems = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getAmount(): ?int
{
return $this->amount;
}
public function setAmount(int $amount): self
{
$this->amount = $amount;
return $this;
}
/**
* @return Collection|AdjustmentItem[]
*/
public function getAdjustmentItems(): Collection
{
return $this->adjustmentItems;
}
public function addAdjustmentItem(AdjustmentItem $adjustmentItem): self
{
if (!$this->adjustmentItems->contains($adjustmentItem)) {
$this->adjustmentItems[] = $adjustmentItem;
$adjustmentItem->setCharge($this);
}
return $this;
}
public function removeAdjustmentItem(AdjustmentItem $adjustmentItem): self
{
if ($this->adjustmentItems->contains($adjustmentItem)) {
$this->adjustmentItems->removeElement($adjustmentItem);
// set the owning side to null (unless already changed)
if ($adjustmentItem->getCharge() === $this) {
$adjustmentItem->setCharge(null);
}
}
return $this;
}
/**
* @AssertCallback
*/
public function validateBalance(ExecutionContextInterface $context, $payload)
{
dd(count($this->adjustmentItems->toArray()));
if (1) {
$context->buildViolation('Charge balance (after adjustments) must be greater or equal to $0.')
->atPath('invoice')
->addViolation();
}
}
}
<?php
namespace AppEntityTestFin;
use AppRepositoryTestFinAdjustmentRepository;
use DoctrineCommonCollectionsArrayCollection;
use DoctrineCommonCollectionsCollection;
use DoctrineORMMapping as ORM;
use SymfonyComponentValidatorConstraints as Assert;
/**
* @ORMEntity(repositoryClass=AdjustmentRepository::class)
* @ORMTable(name="`test_financials_adjustment`")
*/
class Adjustment
{
/**
* @ORMId()
* @ORMGeneratedValue()
* @ORMColumn(type="integer")
*/
private $id;
/**
* @ORMColumn(type="string", length=255, nullable=true)
*/
private $note;
/**
* @ORMOneToMany(targetEntity=AdjustmentItem::class, mappedBy="adjustment", orphanRemoval=true)
* @AssertValid
*/
private $adjustmentItems;
public function __construct()
{
$this->adjustmentItems = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getNote(): ?string
{
return $this->note;
}
public function setNote(?string $note): self
{
$this->note = $note;
return $this;
}
/**
* @return Collection|AdjustmentItem[]
*/
public function getAdjustmentItems(): Collection
{
return $this->adjustmentItems;
}
public function addAdjustmentItem(AdjustmentItem $adjustmentItem): self
{
if (!$this->adjustmentItems->contains($adjustmentItem)) {
$this->adjustmentItems[] = $adjustmentItem;
$adjustmentItem->setAdjustment($this);
}
return $this;
}
public function removeAdjustmentItem(AdjustmentItem $adjustmentItem): self
{
if ($this->adjustmentItems->contains($adjustmentItem)) {
$this->adjustmentItems->removeElement($adjustmentItem);
// set the owning side to null (unless already changed)
if ($adjustmentItem->getAdjustment() === $this) {
$adjustmentItem->setAdjustment(null);
}
}
return $this;
}
}
<?php
namespace AppEntityTestFin;
use AppRepositoryTestFinAdjustmentItemRepository;
use DoctrineORMMapping as ORM;
use SymfonyComponentValidatorConstraints as Assert;
/**
* @ORMEntity(repositoryClass=AdjustmentItemRepository::class)
* @ORMTable(name="`test_financials_adjustment_item`")
*/
class AdjustmentItem
{
/**
* @ORMId()
* @ORMGeneratedValue()
* @ORMColumn(type="integer")
*/
private $id;
/**
* @ORMManyToOne(targetEntity=Adjustment::class, inversedBy="adjustmentItems")
* @ORMJoinColumn(nullable=false)
*/
private $adjustment;
/**
* @ORMManyToOne(targetEntity=Charge::class, inversedBy="adjustmentItems")
* @ORMJoinColumn(nullable=false)
* @AssertValid
*/
private $charge;
public function getId(): ?int
{
return $this->id;
}
public function getAdjustment(): ?Adjustment
{
return $this->adjustment;
}
public function setAdjustment(?Adjustment $adjustment): self
{
$this->adjustment = $adjustment;
return $this;
}
public function getCharge(): ?Charge
{
return $this->charge;
}
public function setCharge(?Charge $charge): self
{
$this->charge = $charge;
return $this;
}
}
$json = json_encode([
"note" => "bla",
"adjustmentItems" => [
["charge" => 1],
],
]);
$credit = $this->_deserializeJson($json, Adjustment::class);
//dd($credit);
//dd($credit->getAdjustmentItems()->first()->getCharge()->getAdjustmentItems()->toArray());
$this->_validate($credit);
Комментарии:
1. Я думаю, вы должны показать свой код. Потому что причин может быть слишком много — может быть, группа проверки, может быть, в контроллере, может быть, вы что-то забыли..
2. @UrmatZhenaliev Я добавил код
Ответ №1:
Вызов Charge::addAdjustmentItem
AdjustmentItem::setCharge
решил проблему для меня.
Кто-нибудь знает, зачем это нужно?
public function setCharge(?Charge $charge): self
{
$this->charge = $charge;
// This is needed so that the Assert/Callback in Charge knows about this adjustmentItem.
$charge->addAdjustmentItem($this);
return $this;
}