如何在反规范化之前修改数据并将其发回?

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 }