JSON → PHP 8.2+ DTO
Architecture PHP moderne

Générateur de DTOs Typés Readonly en PHP 8.2+ depuis JSON

Convertissez des données JSON en DTOs modernes avec les readonly classes PHP 8.2+, promotion de constructeur et désérialiseurs fromArray.

Préréglages
Payload JSON SourceValide
<?php

declare(strict_types=1);

namespace App\DTO;

/**
 * @param string[] $tags
 */
final readonly class UserDto implements \JsonSerializable
{
    public function __construct(
        public string $id,
        public string $email,
        public string $username,
        public string $displayName,
        public string $role,
        public bool $isActive,
        public TenantDto $tenant,
        public PreferencesDto $preferences,
        /** @var string[] */
        public array $tags = [],
        public \DateTimeImmutable $lastLoginAt,
        public \DateTimeImmutable $createdAt,
    ) {}

    public static function fromArray(array $data): self
    {
        return new self(
            id: (string) ($data['id'] ?? $data['id'] ?? null ?? ''),
            email: (string) ($data['email'] ?? $data['email'] ?? null ?? ''),
            username: (string) ($data['username'] ?? $data['username'] ?? null ?? ''),
            displayName: (string) ($data['display_name'] ?? $data['displayName'] ?? null ?? ''),
            role: (string) ($data['role'] ?? $data['role'] ?? null ?? ''),
            isActive: (bool) ($data['is_active'] ?? $data['isActive'] ?? null ?? false),
            tenant: TenantDto::fromArray((array) ($data['tenant'] ?? [])),
            preferences: PreferencesDto::fromArray((array) ($data['preferences'] ?? [])),
            tags: array_map(fn($item) => (string) $item, (array) ($data['tags'] ?? [])),
            lastLoginAt: isset($data['last_login_at']) ? new \DateTimeImmutable((string) $data['last_login_at']) : null,
            createdAt: isset($data['created_at']) ? new \DateTimeImmutable((string) $data['created_at']) : null,
        );
    }

    public function toArray(): array
    {
        return [
            'id' => $this->id,
            'email' => $this->email,
            'username' => $this->username,
            'display_name' => $this->displayName,
            'role' => $this->role,
            'is_active' => $this->isActive,
            'tenant' => $this->tenant->toArray(),
            'preferences' => $this->preferences->toArray(),
            'tags' => $this->tags,
            'last_login_at' => $this->lastLoginAt?->format(\DateTimeInterface::ATOM),
            'created_at' => $this->createdAt?->format(\DateTimeInterface::ATOM),
        ];
    }

    public function jsonSerialize(): array
    {
        return $this->toArray();
    }
}

final readonly class TenantDto implements \JsonSerializable
{
    public function __construct(
        public string $id,
        public string $name,
        public string $tier,
        public int $activeSeats,
        public string $billingContact,
    ) {}

    public static function fromArray(array $data): self
    {
        return new self(
            id: (string) ($data['id'] ?? $data['id'] ?? null ?? ''),
            name: (string) ($data['name'] ?? $data['name'] ?? null ?? ''),
            tier: (string) ($data['tier'] ?? $data['tier'] ?? null ?? ''),
            activeSeats: (int) ($data['active_seats'] ?? $data['activeSeats'] ?? null ?? 0),
            billingContact: (string) ($data['billing_contact'] ?? $data['billingContact'] ?? null ?? ''),
        );
    }

    public function toArray(): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'tier' => $this->tier,
            'active_seats' => $this->activeSeats,
            'billing_contact' => $this->billingContact,
        ];
    }

    public function jsonSerialize(): array
    {
        return $this->toArray();
    }
}

final readonly class PreferencesDto implements \JsonSerializable
{
    public function __construct(
        public string $theme,
        public bool $notificationsEnabled,
        public string $locale,
        public string $timezone,
    ) {}

    public static function fromArray(array $data): self
    {
        return new self(
            theme: (string) ($data['theme'] ?? $data['theme'] ?? null ?? ''),
            notificationsEnabled: (bool) ($data['notifications_enabled'] ?? $data['notificationsEnabled'] ?? null ?? false),
            locale: (string) ($data['locale'] ?? $data['locale'] ?? null ?? ''),
            timezone: (string) ($data['timezone'] ?? $data['timezone'] ?? null ?? ''),
        );
    }

    public function toArray(): array
    {
        return [
            'theme' => $this->theme,
            'notifications_enabled' => $this->notificationsEnabled,
            'locale' => $this->locale,
            'timezone' => $this->timezone,
        ];
    }

    public function jsonSerialize(): array
    {
        return $this->toArray();
    }
}
3 Classes
Classes DTO Générées
20 Champs
Propriétés Typées
0 ms de latence serveur
Moteur PHP 8.2+ Readonly

Classes Readonly PHP 8.2+ et Promotion de Constructeur

Tirez parti des classes readonly modernes de PHP 8.2 avec promotion de propriétés dans le constructeur et immuabilité totale pour une robustesse maximale.

Confidentialité 100% Côté Client

L'analyse JSON, la déduction d'AST et la génération de code PHP s'exécutent intégralement dans votre navigateur sans aucune transmission réseau.

Sérialisation et Désérialisation Bidirectionnelle

Génère des méthodes statiques fromArray() avec hydratation récursive des sous-DTOs, ainsi que toArray() et l'interface JsonSerializable.

