月份生成中的 doctrine2 实体编号

doctrine2 entity number in month generation

我有发票实体,我想在其中生成给定月份内的后续数字。
实体代码:

/**
 * Class Invoice
 * @package App\Entity
 * @ORM\Entity()
 * @ORM\HasLifecycleCallbacks()
 */
class Invoice
{
(...)
   /**
     * @var int
     * @ORM\Column(type="integer")
     */
    private $year;

    /**
     * @var int
     * @ORM\Column(type="integer")
     */
    private $month;

    /**
     * @var int
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="CUSTOM")
     * @ORM\CustomIdGenerator(class="App\Helper\InvoiceNumberGenerator")
     */
    private $counter;
(...)
    /**
     * @ORM\PrePersist
     * @ORM\PreUpdate
     */
    public function numberGenerator()
    {
        if ($this->getYear() === null) {
            $this->setYear(date('Y'));
            $this->setMonth(date('m'));
        }
    }

而App\Helper\InvoiceNumberGenerator代码是:

<?php

namespace App\Helper;


use App\Entity\Invoice;
use Doctrine\Common\Persistence\ObjectRepository;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Id\AbstractIdGenerator;
use Exception;

class InvoiceNumberGenerator extends AbstractIdGenerator
{

    /**
     * Generates an invoice number
     *
     * @param EntityManager $em
     * @param Invoice $entity
     * @return mixed
     * @throws Exception
     */
    public function generate(EntityManager $em, $entity)
    {
        if (!$entity instanceof Invoice) {
            throw new Exception('Generator służy tylko do generowania numerów faktur.');
        }
        /** @var ObjectRepository | EntityRepository $invoiceRepository */
        $invoiceRepository = $em->getRepository(Invoice::class);

        /** @var Invoice $lastInvoice */
        $lastInvoice = $invoiceRepository->findOneBy(
            array(
                'year' => $entity->getYear(),
                'month' => $entity->getMonth()
            ),
            array(
                'counter' => 'desc'
            )
        );

        if (empty($lastInvoice)) {
            return 1;
        }

        return $lastInvoice->getCounter() + 1;
    }
}

当我转储 $lastInvoice 时,它显示:

Invoice {#5522 ▼
  -id: 1
  -generated: false
  -fileName: "example"
  -year: 2019
  -month: 11
  -counter: 1
  -name: "AG"
  -company: "Gall"
  -address: "Street 1"
  -address2: "Gliwice"
  -nip: "6314567890"
  -reservation: Reservation {#5855 ▶}
  -date: null
}

看起来生成器正确地选择了最后一个,但是我在尝试创建新发票时遇到了错误:

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'counter' cannot be null

对我做错了什么有什么建议吗?

只有当列也被标记为 @Id 时才会调用 @CustomIdGenerator 注释。来自 docs:

This annotations allows you to specify a user-provided class to generate identifiers. This annotation only works when both @Id and @GeneratedValue(strategy="CUSTOM") are specified.

ID 总是一种特殊的东西,因此在插入之前有时必须是完美的。要解决您的问题-因为计数器不是 id 列-,您可以在事件 listener/subscriber 中使用 lifecycle events instead (prePersist, probably) and use the event's entity manager 到 运行 您的查询。