[SOLVED] Autoincrement integer

Hello, everybody. I am using Neos Flow version 6. I have a model “order” which is stored in the database. Of course each “order” has the unique persistence_object_identifier. However, I would like to implement a unique, consecutive number (“order number”). I have played a lot with Doctrine the last few days, but Flow and Doctrine don’t like me :slight_smile:

Can anyone help me at this point? Does anyone have a suitable code snippet that I could try out?

Thank you very much for your support!

Many greetings,

Tobias

Hi!
this should work:

/**
 * @ORM\Id
 * @ORM\GeneratedValue
 * @var int
 */
protected $id;

Dear Bastian,

thank you very much for your quick answer. I have tested your code and it works very well and is also very simple. I like it. :slight_smile:
Thank you!

Tobias

1 Like

A little hasty, I’m afraid.
When I’m using:

/**
 * @ORM\Id
 * @ORM\GeneratedValue
 * @var int
 */
protected $id;

Then, there will be no persistence_object_identifier anymore.

When I’m using:

/**
 * @ORM\GeneratedValue
 * @var int
 */
protected $id;

there will be an error: SQLSTATE[HY000]: General error: 1364 Field ‘persistence_object_identifier’ doesn’t have a default value. Unfortunately I did not mention in the first question that I want to leave the persistence_object_identifier untouched. I want to create the consecutive number in parallel. I’m sorry for the missleading question.

Any idea to solve this behavior?

Thank you very much!

Tobias

OK, I’m sorry. It seems Doctrine only supports the GeneratedValue annotation for Identifier columns (see https://github.com/doctrine/orm/issues/7215#issuecomment-479868492).

You could turn it around, make the $id the actual id and add the persistence_object_identifier column manually:

<?php
declare(strict_types=1);
namespace Some\Package;

use Neos\Flow\Annotations as Flow;
use Doctrine\ORM\Mapping as ORM;
use Neos\Flow\Utility\Algorithms;

/**
 * @Flow\Entity
 */
class SomeEntity
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @var int
     */
    protected $id;

    /**
     * @var string
     */
    protected $Persistence_Object_Identifier;

    public function __construct()
    {
        $this->Persistence_Object_Identifier = Algorithms::generateUUID();
    }
}

But at this point I’d really question your intention? What do you want to achieve?

Dear Bastian,

thank you very much for your kind answer. Let me explain my problem in more detail…

I have the object “order”. An instance of “order” has many references to other objects (for example “shipping”, “bought items” etc). However, an “order” shall have an unique id (consecutive number). My system shall be usable by many users at the same time. Therefore, SQL should manage the unique order id.

I like your idea, setting the POI “manually”. But I’m not sure whether in your idea for example “shipping” refers to the POI or then to the “order number”?

What do you think is the best, safest and easiest solution?

Again thank you very much for your help.

Best regards,

Tobias

Aah, a classic one! :slightly_smiling_face:
In that case I would strongly recommend to make the order numbering an explicit concept.
For example you could introduce an OrderNumberingService that stores the highest number for a given type (“Nummernkreis”) in a database table.
Whenever an order is finalized you could assign a number using that service.

In the simplest case you could make use of the Doctrine Event System to assign the number just before the order is persisted.

Ah okay, this sounds like a reasonable workaround.
So, I think, I will use your first suggestion:

/**
 * @Flow\Entity
 */
class OrderNumerGenerator
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @var int
     */
    protected $id;

By creating a new order, I will add a new instance of “OrderNumerGenerator” => a new unique number will be created (eventListener => prePersist). However, on a last point I can’t get the right way:

$orderNumber = new OrderNumberGenerator();
$this->persistenceManager->persistAll();
$createdNumber = ???

How I can get EXACTLY this number which was created at this persist? I need to be 100% sure that this number is not used by another process that happened to run at the same time (multi-user application).

I have the feeling I’m coming closer and closer to the solution :slight_smile: Thank you very much for your great support!

You could of course do sth like

<?php
declare(strict_types=1);
namespace Your\Namespace;

use Doctrine\ORM\Mapping as ORM;
use Neos\Flow\Annotations as Flow;

/**
 * @Flow\Entity
 */
final class OrderNumber
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @var int
     */
    protected $number;

    public function getValue(): int
    {
        return $this->number;
    }
}

and then

<?php
// ...
$orderNumber = new OrderNumber();
$this->persistenceManager->add($orderNumber);
$this->persistenceManager->persistAll();
// $orderNumber->getValue() contains the next number

But I would rather use DBAL directly for that and encapsulate the logic in some Service that can be used like $orderNumber = $this->orderNumberService->allocateNext(); (that service would only need to keep track of the last number btw, no need for an auto_increment column).

In both cases you risk that a number was generated but never used because of some exception that happened afterwards.

Thank you very much for your great support. You really helped me a lot!

1 Like