Référence technique et guide d'architecture

Guide Développeur : Générateur de DTOs Typés Readonly en PHP 8.2+ depuis JSON — Guide de référence

Convertissez des données JSON en DTOs modernes avec les readonly classes PHP 8.2+, promotion de constructeur et désérialiseurs fromArray.

Paramètres clés et contrôles

Root Class NameString (Identifiant PHP)

Identifiant de la classe de premier niveau générée pour l'objet JSON racine.

Par défaut : RootDto
NamespaceString (Namespace PHP)

Déclaration d'espace de noms conforme à la norme PSR-4 ajoutée aux classes DTO générées.

Par défaut : App\DTO
PHP Target VersionEnum ('8.2+', '8.1', '8.0')

Syntaxe PHP ciblée ; 8.2+ génère des readonly classes avec promotion des propriétés de constructeur.

Par défaut : 8.2+
Constructor PromotionBoolean

Déclare et assigne les propriétés typées directement dans la liste des arguments de __construct().

Par défaut : true
Deserializer Hydration (fromArray)Boolean

Génère une méthode de fabrique statique typée fromArray(array $data): self avec hydratation récursive des sous-DTOs.

Par défaut : true
Property CasingEnum ('camelCase', 'snake_case', 'preserve')

Normalise les clés JSON en identifiants camelCase idiomatiques en PHP tout en conservant le mappage d'origine.

Par défaut : camelCase
DateTime DetectionBoolean

Détecte les chaînes d'horodatage ISO 8601 et les type automatiquement sous forme de propriétés \DateTimeImmutable.

Par défaut : true

Conseils de pro et bonnes practices

Hydratation Récursive des DTOs Imbriqués

Lors du traitement de structures JSON imbriquées ou de listes de sous-objets, utilisez array_map() dans fromArray() pour invoquer récursivement les fabriques statiques des DTOs enfants en toute sécurité face aux valeurs nulles.

En PHP 8.2+

En PHP 8.2+, déclarer une readonly class applique automatiquement le modificateur readonly à l'ensemble des propriétés d'instance, empêchant toute mutation indésirable et renforçant la sémantique de Value Object.

Pour les collections JSON contenant

Pour les collections JSON contenant des valeurs nulles ou des scalaires mixtes, exploitez les types d'union de PHP 8.0+ (ex. string|int|null) et les annotations PHPDoc (/** @var list<UserDto> */) pour valider l'analyse statique au Niveau 8+ de PHPStan et Psalm.

Découplage par Attributs de Framework

Associez la promotion de constructeur aux attributs Symfony #[SerializedName('cle')] ou Spatie #[MapInputName] pour séparer rigoureusement les contrats API externes de vos modèles de domaine internes.

Pièges courants et dépannage

Erreur fatale à l'exécution 'Cannot modify readonly property'

Les propriétés readonly de PHP 8.2 ne peuvent plus être modifiées après l'exécution du constructeur. Utilisez des méthodes d'altération par clonage immuable (withers) ou transmettez l'ensemble des valeurs lors de l'instanciation via fromArray().

Échec de déballage de tableaux associatifs imbriqués dans le constructeur

Ne passez jamais directement des tableaux associatifs bruts aux paramètres typés d'objets enfants ; transitez obligatoirement par la méthode de fabrique fromArray() de la classe correspondante.

Exception DateMalformedStringException lors du parsing de dates en PHP 8.3+

Validez le format de la chaîne de date avant d'instancier un nouvel objet \DateTimeImmutable(), ou encapsulez l'opération dans un bloc try-catch avec repli sur un type nullable ?\DateTimeImmutable.

Foire aux questions (FAQ)

Quels sont les atouts des classes readonly de PHP 8.2 pour les DTOs ?▼

Elles interdisent formellement toute modification des propriétés après instanciation ainsi que la création de propriétés dynamiques. Cela offre une immuabilité absolue, une sécurité d'exécution multithread (Swoole, RoadRunner) et supprime le besoin de copies défensives.

Comment la promotion de constructeur élimine-t-elle le code répétitif (boilerplate) ?▼

Au lieu de déclarer séparément les propriétés, les paramètres du constructeur et les affectations ($this->prop = $prop), la promotion regroupe visibilité, type, immuabilité et valeurs par défaut dans une seule signature __construct(), réduisant le code de plus de 60%.

Peut-on générer des DTOs compatibles avec Symfony Serializer ou Spatie Laravel Data ?▼

Oui. Vous pouvez activer l'exportation des attributs natifs tels que #[SerializedName] de Symfony ou #[MapInputName] de Spatie Data afin d'assurer une correspondance sans couture entre les charges utiles JSON en snake_case et les objets PHP en camelCase.

Comment fromArray() gère-t-il les champs JSON manquants ou nuls ?▼

Le générateur analyse l'échantillon JSON pour identifier les clés manquantes ou nulles, assignant des types nullables (?string $champ = null) et l'opérateur de coalescence null ($data['champ'] ?? null) pour écarter tout avertissement de clé indéfinie.

Les données JSON sont-elles envoyées à un serveur externe durant la génération ?▼

Non. L'analyse syntaxique du JSON, la déduction d'arbre AST et la génération du code PHP s'exécutent intégralement au sein de votre navigateur via JavaScript, assurant une confidentialité absolue et zéro transmission réseau.

Outils et utilitaires connexes

Tous les outils →