Платформа API: сериализация денормализации для вложенных данных с пользовательским идентификатором (НЕ первичным ключом объекта)

#symfony4 #api-platform.com

#symfony4 #api-platform.com

Вопрос:

Как использовать пользовательский идентификатор (не первичный ключ) при денормализации вложенных данных?

Я уже использую группы для вложенных данных, чтобы нормализовать / денормализовать мой ресурс.

У меня есть приведенный ниже JSON, который используется для создания:

  • счет-фактура
    • InvoiceLine
      • элемент
 {
    "total": "1060.000",
    "paid": "1100.000",
    "status": true,
    "invoiceLine": [
        {
            "price": "460.000",
            "quantity": 1,
            "item": {
                "clientItemId": 9,
                "name": "laptop",
                "price": "13000",
                "category": "/categories/2"
            }
        },
        {
            "price": "600.000",
            "quantity": 2,
            "item": {
                "clientItemId": 10,
                "name": "screen",
                "price": "300.000",
                "category": "/categories/2"
            }
        }
    ]
}
  

Как я могу убедиться, что элементы не всегда создаются (дублируются), используя clientItemId вместо объекта id ?

Примечание: это я не могу использовать clientItemId в качестве своего первичного ключа, поскольку у меня разные клиенты, и у 2 клиентов может быть одинаковое значение для clientItemId (думайте об этом как об уникальном ссылочном коде, предоставленном клиентом), поэтому у меня есть собственное сгенерированное значение id .

Классы сущностей

api/src/Entity/InvoiceLine.php

 <?php

namespace AppEntity;

use ApiPlatformCoreAnnotationApiResource;
use SymfonyComponentSerializerAnnotationGroups;
use SymfonyComponentValidatorConstraints as Assert;
use DoctrineORMMapping as ORM;

/**
 * @ApiResource()
 * @ORMEntity(repositoryClass="AppRepositoryInvoiceLineRepository")
 */
class InvoiceLine
{
    /**
     * @ORMId()
     * @ORMGeneratedValue()
     * @ORMColumn(type="integer")
     *
     * @Groups({"order"})
     */
    private $id;

    /**
     * @ORMColumn(type="decimal", precision=15, scale=2)
     *
     * @Groups({"order"})
     */
    private $price;

    /**
     * @ORMColumn(type="integer")
     *
     * @Groups({"order"})
     */
    private $quantity;

    /**
     * @ORMManyToOne(
     *     targetEntity="AppEntityInvoice",
     *     inversedBy="InvoiceLines"
     * )
     * @ORMJoinColumn(nullable=false)
     */
    private $invoice;

    /**
     * @ORMManyToOne(
     *     targetEntity="AppEntityItem",
     *     cascade={"persist"}
     * )
     * @ORMJoinColumn(nullable=false)
     *
     * @Groups({"order"})
     */
    private $item;
...
  

api/src/Entity/Item.php

 <?php

namespace AppEntity;

use ApiPlatformCoreAnnotationApiResource;
use ApiPlatformCoreAnnotationApiSubresource;
use ApiPlatformCoreAnnotationApiProperty;
use SymfonyComponentSerializerAnnotationGroups;
use DoctrineORMMapping as ORM;

/**
 * @ApiResource()
 * @ORMEntity(repositoryClass="AppRepositoryItemRepository")
 */
class Item
{
    /**
     * @ORMId()
     * @ORMGeneratedValue()
     * @ORMColumn(type="integer")
     *
     * @Groups({"order"})
     */
    private $id;

    /**
     * @ORMColumn(type="integer", nullable=true)
     *
     * @Groups({"order"})
     */
    private $clientItemId;

    /**
     * @ORMColumn(type="string", length=255)
     *
     * @Groups({"order"})
     */
    private $name;

    /**
     * @ORMColumn(type="decimal", precision=15, scale=3)
     *
     * @Groups({"order"})
     */
    private $price;

    /**
     * @ORMManyToOne(targetEntity="AppEntityItemCategory", inversedBy="Items")
     * @ORMJoinColumn(nullable=false)
     *
     * @Groups({"order"})
     */
    private $ItemCategory;
...
  

Комментарии:

1. У вас есть объект Item со свойствами: clientItemId , name , price , category ? Есть ли у него поле, invoiceLine как ManyToOne относящееся к InvoiceLine ?

2. @cezar добавил содержимое объектов InvoiceLine и Item, кстати, элемент связан только с объектом InvoiceLine.

3. Не уверен, о чем вы спрашиваете. Нет, вы не можете использовать неуникальный идентификатор для идентификации объекта. Да, вы можете включить первичный ключ для идентификации item .

4. Как насчет пользовательского денормализатора?

5. Вы хотите проверить, существует ли уже элемент с тем же clientItemId перед вставкой в DB?