Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/symfony/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Symfony 带额外字段的多对多条令(更新和删除特定项目)_Symfony_Doctrine_Many To Many - Fatal编程技术网

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”这样的发票号码并不是您希望用户能够随意修改的事情。回到您最初的问题:代码如此混乱的一个原因是您试图用一个请求做很多事情。例如,更新发票可以有自己的操作。