Сериализация представлений JSON вложенных элементов Doctrine обратно в Doctrine - PullRequest
0 голосов
/ 30 мая 2019

У меня есть пакет общих доктринных сущностей для нескольких проектов.

Первый проект извлекает данные из внешнего API, сериализует данные в мои объекты Doctrine, а затем в JSON.Этот JSON помещается в очередь для чтения другим проектом.

Примером полезной нагрузки JSON будет

{
  "addressLine1": "Address1",
  "addressLine2": "Address2",
  "townCity": "",
  "county": "Somewhere",
  "postCode": "XX17 XPJ",
  "meters": [
    {
      "reference": "1234442123",
      "profileClass": null,
      "source": "Futura",
      "sourceId": 132
    }
  ],
  "source": "Futura",
  "sourceId": "00000002|97"
}

Это хорошо для моей начальной синхронизации, поскольку сущность не существует в моей базе данных, однако, если я получаю сущность, которая уже существует, я заканчиваюс

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1234442123' for key 'reference'

Могу ли я сериализовать JSON в мои объекты Doctrine, но запросить по source и source_id, чтобы извлечь существующие сущности и обновить их?

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

class SupplyPoint
{

    /**
     * @var int
     */
    private $id;

    /**
     * @var string|null
     */
    private $addressLine1;

    /**
     * @var string|null
     */
    private $addressLine2;

    /**
     * @var string|null
     */
    private $townCity;

    /**
     * @var string|null
     */
    private $county;

    /**
     * @var string|null
     */
    private $postCode;

    /**
     * @var Meter[]|array
     */
    private $meters;
class Meter
{
    /**
     * @var int|string
     */
    private $id;

    /**
     * @var SupplyPoint
     */
    private $supplyPoint;

    /**
     * @var string|null
     */
    private $reference;

    /**
     * @var int|null
     */
    private $profileClass;

В настоящее время я получаю это после сериализации, но я хочу где-то там сделать шаг, который свяжет мои данные с существующими объектами, если они существуют вбаза данных.Заполните поле идентификатора и сообщите Doctrine, что они являются существующими сущностями, которые необходимо обновить

Uttily\Entities\SupplyPoint {#964
  -id: null
  -addressLine1: "Address1"
  -addressLine2: "Address2"
  -townCity: ""
  -county: "Somewhere"
  -postCode: "XX17 XPJ"
  -meters: Doctrine\Common\Collections\ArrayCollection {#980
    -elements: array:1 [
      0 => Uttily\Entities\Meter {#1088
        -id: null
        -supplyPoint: Uttily\Entities\SupplyPoint {#964}
        -reference: "1234442123"
        -profileClass: null
        -source: "Futura"
        -sourceId: 132
        #createdAt: null
        #updatedAt: null
      }
    ]
  }
  -source: "Futura"
  -sourceId: "00000002|97"
  #createdAt: null
  #updatedAt: null
}

Я бы не стал делать это вручную, так как в Meters будет добавлено больше связей, автоматический процесс будетидеально, так что я могу просто добавить отношения в Doctrine, и он "просто работает"

Мой сериализатор:

        $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));

        $encoders = [new JsonEncoder()];
        $normalizers = [new EntityNormalizer($em), new ArrayDenormalizer(), new ObjectNormalizer($classMetadataFactory, null, null, new PhpDocExtractor())];

        $this->serializer = new Serializer($normalizers, $encoders);

* * * * * * * * * * * * * * * * * * * *

* * * * **
        if (isset($data['source'], $data['sourceId']) && $data['source'] !== null && $data['sourceId'] !== null) {
            $source = [
                'source'   => $data['source'],
                'sourceId' => $data['sourceId'],
            ];
        }

        return $this->em->getRepository($class)->findOneBy($source);

И возвращает мой SupplyPoint с существующим Meters, однако, когда я объединяю свою полезную нагрузку JSON с таким объектом, как:

        // Merge JSON data into a new or existing supply point object
        $uttilySupplyPoint = $serializer->deserializeIntoObject(
            $this->payload,
            SupplyPoint::class,
            $uttilySupplyPoint
        );

Идентификатор SupplyPoint все еще там, ноMeter идентификатор удален

    #collection: Doctrine\Common\Collections\ArrayCollection {#999
      -elements: array:1 [
        1 => Uttily\Entities\Meter {#1018
          -id: null
          -supplyPoint: Uttily\Entities\SupplyPoint {#983}
          -reference: "123456"
          -profileClass: null
          -source: "Futura"
          -sourceId: null
          #createdAt: null
          #updatedAt: null
        }
      ]
    }
...