Symfony 带额外字段的多对多条令(更新和删除特定项目)
早上好。Symfony 带额外字段的多对多条令(更新和删除特定项目),symfony,doctrine,many-to-many,Symfony,Doctrine,Many To Many,早上好。 我在更新和删除特定项目时遇到问题。我在整个互联网上搜索答案,但没有找到,什么地方也没有找到 这就是我所拥有的 1。行动理念: 将销售发票添加到特定预算中,以计算剩余的结算金额。每个发票可结算到多个项目步骤。 示例: 2。数据库关系 3。发布和修补所需的JSON请求示例 {“数字”:“4/2020”,“净价值”:4000.00,“预算详情”:[{“id”:2,“价值”:500.00},{“id”:3,“价值”:3500.00} 4。实体 salesvoice.php namespa
我在更新和删除特定项目时遇到问题。我在整个互联网上搜索答案,但没有找到,什么地方也没有找到 这就是我所拥有的 1。行动理念:
将销售发票添加到特定预算中,以计算剩余的结算金额。每个发票可结算到多个项目步骤。
示例: 2。数据库关系 3。发布和修补所需的JSON请求示例
{“数字”:“4/2020”,“净价值”:4000.00,“预算详情”:[{“id”:2,“价值”:500.00},{“id”:3,“价值”:3500.00}
4。实体
salesvoice.php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Table(name="SalesInvoices")
* @ORM\Entity(repositoryClass="App\Repository\SalesInvoiceRepository")
* @ORM\HasLifecycleCallbacks()
*/
class SalesInvoice
{
use Timestamps;
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $number;
/**
* @ORM\Column(type="decimal", precision=10, scale=2)
*/
private $netValue;
/**
* @ORM\OneToMany(targetEntity="SalesInvoiceBudget", mappedBy="salesInvoice", cascade={"persist", "remove"}, fetch="EAGER")
*/
private $salesInvoiceBudgets;
public function __construct()
{
$this->salesInvoiceBudgets = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getNumber(): ?string
{
return $this->number;
}
public function setNumber(string $number): self
{
$this->number = $number;
return $this;
}
public function getNetValue(): ?string
{
return $this->netValue;
}
public function setNetValue(string $netValue): self
{
$this->netValue = $netValue;
return $this;
}
/**
* @return Collection|SalesInvoiceBudget[]
*/
public function getSalesInvoiceBudgets(): Collection
{
return $this->salesInvoiceBudgets;
}
public function addSalesInvoiceBudget(SalesInvoiceBudget $salesInvoiceBudget): self
{
if (!$this->salesInvoiceBudgets->contains($salesInvoiceBudget)) {
$this->salesInvoiceBudgets[] = $salesInvoiceBudget;
$salesInvoiceBudget->setSalesInvoice($this);
}
return $this;
}
public function removeSalesInvoiceBudget(SalesInvoiceBudget $salesInvoiceBudget): self
{
if ($this->salesInvoiceBudgets->contains($salesInvoiceBudget)) {
$this->salesInvoiceBudgets->removeElement($salesInvoiceBudget);
// set the owning side to null (unless already changed)
if ($salesInvoiceBudget->getSalesInvoice() === $this) {
$salesInvoiceBudget->setSalesInvoice(null);
}
}
return $this;
}
}
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Table(name="SalesInvoices_ProjectBudgets")
* @ORM\Entity(repositoryClass="App\Repository\SalesInvoiceBudgetRepository")
*/
class SalesInvoiceBudget
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity="SalesInvoice", inversedBy="salesInvoiceBudgets", cascade={"persist"})
* @ORM\JoinColumn(referencedColumnName="id", nullable=false, onDelete="CASCADE")
*/
private $salesInvoice;
/**
* @ORM\ManyToOne(targetEntity="ProjectBudget", inversedBy="salesInvoiceBudgets", cascade={"persist"})
* @ORM\JoinColumn(referencedColumnName="id", nullable=false, onDelete="CASCADE")
*/
private $budget;
/**
* @ORM\Column(type="decimal", precision=10, scale=2)
*/
private $value;
public function getId(): ?int
{
return $this->id;
}
public function getValue(): ?string
{
return $this->value;
}
public function setValue(string $value): self
{
$this->value = $value;
return $this;
}
public function getSalesInvoice(): ?SalesInvoice
{
return $this->salesInvoice;
}
public function setSalesInvoice(?SalesInvoice $salesInvoice): self
{
$this->salesInvoice = $salesInvoice;
return $this;
}
public function getBudget(): ?ProjectBudget
{
return $this->budget;
}
public function setBudget(?ProjectBudget $budget): self
{
$this->budget = $budget;
return $this;
}
}
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Table(name="SalesInvoices_ProjectBudgets")
* @ORM\Entity(repositoryClass="App\Repository\SalesInvoiceBudgetRepository")
*/
class SalesInvoiceBudget
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity="SalesInvoice", inversedBy="salesInvoiceBudgets", cascade={"persist"})
* @ORM\JoinColumn(referencedColumnName="id", nullable=false, onDelete="CASCADE")
*/
private $salesInvoice;
/**
* @ORM\ManyToOne(targetEntity="ProjectBudget", inversedBy="salesInvoiceBudgets", cascade={"persist"})
* @ORM\JoinColumn(referencedColumnName="id", nullable=false, onDelete="CASCADE")
*/
private $budget;
/**
* @ORM\Column(type="decimal", precision=10, scale=2)
*/
private $value;
public function getId(): ?int
{
return $this->id;
}
public function getValue(): ?string
{
return $this->value;
}
public function setValue(string $value): self
{
$this->value = $value;
return $this;
}
public function getSalesInvoice(): ?SalesInvoice
{
return $this->salesInvoice;
}
public function setSalesInvoice(?SalesInvoice $salesInvoice): self
{
$this->salesInvoice = $salesInvoice;
return $this;
}
public function getBudget(): ?ProjectBudget
{
return $this->budget;
}
public function setBudget(?ProjectBudget $budget): self
{
$this->budget = $budget;
return $this;
}
}
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Table(name="ProjectBudgets")
* @ORM\Entity(repositoryClass="App\Repository\ProjectBudgetRepository")
* @ORM\HasLifecycleCallbacks()
*/
class ProjectBudget
{
use Timestamps;
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="decimal", precision=10, scale=2, nullable=true)
*/
private $budgetAmount;
/**
* @ORM\OneToMany(targetEntity="SalesInvoiceBudget", mappedBy="budget", fetch="EXTRA_LAZY")
*/
private $salesInvoiceBudgets;
public function __construct()
{
$this->salesInvoiceBudgets = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getBudgetAmount(): ?string
{
return $this->budgetAmount;
}
public function setBudgetAmount(?string $budgetAmount): self
{
$this->budgetAmount = $budgetAmount;
return $this;
}
/**
* @return Collection|SalesInvoiceBudget[]
*/
public function getSalesInvoiceBudgets(): Collection
{
return $this->salesInvoiceBudgets;
}
public function addSalesInvoiceBudget(SalesInvoiceBudget $salesInvoiceBudget): self
{
if (!$this->salesInvoiceBudgets->contains($salesInvoiceBudget)) {
$this->salesInvoiceBudgets[] = $salesInvoiceBudget;
$salesInvoiceBudget->setBudget($this);
}
return $this;
}
public function removeSalesInvoiceBudget(SalesInvoiceBudget $salesInvoiceBudget): self
{
if ($this->salesInvoiceBudgets->contains($salesInvoiceBudget)) {
$this->salesInvoiceBudgets->removeElement($salesInvoiceBudget);
// set the owning side to null (unless already changed)
if ($salesInvoiceBudget->getBudget() === $this) {
$salesInvoiceBudget->setBudget(null);
}
}
return $this;
}
}
saleinvoicebudget.php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Table(name="SalesInvoices")
* @ORM\Entity(repositoryClass="App\Repository\SalesInvoiceRepository")
* @ORM\HasLifecycleCallbacks()
*/
class SalesInvoice
{
use Timestamps;
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $number;
/**
* @ORM\Column(type="decimal", precision=10, scale=2)
*/
private $netValue;
/**
* @ORM\OneToMany(targetEntity="SalesInvoiceBudget", mappedBy="salesInvoice", cascade={"persist", "remove"}, fetch="EAGER")
*/
private $salesInvoiceBudgets;
public function __construct()
{
$this->salesInvoiceBudgets = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getNumber(): ?string
{
return $this->number;
}
public function setNumber(string $number): self
{
$this->number = $number;
return $this;
}
public function getNetValue(): ?string
{
return $this->netValue;
}
public function setNetValue(string $netValue): self
{
$this->netValue = $netValue;
return $this;
}
/**
* @return Collection|SalesInvoiceBudget[]
*/
public function getSalesInvoiceBudgets(): Collection
{
return $this->salesInvoiceBudgets;
}
public function addSalesInvoiceBudget(SalesInvoiceBudget $salesInvoiceBudget): self
{
if (!$this->salesInvoiceBudgets->contains($salesInvoiceBudget)) {
$this->salesInvoiceBudgets[] = $salesInvoiceBudget;
$salesInvoiceBudget->setSalesInvoice($this);
}
return $this;
}
public function removeSalesInvoiceBudget(SalesInvoiceBudget $salesInvoiceBudget): self
{
if ($this->salesInvoiceBudgets->contains($salesInvoiceBudget)) {
$this->salesInvoiceBudgets->removeElement($salesInvoiceBudget);
// set the owning side to null (unless already changed)
if ($salesInvoiceBudget->getSalesInvoice() === $this) {
$salesInvoiceBudget->setSalesInvoice(null);
}
}
return $this;
}
}
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Table(name="SalesInvoices_ProjectBudgets")
* @ORM\Entity(repositoryClass="App\Repository\SalesInvoiceBudgetRepository")
*/
class SalesInvoiceBudget
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity="SalesInvoice", inversedBy="salesInvoiceBudgets", cascade={"persist"})
* @ORM\JoinColumn(referencedColumnName="id", nullable=false, onDelete="CASCADE")
*/
private $salesInvoice;
/**
* @ORM\ManyToOne(targetEntity="ProjectBudget", inversedBy="salesInvoiceBudgets", cascade={"persist"})
* @ORM\JoinColumn(referencedColumnName="id", nullable=false, onDelete="CASCADE")
*/
private $budget;
/**
* @ORM\Column(type="decimal", precision=10, scale=2)
*/
private $value;
public function getId(): ?int
{
return $this->id;
}
public function getValue(): ?string
{
return $this->value;
}
public function setValue(string $value): self
{
$this->value = $value;
return $this;
}
public function getSalesInvoice(): ?SalesInvoice
{
return $this->salesInvoice;
}
public function setSalesInvoice(?SalesInvoice $salesInvoice): self
{
$this->salesInvoice = $salesInvoice;
return $this;
}
public function getBudget(): ?ProjectBudget
{
return $this->budget;
}
public function setBudget(?ProjectBudget $budget): self
{
$this->budget = $budget;
return $this;
}
}
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Table(name="SalesInvoices_ProjectBudgets")
* @ORM\Entity(repositoryClass="App\Repository\SalesInvoiceBudgetRepository")
*/
class SalesInvoiceBudget
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity="SalesInvoice", inversedBy="salesInvoiceBudgets", cascade={"persist"})
* @ORM\JoinColumn(referencedColumnName="id", nullable=false, onDelete="CASCADE")
*/
private $salesInvoice;
/**
* @ORM\ManyToOne(targetEntity="ProjectBudget", inversedBy="salesInvoiceBudgets", cascade={"persist"})
* @ORM\JoinColumn(referencedColumnName="id", nullable=false, onDelete="CASCADE")
*/
private $budget;
/**
* @ORM\Column(type="decimal", precision=10, scale=2)
*/
private $value;
public function getId(): ?int
{
return $this->id;
}
public function getValue(): ?string
{
return $this->value;
}
public function setValue(string $value): self
{
$this->value = $value;
return $this;
}
public function getSalesInvoice(): ?SalesInvoice
{
return $this->salesInvoice;
}
public function setSalesInvoice(?SalesInvoice $salesInvoice): self
{
$this->salesInvoice = $salesInvoice;
return $this;
}
public function getBudget(): ?ProjectBudget
{
return $this->budget;
}
public function setBudget(?ProjectBudget $budget): self
{
$this->budget = $budget;
return $this;
}
}
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Table(name="ProjectBudgets")
* @ORM\Entity(repositoryClass="App\Repository\ProjectBudgetRepository")
* @ORM\HasLifecycleCallbacks()
*/
class ProjectBudget
{
use Timestamps;
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="decimal", precision=10, scale=2, nullable=true)
*/
private $budgetAmount;
/**
* @ORM\OneToMany(targetEntity="SalesInvoiceBudget", mappedBy="budget", fetch="EXTRA_LAZY")
*/
private $salesInvoiceBudgets;
public function __construct()
{
$this->salesInvoiceBudgets = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getBudgetAmount(): ?string
{
return $this->budgetAmount;
}
public function setBudgetAmount(?string $budgetAmount): self
{
$this->budgetAmount = $budgetAmount;
return $this;
}
/**
* @return Collection|SalesInvoiceBudget[]
*/
public function getSalesInvoiceBudgets(): Collection
{
return $this->salesInvoiceBudgets;
}
public function addSalesInvoiceBudget(SalesInvoiceBudget $salesInvoiceBudget): self
{
if (!$this->salesInvoiceBudgets->contains($salesInvoiceBudget)) {
$this->salesInvoiceBudgets[] = $salesInvoiceBudget;
$salesInvoiceBudget->setBudget($this);
}
return $this;
}
public function removeSalesInvoiceBudget(SalesInvoiceBudget $salesInvoiceBudget): self
{
if ($this->salesInvoiceBudgets->contains($salesInvoiceBudget)) {
$this->salesInvoiceBudgets->removeElement($salesInvoiceBudget);
// set the owning side to null (unless already changed)
if ($salesInvoiceBudget->getBudget() === $this) {
$salesInvoiceBudget->setBudget(null);
}
}
return $this;
}
}
5。控制器的一部分
/**
* @Rest\RequestParam(name="number")
* @Rest\RequestParam(name="netValue")
* @Rest\RequestParam(name="budgetsDetails", nullable=true)
* @param ParamFetcher $paramFetcher
* @return View
* @throws Exception
*/
public function postSinvoiceAction(ParamFetcher $paramFetcher)
{
$number = $paramFetcher->get('number');
$netValue = $paramFetcher->get('netValue');
$budgetsDetails = $paramFetcher->get('budgetsDetails');
if($number === null) {
return $this->view(null, Response::HTTP_BAD_REQUEST);
}
$contractor = $this->contractorRepository->findOneBy(array("id" => $contractorId));
$invoice = new SalesInvoice();
$invoice->setNumber($number);
$invoice->setNetValue($netValue);
if ($budgetsDetails && sizeof($budgetsDetails) > 0) {
foreach ($budgetsDetails as $budgetDetails) {
$budget = $this->projectBudgetRepository->findOneBy(array('id' => $budgetDetails['id']));
if ($budget === null) {
return $this->view("There is no budget like this.");
}
$relation = new SalesInvoiceBudget();
$relation->setBudget($budget);
$relation->setValue($budgetDetails['value']);
$invoice->addSalesInvoiceBudget($relation);
}
}
$this->entityManager->persist($invoice);
$this->entityManager->flush();
return $this->view("Added.", Response::HTTP_CREATED);
}
}
使用上述JSON向项目阶段添加新发票并分配金额是可行的,但当有人在输入待结算金额时出错或在项目的错误阶段结算时,我不知道如何编辑和删除分配的预算。我成功实现了我的目标,但我认为这看起来很糟糕。它可以工作,但它可能没有按它应该的那样编码
/**
* @Rest\RequestParam(name="number")
* @Rest\RequestParam(name="netValue")
* @Rest\RequestParam(name="budgetsDetails", nullable=true)
* @param ParamFetcher $paramFetcher
* @param SalesInvoice $invoice
* @return View
* @throws Exception
*/
public function patchSinvoiceAction(ParamFetcher $paramFetcher, SalesInvoice $invoice)
{
$number = $paramFetcher->get('number');
$netValue = $paramFetcher->get('netValue');
$budgetsDetails = $paramFetcher->get('budgetsDetails');
if($number === null) {
return $this->view(null, Response::HTTP_BAD_REQUEST);
}
$invoice->setNumber($number);
$invoice->setNetValue($netValue);
if ($budgetsDetails && sizeof($budgetsDetails) > 0) {
foreach ($budgetsDetails as $item) {
// Iterating the record found in the request.
if ($relation = $this->salesInvoiceBudgetRepository->findOneBy(array('budget' => $item['id'], 'salesInvoice' => $invoice->getId()))) {
// An existing record in the database that matches the request was found. Edit.
$relation->setValue($item['value']);
} else {
// There is no matching database record for the request. Adding a record.
$budget = $this->projectBudgetRepository->findOneBy(array('id' => $item['id']));
$relation = new SalesInvoiceBudget();
$relation->setBudget($budget);
$relation->setValue($item['value']);
$invoice->addSalesInvoiceBudget($relation);
}
}
// Clearing the database of records that are not in the request. Since they are not there, they must be removed.
$relations = $invoice->getSalesInvoiceBudgets();
foreach ($relations as $relation) {
if (!in_array($relation->getBudget()->getId(), array_column($budgetsDetails, 'id'))) {
// A record was found in the database that is not in the request. Delete a record.
$relation->getSalesInvoice()->removeSalesInvoiceBudget($relation);
}
}
}
$this->entityManager->persist($invoice);
$this->entityManager->flush();
return $this->view("Added.", Response::HTTP_CREATED);
}
你是在问如何查询特定的SalesInvoiceBudget吗?当有人发送这样修改过的JSON时:
{“number”:“4/2020”,“netValue”:4000.00,“BudgetDetails”:[{“id”:2,“value”:500.00},{“id”:1,“value”:800.00}
我想删除未使用的,添加新的并编辑现有的。通常在“销售\发票\项目\预算”表上进行操作。据我所知,没有内置解决方案。它将采取一些步骤,部分取决于您的总体设计。首先添加SalesInvoiceBudgetRepository::findBySalesInvoiceNumber($number);方法。这将为您提供给定发票的所有当前预算详细信息的列表。在此之后,问题是将列表与数据进行比较,并找出需要更改的内容。一步一个脚印。为这类事情设置一个功能测试是一个很大的帮助。无论你如何处理,这类代码几乎总是有点混乱。此部件,$invoice->setNumber($number);看起来可疑。我认为传递的$invoice已经被$number查询过了。更新它似乎有点错误。但如果它满足了您的需要,那么好吧。我一点也不理解这句话:“我认为传递的$invoice应该已经被$number查询过了。”如何实例化$invoice?我假设它是从数据库加载的。它是按id还是按编号加载的?在API路径I中,输入发票的id,但在控制器方法中,参数是发票对象。如果我想更新发票号,我需要设置它。始终要小心传递ID。请记住,用户更改它们是微不足道的。而且,似乎拥有“4/2020”这样的发票号码并不是您希望用户能够随意修改的事情。回到您最初的问题:代码如此混乱的一个原因是您试图用一个请求做很多事情。例如,更新发票可以有自己的操作。