PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Friday, March 4, 2022

[FIXED] How to modify data before the denormalization and send It back?

 March 04, 2022     api-platform.com, denormalization, symfony     No comments   

Issue

I'd like to have advice on the best practice to achieve something.

I've a JSON output of an entity called "Session" with 3 related entities (platform, user, course ) and I'd like to use the nested way to create those 3 related if they don't exist.

But If they do exist I'd like to add their IRI (or ID) to the JSON output before API Platform does the magic. (or another way to achieve this behavior)

I naively thought that I should bind to the pre_denormalization event but I've no idea how to return the data to the event.

Here is what I've got so far.

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);
}

And the 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

}

I can't get the ID in this JSON since those information are provided by a Puppeteer APP, or I should do 3 request to check if the related entity exist first, which is not adviced I think.

I also tried to change the identifier on the user, course and platform but In both cases, I've duplicate entries in database


Solution

I manage to do what I want with a custom denormalizer.

So I can post and update data comming from tierce source without ID.

class SessionDenormalizer implements DenormalizerAwareInterface, ContextAwareDenormalizerInterface

{ use 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 }


Answered By - DrK
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing