PrestaShop 9.2 : Extra Properties, champs personnalisés natifs via Admin API

Guide pratique pour exploiter les Extra Properties de PrestaShop 9.2 — vérifiez l’OpenAPI, sécurisez les scopes, gérez lecture/écriture, nommage multilang et migration vers relationnel.

Écran d'ordinateur avec l'interface de PrestaShop 9.2 montrant le développement de propriétés supplémentaires.

Table des matières :

  1. Vérifier ce que PrestaShop 9.2 expose vraiment (OpenAPI avant tout)
  2. Sécurité Admin API : scopes, moindre privilège et données à ne pas stocker
  3. Écrire et lire des champs personnalisés via Admin API (patterns robustes, pas de magie)
  4. Modélisation : nommage, types, multilang/multiboutique, et stratégie d’évolution

Les « Extra Properties » de PrestaShop 9.2 visent un problème très concret du core : dès que vous avez besoin d’un champ métier qui n’existe pas (SKU fournisseur, délai de réassort, code douanier/HS, attribut logistique, identifiant PIM…), les options historiques finissent en contournements (Features produits sur‑détournées, tables custom + overrides, surcharge des objets legacy). L’objectif d’Extra Properties est d’offrir un espace de métadonnées natif, consommable par l’Admin API, avec une surface d’extension plus stable que l’override (et plus « contractuelle » quand l’API est correctement décrite).

Dans la pratique, ça se présente comme un conteneur de données additionnelles attaché à une ressource (produit, commande, client… selon ce que votre 9.2 expose réellement). L’API renvoie/consomme un objet clé/valeur (souvent sérialisé en JSON côté persistance) et le cœur garantit au minimum : transport, permissions/scopes, et persistance. En revanche, il ne garantit pas automatiquement le modèle métier (validation fine, indexation, recherche, affichage FO/BO, export, règles). C’est à vous de définir une gouvernance : noms, types, contraintes, visibilité (qui lit/écrit), et stratégie d’index si vous filtrez/tri.

Point important : ce mécanisme n’est pas une alternative universelle à un schéma relationnel. Dès que vos champs deviennent requêtables (filtrer des listings BO/FO, tri, facettes, règles de prix, exports massifs, synchronisations incrémentales), une simple propriété JSON sans index peut vous faire payer l’addition en latence, CPU SQL et complexité d’intégrité. Gardez Extra Properties pour ce que c’est : une extension souple et API-first, pas un EAV sans conséquences.

Petit scénario très courant (contexte FR/UE) : vous vendez en France et expédiez en UE/hors UE. Votre ERP a besoin d’un supplier_sku et d’un lead_time_days, votre WMS d’un hazmat et d’un packaging_type, et votre équipe douane d’un hs_code. Extra Properties vous permet de faire circuler ces informations via Admin API sans modifier immédiatement le schéma produit. Mais si demain vous devez filtrer vos produits « dangereux » ou « délai > 10 jours » dans le BO, ou générer automatiquement des documents douaniers à grande échelle, vous devrez probablement structurer et indexer.

Vérifier ce que PrestaShop 9.2 expose vraiment (OpenAPI avant tout)

Avant d’écrire une ligne de code, partez du contrat. Sur PrestaShop 9.x, l’Admin API est documentée via OpenAPI/Swagger : c’est la source de vérité la plus exploitable quand le core bouge. Appuyez-vous sur l’article interne PrestaShop Admin API : environnement de développement Docker et Swagger pour monter un environnement reproductible et accéder à la spec.

L’idée est simple : ouvrez l’UI Swagger et cherchez le champ (ou propriété) nommé extraProperties, extra_properties ou équivalent. Ensuite, identifiez :

  • les ressources concernées (products, orders, customers…),
  • les méthodes autorisées (GET/POST/PATCH/PUT),
  • le format (objet JSON libre, map typée, tableau…),
  • les contraintes (taille max, types attendus, champs readOnly),
  • les codes d’erreur (400 validation, 403 scope, 409 conflit, etc.),
  • et les règles de sérialisation (nullables, suppression de clé, comportement d’un PATCH partiel).

Tant que vous n’avez pas validé ça dans votre 9.2.x, ne partez pas sur des hypothèses (surtout si vous développez un module destiné à plusieurs marchands, ou si vous avez plusieurs environnements avec des patchs différents).

OpenAPI n’est pas « juste de la doc » : c’est un contrat exploitable par l’outillage (génération de clients, tests contractuels, validation de schéma). La définition officielle résume bien l’intention :

“The OpenAPI Specification (OAS) defines a standard, programming language-agnostic interface description for HTTP APIs.” (OpenAPI Specification 3.1.0, 2021) — https://spec.openapis.org/oas/v3.1.0

Concrètement, pour un usage “pro” d’Extra Properties, vous pouvez vous donner une check-list simple avant d’implémenter :

  • Le champ est-il présent sur la ressource cible (produit/commande/…)?
  • Est-il en lecture seule (utile pour exposer, mais pas pour écrire) ?
  • Quelle est la limite de taille (important si vous êtes tentés d’y stocker des blobs) ?
  • Le PATCH est-il supporté et sous quel media type (application/merge-patch+json par exemple) ?
  • Les erreurs de validation sont-elles explicites (message, path) ?
  • Le comportement de suppression est-il défini (mettre null supprime, ou conserve, ou invalide) ?

Pré-requis & contexte versions : ce qui suit suppose PrestaShop 9.2.x, PHP 8.3 (stack 9.x) et une base MySQL 8 / MariaDB 10.6+ (les fonctions JSON, indexes fonctionnels et colonnes générées ne se comportent pas exactement pareil selon le moteur). Faites vos tests sur un staging fidèle (réseau, cache, volumes, dataset) : voir aussi créer un staging Docker fidèle à la production.

Sécurité Admin API : scopes, moindre privilège et données à ne pas stocker

Extra Properties, c’est de la surface d’écriture en plus. Donc de la surface d’attaque en plus. L’Admin API doit être traitée comme une interface d’admin distante : TLS obligatoire, secrets correctement gérés, rotation, journalisation, et scopes minimaux.

Pour la partie OAuth2, ne vous contentez pas de “ça marche”. Le RFC le rappelle dès l’introduction :

“The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service.” (RFC 6749) — https://www.rfc-editor.org/rfc/rfc6749

Le mot important est limited : vous voulez être capable de dire “cette intégration peut mettre à jour uniquement les propriétés erp.* des produits”, et pas “elle peut tout faire parce que c’était plus rapide”.

Bonnes pratiques concrètes (et faciles à auditer) :

  • Un client OAuth par intégration (ERP, PIM, WMS, BI, connecteur marketplace), jamais un client partagé.
  • Scopes strictement nécessaires à la ressource qui porte vos Extra Properties (produits ≠ commandes).
  • Rotation planifiée (secrets et tokens), et révocation si un prestataire sort du périmètre.
  • Journalisation côté SI : loggez qui écrit quoi (au minimum l’ID ressource + namespace modifié + timestamp + identifiant du client OAuth), pour pouvoir investiguer en cas d’écart.

L’article interne sur l’hygiène des clients et permissions peut vous servir de base : sécuriser secret et scopes par client.

Dernier point souvent négligé : ne stockez pas n’importe quoi dans Extra Properties.

  • Pas de secrets (tokens, clés API, identifiants), même “temporairement”.
  • Pas de payload brut venant d’un webhook externe (risque d’injection de données, volumes non maîtrisés, données inutiles).
  • Données personnelles : évitez. En UE, la minimisation est un principe central du RGPD :

“adequate, relevant and limited to what is necessary in relation to the purposes” (GDPR / Règlement (UE) 2016/679, art. 5(1)(c)) — https://eur-lex.europa.eu/eli/reg/2016/679/oj

Si vous devez tracer un lien externe, stockez plutôt un identifiant opaque (external_id) et conservez le reste dans votre SI (ou une table dédiée, chiffrée/contrôlée, avec rétention). Et si vous avez une démarche outillée (SBOM, WAF, CI/CD, revue supply chain), alignez vos pratiques : sécuriser APIs et modules avec SBOM, WAF et CI/CD.

Écrire et lire des champs personnalisés via Admin API (patterns robustes, pas de magie)

Lecture : récupérer uniquement ce qui est utile

Commencez par un GET de la ressource et inspectez le shape exact (noms, niveaux, casing). Exemple de pattern (à adapter aux routes exactes de votre OpenAPI 9.2) :

TOKEN="…"

curl -sS "$BASE/products/123" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json" \
| jq '.extraProperties // .extra_properties'

Deux réflexes à prendre en lecture :

  1. Tolérer l’absence : sur un parc de produits existants, le conteneur peut être absent ou vide. Votre code doit gérer null, {}, ou un champ non présent.
  2. Stabiliser le mapping : ne parsez pas “au fil de l’eau” dans 5 services différents. Définissez un mapping canonique (ex. erp.supplier_sku string) et réutilisez-le.

Si l’API supporte des sparse fieldsets (ce n’est pas systématique), utilisez-les : sur des produits riches, vous évitez de transférer des blocs inutiles et vous réduisez la variance de latence. À défaut, pour des usages intensifs (export BI, synchronisation PIM), il est souvent plus sain de mettre un middleware (cache, normalisation, quotas) plutôt que de sur‑consommer l’Admin API comme une API publique.

Astuce “terrain” : si vous faites des synchronisations incrémentales, vérifiez dans votre spec si la ressource expose un champ de type updatedAt/modified_at et si des filtres existent. Si ce n’est pas le cas, votre intégration risque de tomber dans le piège du full-scan quotidien (coûteux, et fragile).

Rappelez-vous aussi que JSON n’impose pas de type “date” ou “decimal”. Le standard dit simplement :

“A JSON text is a serialized value.” (RFC 8259) — https://www.rfc-editor.org/rfc/rfc8259

Traduction opérationnelle : si vous avez des types métier (date, monnaie, poids), c’est à vous (ou au core) de les contraindre via schéma/validation côté applicatif.

Écriture : PATCH, merge et collisions

Pour écrire, préférez PATCH quand l’API le propose (notamment application/merge-patch+json) afin d’éviter d’écraser des champs que vous ne maîtrisez pas. Pattern typique :

curl -sS -X PATCH "$BASE/products/123" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/merge-patch+json" \
  -d '{
    "extraProperties": {
      "erp": {
        "supplier_sku": "SUP-99118",
        "lead_time_days": 5,
        "hazmat": false
      }
    }
  }'

Le piège principal, c’est la collision d’écritures : si deux intégrations écrivent dans le même conteneur sans merge serveur profond, vous perdez des données (last write wins). Les mitigations réalistes :

  • (1) Namespacer par intégration ou domaine : erp.*, pim.*, wms.*, logistics.*.
  • (2) Limiter la surface d’édition via scopes (le client “ERP” ne touche pas wms.*).
  • (3) Documenter une règle de merge (ex. merge profond par namespace, interdiction d’écraser un objet racine d’un autre domaine).
  • (4) Éviter les écritures “globales” : n’envoyez pas tout le blob extraProperties si vous ne contrôlez pas 100% de son contenu.

Côté robustesse d’intégration, pensez aussi “réseau réel” :

  • Retries avec backoff sur 429/503 (si l’API rate-limit ou subit un pic).
  • Idempotence logique : si vous rejouez un PATCH après un timeout, est-ce que la valeur finale reste correcte ?
  • Traçabilité : loggez la requête (sans données sensibles), l’ID produit, et la réponse (code, message, request-id si présent).

Enfin, gardez un œil sur les validations côté core : taille maximale du payload, profondeur d’objet autorisée, et champs interdits. Quand vous dépassez ces limites, ne “contournez” pas : c’est un signal que vous utilisez Extra Properties comme un stockage applicatif, ce qui n’est pas le but.

Modélisation : nommage, types, multilang/multiboutique, et stratégie d’évolution

Sur un projet qui vit, la difficulté n’est pas de créer un champ, c’est de le faire durer sans casser les consommateurs. Adoptez un schéma stable : clés en snake_case, namespaces de premier niveau par domaine (erp, pim, logistics), et versionnement implicite si nécessaire (erp.v1.*). Évitez les clés “fonctionnelles” fluctuantes (custom_field_12) : c’est illisible, et ingouvernable.

Discipline de nommage (et pourquoi ça change tout)

  • Clés stables et explicites : hs_code plutôt que custom_1.
  • Unités explicites : lead_time_days plutôt que lead_time.
  • Pas de doublons sémantiques : ne stockez pas à la fois supplier_sku et supplierSku selon les équipes.
  • Owner clair : qui a le droit de modifier la valeur ? (ERP ? PIM ? opérateur BO ?)

Un format simple qui marche bien en équipe : documentez vos Extra Properties dans un tableau (même un fichier Markdown versionné). Exemple :

