$submittedData The submitted participant form data * @param BookingDto $bookingDto The booking DTO to update (create or edit) * @param int $participantIndex The index of the participant being processed */ public function processField(array $submittedData, BookingDto $bookingDto, int $participantIndex): void { // Safely get the participant object, returning early if not found $participant = $this->getParticipant($bookingDto, $participantIndex); if (null === $participant) { return; } // Extract the date of birth from form data (defaults to null if not present) $dateOfBirth = $this->getFieldValue($submittedData, $this->getFieldName()); // Convert form date to DateTimeImmutable, handling empty selections as null $participant->dateOfBirth = $this->normalizeDateValue($dateOfBirth); } /** * Normalizes a date value from form submission to DateTimeImmutable or null. * * This method handles the conversion of form date values to proper DateTimeImmutable * objects. It gracefully handles empty strings, null values, and invalid date formats. * * @param mixed $value The raw value from form submission * * @return \DateTimeImmutable|null The normalized date or null if empty/invalid */ private function normalizeDateValue(mixed $value): ?\DateTimeImmutable { // Handle null or empty string (no date selected) if (null === $value || '' === trim((string) $value)) { return null; } // If already a DateTimeInterface, convert to DateTimeImmutable if ($value instanceof \DateTimeInterface) { return \DateTimeImmutable::createFromInterface($value); } // Try to parse string date if (is_string($value)) { try { return new \DateTimeImmutable($value); } catch (\Exception $e) { // Invalid date format, return null return null; } } // Unsupported type, return null return null; } }