У меня есть пакет общих доктринных сущностей для нескольких проектов.
Первый проект извлекает данные из внешнего 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
}
]
}