Clé Type Exemple Source d’autorité Lecture Écriture Notes
erp.supplier_sku string SUP-99118 ERP BO/ERP ERP Stable, utilisé en litige fournisseur
erp.lead_time_days integer 5 ERP BO/FO (si utile) ERP Valider >= 0
logistics.hazmat boolean false WMS BO WMS Sert à choisir un transporteur
customs.hs_code string 610910 Douane/ERP BO ERP Code SH/HS (souvent 6 chiffres)

Même si Extra Properties est “libre”, vous, vous n’êtes pas obligés d’être “libres” : imposez une gouvernance.

Types : cohérence, validation et sérialisation

Pour les types, tenez une discipline stricte :

  • booléens pour les flags (pas "0", pas "false" en string).
  • integers pour les quantités/compteurs (lead_time_days, min_order_qty).
  • numbers (ou strings normalisées) pour les montants : si vous manipulez des prix, préférez une représentation maîtrisée (ex. centimes en integer) plutôt qu’un float.
  • strings ISO pour les dates (YYYY-MM-DD) et datetimes (YYYY-MM-DDTHH:MM:SSZ) si vous n’avez pas de type natif.
  • objets uniquement si vous avez une structure stable (ex. dimensions: { "length_mm": 200, "width_mm": 100 }), sinon vous créez des blobs ingérables.

Si vous avez besoin de validations (ex. lead_time_days >= 0, hs_code regex, longueur max), deux options réalistes :

  • validation côté middleware/SI (contrats, rejets, monitoring),
  • ou validation côté module (si vous contrôlez l’extension et les points d’écriture).

Multilang / multiboutique : décider (et ne pas bricoler)

Extra Properties peut vous tenter pour stocker des contenus multilingues (“un label custom”, “une note interne”). Mais attention : PrestaShop a déjà ses propres mécanismes multilang et multiboutique. Avant de tout mettre en Extra Properties, posez-vous deux questions :

  1. Est-ce vraiment un champ métier “hors core”, ou est-ce une donnée qui devrait vivre dans un champ natif (ex. texte produit, meta, attributs) ?
  2. La donnée varie-t-elle par langue et/ou par boutique ?

Si vous devez quand même le faire, choisissez une convention explicite, par exemple :

{
  "extraProperties": {
    "pim": {
      "short_label": {
        "fr_FR": "T-shirt coton",
        "en_GB": "Cotton T-shirt"
      }
    }
  }
}

Pour la multi‑boutique, évitez les structures opaques du type “un objet de 50 clés par boutique” si vous ne savez pas comment vous allez le maintenir. Dans beaucoup de cas, la meilleure approche est de stocker une valeur globale (commune) dans Extra Properties et de gérer les exceptions multi‑boutique ailleurs (ou dans le PIM), plutôt que d’implémenter un mini‑framework de déclinaisons maison.

Stratégie d’évolution : compatibilité, dépréciation, et sortie vers du relationnel

Le vrai coût arrive quand votre schéma évolue. Quelques règles qui évitent 80% des crises :

  • Ne renommez pas une clé en production si vous avez des consommateurs. Créez une nouvelle clé et migrez progressivement.
  • Versionnez quand nécessaire : erp.v1.supplier_sku puis erp.v2.supplier_sku si le sens change.
  • Documentez la dépréciation : date de fin de support, et comportement (champ présent mais vide ? champ supprimé ?).
  • Évitez les “overloads” : une clé qui change de type (string → objet) casse tout.

Et surtout : prévoyez la “sortie” d’Extra Properties quand un champ devient structurant. Indices typiques que vous devez basculer vers une table/colonne indexée :

  • vous filtrez/tri en BO sur ce champ,
  • vous exportez massivement pour BI/ERP,
  • vous avez besoin d’unicité (ex. SKU fournisseur unique),
  • vous devez faire des jointures (ex. règles de transport/douane).

Ça ne remplace pas un vrai modèle, mais ça peut acheter du temps si vous savez exactement ce que vous faites.

En synthèse : Extra Properties est excellent pour accélérer l’intégration (ERP/PIM/WMS) et limiter les overrides, à condition de traiter le sujet comme un contrat (OpenAPI), de sécuriser comme une admin distante (scopes, minimisation), et de garder une règle simple : dès que ça devient requêtable ou critique, on modélise et on indexe proprement.


À lire aussi