Position actuelle: Accueil> Derniers articles> Écrivez une classe d'outils de gestion du format de données package () qui prend en charge la version compatible

Écrivez une classe d'outils de gestion du format de données package () qui prend en charge la version compatible

M66 2025-06-04

Dans le développement de PHP, la fonction Pack () est souvent utilisée pour emballer les données dans des chaînes binaires et est largement utilisée dans des scénarios tels que la communication réseau, le stockage de fichiers et les structures de données chiffrées. Cependant, à mesure que les itérations du projet, les formats de données de différentes versions peuvent changer, entraînant un déballage de défaillances ou d'erreurs d'analyse de données. Pour résoudre ce problème, nous pouvons créer une classe d'outils PackFormatManager qui prend en charge la compatibilité des versions, gérer uniformément les définitions de format pack () de chaque version et obtenir une compatibilité arrière entre l'emballage de données et le déballage.

1. Analyse des antécédents des exigences

Supposons que nous ayons une structure de données binaires, et chaque champ a un format de codage fixe, tel que des entiers, des numéros de points flottants, des chaînes, etc. Au début du projet, nous n'avons pu utiliser que deux champs:

  • user_id (entier de 4 octets)

  • horodatage (entier de 4 octets)

À mesure que le système améliore, nous ajoutons des champs tels que:

  • Version 2: Ajout d'un user_type (1 octet)

  • Version 3: IS_ACTIVE (valeur booléenne de 1 octet)

Chaque fois que la version est mise à niveau, nous nous attendons à ce que les données de l'ancienne version soient toujours correctement identifiées et traitées sans lancer des exceptions ou lire des erreurs.

2. Objectifs de conception des outils

Nous voulons implémenter une classe PackFormatManager , qui a les fonctions suivantes:

  1. Prend en charge la définition du format d'emballage multi-version;

  2. La version de données peut être automatiquement identifiée et déballée;

  3. Fournir une interface unifiée pour les opérations d'emballage et de déballage;

  4. Fournit une compatibilité arrière et une évolutivité des données;

  5. Les nouveaux champs extensibles n'affectent pas le traitement des anciennes données de version.

3. Implémentation du code

 <?php

class PackFormatManager
{
    private $formats = [];

    public function __construct()
    {
        $this->registerDefaultFormats();
    }

    private function registerDefaultFormats()
    {
        $this->formats = [
            1 => [
                'format' => 'Luser_id/Ltimestamp',
                'fields' => ['user_id', 'timestamp'],
            ],
            2 => [
                'format' => 'Luser_id/Ltimestamp/Cuser_type',
                'fields' => ['user_id', 'timestamp', 'user_type'],
            ],
            3 => [
                'format' => 'Luser_id/Ltimestamp/Cuser_type/Cis_active',
                'fields' => ['user_id', 'timestamp', 'user_type', 'is_active'],
            ],
        ];
    }

    public function pack(array $data, int $version): string
    {
        if (!isset($this->formats[$version])) {
            throw new InvalidArgumentException("Unsupported format version: $version");
        }

        $format = $this->formats[$version]['format'];
        $values = [];

        foreach ($this->formats[$version]['fields'] as $field) {
            $values[] = $data[$field] ?? 0;
        }

        // Ajouter l&#39;en-tête du numéro de version (1 octet)
        return pack('C', $version) . pack($format, ...$values);
    }

    public function unpack(string $binary): array
    {
        // Présent d&#39;abord le numéro de version
        $version = unpack('Cversion', $binary)['version'];

        if (!isset($this->formats[$version])) {
            throw new InvalidArgumentException("Unsupported format version: $version");
        }

        $format = $this->formats[$version]['format'];
        $fields = $this->formats[$version]['fields'];

        // Supprimer l&#39;en-tête de la version et le déballer
        $data = unpack($format, substr($binary, 1));

        return array_merge(['version' => $version], $data);
    }

    public function getSupportedVersions(): array
    {
        return array_keys($this->formats);
    }
}

4. Utiliser des exemples

 $manager = new PackFormatManager();

$data = [
    'user_id' => 1001,
    'timestamp' => time(),
    'user_type' => 2,
    'is_active' => 1,
];

$packed = $manager->pack($data, 3);
echo "Packed binary: " . bin2hex($packed) . PHP_EOL;

$unpacked = $manager->unpack($packed);
print_r($unpacked);

5. Suggestions de traitement de l'extension et de compatibilité des versions

Lorsque vous souhaitez ajouter un nouveau champ, ajoutez simplement une définition de format à la nouvelle version. Les versions plus anciennes peuvent toujours être correctement identifiées et traitées. Par exemple:

 $this->formats[4] = [
    'format' => 'Luser_id/Ltimestamp/Cuser_type/Cis_active/Llogin_count',
    'fields' => ['user_id', 'timestamp', 'user_type', 'is_active', 'login_count'],
];

Pour maintenir une bonne compatibilité, vous pouvez également héberger le document de description du champ dans une adresse telle que <code> https://m66.net/docs/pack-forat-v4.json </code>, permettant au client de charger et de vérifier dynamiquement le format de champ.

6. Résumé

En encapsulant la logique de gestion du format package () , nous implémentons une classe d'outils de gestion des emballages compatibles flexibles, extensibles et vers l'arrière. Il améliore non seulement la maintenabilité du code, mais fournit également une base solide pour les mises à niveau du système et la persistance des données. Ce modèle est particulièrement important dans la conception d'une interaction multi-terminaux, de la communication réseau et du flux de données de fichiers, et il est recommandé d'être largement utilisé dans les projets PHP moyens et grands.