如何在反规范化之前修改数据并将其发回?
How to modify data before the denormalization and send It back?
我想获得有关实现某些目标的最佳实践的建议。
我有一个名为“Session”的实体的 JSON 输出,其中包含 3 个相关实体(平台、用户、课程),我想使用嵌套方式创建这 3 个相关实体,如果它们不存在。
但是如果它们确实存在,我想在 API 平台发挥作用之前将它们的 IRI(或 ID)添加到 JSON 输出中。 (或实现此行为的另一种方式)
我天真地认为我应该绑定到 pre_denormalization 事件,但我不知道如何将数据 return 绑定到事件。
这是我目前所知道的。
public static function getSubscribedEvents()
{
return [
KernelEvents::REQUEST => ['onSessionDenormalize', EventPriorities::PRE_DESERIALIZE],
];
}
public function onSessionDenormalize(RequestEvent $event)
{
$data = $event->getRequest()->getContent();
}
public function modifyPayLoad($data) {
$dataObject = json_decode($data);
$platform = $dataObject->platform;
$user = $dataObject->user;
$course = $dataObject->course;
if($this->platformRepository->findOneBy(['slug' => $platform->slug])) {
$platformID = $this->courseRepository->findOneBy(['slug' => $platform->slug])->getId();
$dataObject->id = $platformID;
if($this->userRepository->findOneBy(['email' => $user->slug])) {
$dataObject->id = $this->userRepository->findOneBy(['email' => $user->slug])->getId();
$dataObject->user->platform->id = $platformID;
}
if($this->courseRepository->findOneBy(['slug' => $course->slug])) {
$dataObject->id = $this->courseRepository->findOneBy(['slug' => $course->slug])->getId();
$dataObject->course->platform->id = $platformID;
}
}
return json_encode($dataObject);
}
和 JSON:
{
"user": {
"firstname": "string",
"lastname": "string",
"address": "string",
"city": "string",
"email": "string",
"zipCode": int,
"hubspotID": int
},
"course": {
"id": "string",
"title": "string",
"platform": {
"slug": "string",
"name": "string"
}
},
"startDate": "2022-01-09T23:59:00.000Z",
"endDate": "2022-02-09T23:59:00.000Z",
"hubspotDealId": int
}
我无法在这个 JSON 中获取 ID,因为这些信息是由 Puppeteer APP 提供的,或者我应该先执行 3 个请求以检查相关实体是否存在,我认为不建议这样做.
我还尝试更改用户、课程和平台的标识符,但在这两种情况下,我在数据库中都有重复的条目
我设法用自定义反规范化器做我想做的事。
所以我可以 post 更新来自没有 ID 的 tierce 源的数据。
class SessionDenormalizer implements DenormalizerAwareInterface, ContextAwareDenormalizerInterface
{
使用 DenormalizerAwareTrait;
public function __construct(
private UserRepository $userRepository,
private PlatformRepository $platformRepository,
private CourseRepository $courseRepository,
private SessionRepository $sessionRepository,
)
{
}
private const ALREADY_CALLED = 'SESSION_DENORMALIZER_ALREADY_CALLED';
public function supportsDenormalization($data, string $type, string $format = null, array $context = []): bool
{
if (isset($context[self::ALREADY_CALLED])) {
return false;
}
return $type === Session::class;
}
public function denormalize($data, string $type, string $format = null, array $context = [])
{
if (isset(
$data["user"]["email"],
$data["course"]["slug"],
$data["course"]["platform"]["slug"],
)) {
$user = $this->userRepository->findOneBy(["email" => $data["user"]["email"]]);
$course = $this->courseRepository->findOneBy(["slug" => $data["course"]["slug"]]);
$platform = $this->platformRepository->findOneBy(["slug" => $data["course"]["platform"]["slug"]]);
if ($user && $course && $platform) {
$data["user"]["@id"] = "/v1/users/" . $user?->getId();
$data["course"]["@id"] = "/v1/courses/" . $course?->getId();
$data["course"]["platform"]["@id"] = "/v1/platforms/" . $platform?->getId();
$session = $this->sessionRepository->findOneBy(["cpfID" => $data["cpfID"]]);
if($session) {
$data["@id"] = "/v1/sessions/" . $session->getId();
if(isset($context["collection_operation_name"])) {
$context["collection_operation_name"] = "put";
}
if(isset($context['api_allow_update'])) {
$context['api_allow_update'] = true;
}
}
}
}
$context[self::ALREADY_CALLED] = true;
return $this->denormalizer->denormalize($data , $type , $format , $context);
}
}
Services.yaml :
'app.session.denormalizer.json':
class: 'App\Serializer\Denormalizer\SessionDenormalizer'
tags:
- { name: 'serializer.normalizer', priority: 64 }
我想获得有关实现某些目标的最佳实践的建议。
我有一个名为“Session”的实体的 JSON 输出,其中包含 3 个相关实体(平台、用户、课程),我想使用嵌套方式创建这 3 个相关实体,如果它们不存在。
但是如果它们确实存在,我想在 API 平台发挥作用之前将它们的 IRI(或 ID)添加到 JSON 输出中。 (或实现此行为的另一种方式)
我天真地认为我应该绑定到 pre_denormalization 事件,但我不知道如何将数据 return 绑定到事件。
这是我目前所知道的。
public static function getSubscribedEvents()
{
return [
KernelEvents::REQUEST => ['onSessionDenormalize', EventPriorities::PRE_DESERIALIZE],
];
}
public function onSessionDenormalize(RequestEvent $event)
{
$data = $event->getRequest()->getContent();
}
public function modifyPayLoad($data) {
$dataObject = json_decode($data);
$platform = $dataObject->platform;
$user = $dataObject->user;
$course = $dataObject->course;
if($this->platformRepository->findOneBy(['slug' => $platform->slug])) {
$platformID = $this->courseRepository->findOneBy(['slug' => $platform->slug])->getId();
$dataObject->id = $platformID;
if($this->userRepository->findOneBy(['email' => $user->slug])) {
$dataObject->id = $this->userRepository->findOneBy(['email' => $user->slug])->getId();
$dataObject->user->platform->id = $platformID;
}
if($this->courseRepository->findOneBy(['slug' => $course->slug])) {
$dataObject->id = $this->courseRepository->findOneBy(['slug' => $course->slug])->getId();
$dataObject->course->platform->id = $platformID;
}
}
return json_encode($dataObject);
}
和 JSON:
{
"user": {
"firstname": "string",
"lastname": "string",
"address": "string",
"city": "string",
"email": "string",
"zipCode": int,
"hubspotID": int
},
"course": {
"id": "string",
"title": "string",
"platform": {
"slug": "string",
"name": "string"
}
},
"startDate": "2022-01-09T23:59:00.000Z",
"endDate": "2022-02-09T23:59:00.000Z",
"hubspotDealId": int
}
我无法在这个 JSON 中获取 ID,因为这些信息是由 Puppeteer APP 提供的,或者我应该先执行 3 个请求以检查相关实体是否存在,我认为不建议这样做.
我还尝试更改用户、课程和平台的标识符,但在这两种情况下,我在数据库中都有重复的条目
我设法用自定义反规范化器做我想做的事。
所以我可以 post 更新来自没有 ID 的 tierce 源的数据。
class SessionDenormalizer implements DenormalizerAwareInterface, ContextAwareDenormalizerInterface
{ 使用 DenormalizerAwareTrait;
public function __construct(
private UserRepository $userRepository,
private PlatformRepository $platformRepository,
private CourseRepository $courseRepository,
private SessionRepository $sessionRepository,
)
{
}
private const ALREADY_CALLED = 'SESSION_DENORMALIZER_ALREADY_CALLED';
public function supportsDenormalization($data, string $type, string $format = null, array $context = []): bool
{
if (isset($context[self::ALREADY_CALLED])) {
return false;
}
return $type === Session::class;
}
public function denormalize($data, string $type, string $format = null, array $context = [])
{
if (isset(
$data["user"]["email"],
$data["course"]["slug"],
$data["course"]["platform"]["slug"],
)) {
$user = $this->userRepository->findOneBy(["email" => $data["user"]["email"]]);
$course = $this->courseRepository->findOneBy(["slug" => $data["course"]["slug"]]);
$platform = $this->platformRepository->findOneBy(["slug" => $data["course"]["platform"]["slug"]]);
if ($user && $course && $platform) {
$data["user"]["@id"] = "/v1/users/" . $user?->getId();
$data["course"]["@id"] = "/v1/courses/" . $course?->getId();
$data["course"]["platform"]["@id"] = "/v1/platforms/" . $platform?->getId();
$session = $this->sessionRepository->findOneBy(["cpfID" => $data["cpfID"]]);
if($session) {
$data["@id"] = "/v1/sessions/" . $session->getId();
if(isset($context["collection_operation_name"])) {
$context["collection_operation_name"] = "put";
}
if(isset($context['api_allow_update'])) {
$context['api_allow_update'] = true;
}
}
}
}
$context[self::ALREADY_CALLED] = true;
return $this->denormalizer->denormalize($data , $type , $format , $context);
}
}
Services.yaml :
'app.session.denormalizer.json':
class: 'App\Serializer\Denormalizer\SessionDenormalizer'
tags:
- { name: 'serializer.normalizer', priority: 64 }