feat: reduce session payload
This commit is contained in:
@@ -325,4 +325,62 @@ class BookingDto
|
||||
{
|
||||
return AgencyLoader::INTERNAL_AGENCY_CODE === $this->agencyCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls session serialization to exclude the heavy Travel object graph.
|
||||
*
|
||||
* Replaces the full Travel object with just its integer ID. The Booking's
|
||||
* travelData reference is also removed since it points to the same object.
|
||||
* BookingService::hydrate() restores the Travel from cache after session read.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function __serialize(): array
|
||||
{
|
||||
$data = get_object_vars($this);
|
||||
|
||||
// Replace the full Travel object graph with just its ID
|
||||
$data['travel'] = $this->travel->id;
|
||||
|
||||
// Clone Booking to avoid mutating the live object, then strip its
|
||||
// travelData reference which points to the same heavy Travel graph
|
||||
if (null !== $this->booking) {
|
||||
$booking = clone $this->booking;
|
||||
$booking->travelData = null;
|
||||
$data['booking'] = $booking;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores the DTO from session data with a minimal Travel placeholder.
|
||||
*
|
||||
* Creates a Travel object containing only the ID. BookingService::hydrate()
|
||||
* replaces this with the full Travel from cache on every session read.
|
||||
*
|
||||
* @param array<string, mixed> $data
|
||||
*/
|
||||
public function __unserialize(array $data): void
|
||||
{
|
||||
// Extract the travel ID before the property loop — 'travel' in the
|
||||
// serialized data is an int, not a Travel object
|
||||
$travelId = $data['travel'];
|
||||
unset($data['travel']);
|
||||
|
||||
// Skip keys that no longer exist as declared properties to avoid
|
||||
// dynamic property creation (deprecated since PHP 8.2)
|
||||
foreach ($data as $key => $value) {
|
||||
if (false === property_exists($this, $key)) {
|
||||
continue;
|
||||
}
|
||||
$this->$key = $value;
|
||||
}
|
||||
|
||||
// Create a skeleton Travel with only the ID; BookingService::hydrate()
|
||||
// replaces this with the full object from cache
|
||||
$travel = new Travel();
|
||||
$travel->id = $travelId;
|
||||
$this->travel = $travel;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use App\BusProNet\Constants;
|
||||
@@ -80,14 +82,12 @@ class BookingService
|
||||
*/
|
||||
public function getOrCreateBookingCreateDto(Request $request): BookingDto
|
||||
{
|
||||
$bookingCreateDto = $request->getSession()->get(self::BOOKING_CREATE_KEY);
|
||||
$bookingDto = $this->getBookingDto($request, BookingDto::MODE_CREATE);
|
||||
|
||||
// Return existing DTO from session if available
|
||||
if (null !== $bookingCreateDto) {
|
||||
return $bookingCreateDto;
|
||||
if (null !== $bookingDto) {
|
||||
return $bookingDto;
|
||||
}
|
||||
|
||||
// No session found - user must go through proper init flow
|
||||
throw new BookingSessionNotFoundException();
|
||||
}
|
||||
|
||||
@@ -105,12 +105,15 @@ class BookingService
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the booking DTO from the session.
|
||||
* Retrieves the booking DTO from the session and restores the Travel object.
|
||||
*
|
||||
* After deserialization the DTO contains only a Travel skeleton with the ID.
|
||||
* This method replaces it with the full Travel from cache via hydrate().
|
||||
*
|
||||
* @param Request $request The HTTP request containing session data
|
||||
* @param string $mode The booking mode (create/edit)
|
||||
*
|
||||
* @return BookingDto|null The booking DTO from session or null if not found
|
||||
* @return BookingDto|null The booking DTO or null if not found
|
||||
*/
|
||||
public function getBookingDto(Request $request, string $mode): ?BookingDto
|
||||
{
|
||||
@@ -121,7 +124,10 @@ class BookingService
|
||||
return null;
|
||||
}
|
||||
|
||||
return $session->get($sessionKey);
|
||||
$bookingDto = $session->get($sessionKey);
|
||||
$this->hydrate($bookingDto);
|
||||
|
||||
return $bookingDto;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,6 +154,31 @@ class BookingService
|
||||
return BookingDto::MODE_EDIT === $mode ? self::BOOKING_EDIT_KEY : self::BOOKING_CREATE_KEY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores the full Travel object from cache after session deserialization.
|
||||
*
|
||||
* BookingDto::__serialize() replaces Travel with just its ID to keep session
|
||||
* payloads small. This method fetches the complete Travel from the
|
||||
* TravelDataService cache and sets it on both the DTO and the Booking reference.
|
||||
*/
|
||||
private function hydrate(BookingDto $bookingDto): void
|
||||
{
|
||||
$travel = $this->travelDataService->getTravelData(
|
||||
$bookingDto->travel->id,
|
||||
$bookingDto->hotelId
|
||||
);
|
||||
|
||||
if (null === $travel) {
|
||||
return;
|
||||
}
|
||||
|
||||
$bookingDto->travel = $travel;
|
||||
|
||||
if (null !== $bookingDto->booking) {
|
||||
$bookingDto->booking->travelData = $travel;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all booking-related session data.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user