Ajouter un champ personnalisé aux fiches produits PrestaShop
Guide complet pour créer un champ custom dans PrestaShop : modification base de données, override de classe Product, back-office et template Smarty.
En bref : Pour ajouter un champ personnalisé aux produits PrestaShop, il faut intervenir à quatre niveaux : colonne SQL dans ps_product_lang, override de la classe Product (ObjectModel), intégration au formulaire back-office, et affichage front-office via Smarty. En PS 8.x, préférez un module avec hooks Symfony.
Pourquoi ajouter un champ personnalisé à vos produits
Le catalogue PrestaShop couvre la majorité des besoins e-commerce standard, mais certains secteurs exigent des informations spécifiques : date limite de consommation (DLC) pour l'alimentaire, numéro d'homologation pour l'automobile, indice de protection pour l'électronique, ou encore dosage pour la parapharmacie.
Plutôt que de détourner un champ existant (comme la description courte), la bonne pratique consiste à étendre proprement le modèle Product via le système d'override et la couche ObjectModel de PrestaShop.
Ce guide vous accompagne à travers les quatre étapes nécessaires : modification de la base de données, override de la classe Product, intégration au back-office, et affichage en front-office.
Étape 1 — Ajouter la colonne en base de données
Le champ doit d'abord exister physiquement dans la table correspondante. Pour un champ multilingue (traduisible), c'est la table ps_product_lang qui est concernée. Pour un champ non traduit, ce serait ps_product.
Champ multilingue (dans `ps_product_lang`)
ALTER TABLE `ps_product_lang`
ADD COLUMN `product_dlc` TEXT DEFAULT NULL
AFTER `description_short`;
Champ non multilingue (dans `ps_product`)
ALTER TABLE `ps_product`
ADD COLUMN `product_dlc` VARCHAR(255) DEFAULT NULL
AFTER `reference`;
Bonne pratique : choisissez le type SQL adapté à votre donnée. Un
TEXTconvient pour du contenu riche (HTML autorisé), unVARCHAR(255)pour une valeur courte, unDATEpour une date stricte. Évitez leTEXTsi un type plus restrictif suffit — cela améliore les performances d'indexation.
Attention au préfixe : remplacez
ps_par le préfixe réel de votre installation si vous l'avez personnalisé.
Étape 2 — Override de la classe Product
PrestaShop utilise le pattern ObjectModel : chaque propriété publique déclarée dans la définition du modèle est automatiquement mappée à la base de données. Il faut donc informer l'ORM de l'existence du nouveau champ.
Créez le fichier override/classes/Product.php :
<?php
/**
* Override de la classe Product
* Ajout du champ personnalisé product_dlc
*/
class Product extends ProductCore
{
/** @var string Champ personnalisé — ex : Date Limite de Consommation */
public $product_dlc;
public function __construct(
$id_product = null,
$full = false,
$id_lang = null,
$id_shop = null,
Context $context = null
) {
// Déclaration du champ AVANT l'appel au constructeur parent
self::$definition['fields']['product_dlc'] = [
'type' => self::TYPE_HTML,
'lang' => true,
'validate' => 'isCleanHtml',
'size' => 65535,
];
parent::__construct($id_product, $full, $id_lang, $id_shop, $context);
}
}
Points techniques importants
- **`self::$definition` vs `parent::$definition`** : les deux fonctionnent, mais `self::$definition` est plus explicite. La propriété `$definition` est statique et partagée.
- **`lang => true`** : indique à l'ORM que le champ est multilingue (stocké dans `ps_product_lang`). Si votre champ est dans `ps_product`, mettez `false`.
- **`validate => 'isCleanHtml'`** : plus sécurisé que `isString` car il filtre les balises dangereuses (XSS). Utilisez `isString` uniquement pour du texte brut sans HTML.
- **`type => self::TYPE_HTML`** : autorise le contenu HTML. Alternatives : `TYPE_STRING`, `TYPE_INT`, `TYPE_FLOAT`, `TYPE_DATE`, `TYPE_BOOL`.
Vider le cache des classes
Après avoir créé l'override, supprimez impérativement le fichier de cache :
rm -f var/cache/prod/class_index.php
rm -f var/cache/dev/class_index.php
# PrestaShop 1.6 :
rm -f cache/class_index.php
Sans cette étape, PrestaShop continuera d'utiliser la classe originale et votre champ sera ignoré silencieusement.
Étape 3 — Intégrer le champ au back-office
L'approche diffère selon la version de PrestaShop.
PrestaShop 1.6 — Override du template admin
Dans PrestaShop 1.6, la fiche produit utilise des templates Smarty. Créez un override du template information.tpl :
override/controllers/admin/templates/products/information.tpl
Copiez le contenu original depuis controllers/admin/templates/products/information.tpl et ajoutez votre champ dans le formulaire :
<div class="form-group">
<label class="control-label col-lg-3">
{l s='DLC / Date limite'}
</label>
<div class="col-lg-9">
{foreach from=$languages item=language}
<div class="translatable-field lang-{$language.id_lang}"
{if $language.id_lang != $default_language}style="display:none"{/if}>
<div class="col-lg-9">
<textarea name="product_dlc_{$language.id_lang}"
class="autoload_rte"
id="product_dlc_{$language.id_lang}">{$product->product_dlc[$language.id_lang]|escape:'html':'UTF-8'}</textarea>
</div>
<div class="col-lg-2">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
{$language.iso_code} <span class="caret"></span>
</button>
<ul class="dropdown-menu">
{foreach from=$languages item=lang}
<li><a href="javascript:hideOtherLanguage({$lang.id_lang});">{$lang.name}</a></li>
{/foreach}
</ul>
</div>
</div>
{/foreach}
</div>
</div>
PrestaShop 1.7 / 8.x — Hook et FormBuilder
À partir de la version 1.7, PrestaShop utilise Symfony et le système de hooks pour étendre le formulaire produit. La méthode recommandée est de créer un module qui se greffe sur les hooks appropriés :
// Dans votre module
public function hookActionProductFormBuilderModifier(array $params): void
{
/** @var \Symfony\Component\Form\FormBuilderInterface $formBuilder */
$formBuilder = $params['form_builder'];
$productId = (int) $params['id'];
$formBuilder->add('product_dlc', TranslateType::class, [
'label' => $this->trans('DLC / Date limite', [], 'Modules.Votremodule.Admin'),
'type' => FormattedTextareaType::class,
'locales' => $this->get('prestashop.adapter.legacy.context')->getLanguages(),
'required' => false,
]);
// Pré-remplir avec les valeurs existantes
$product = new Product($productId);
$params['data']['product_dlc'] = $product->product_dlc;
$formBuilder->setData($params['data']);
}
public function hookActionAfterUpdateProductFormHandler(array $params): void
{
$productId = (int) $params['id'];
$formData = $params['form_data'];
$product = new Product($productId);
$product->product_dlc = $formData['product_dlc'] ?? [];
$product->save();
}
PrestaShop 8.x : la nouvelle page produit utilise des hooks différents. Vérifiez la documentation officielle pour
actionProductFormBuilderModifierqui reste compatible, mais le rendu visuel peut nécessiter des ajustements.
Étape 4 — Afficher le champ en front-office
Une fois le champ sauvegardé, il faut l'exposer dans le template de la fiche produit.
Rendre la variable disponible dans Smarty
Pour PrestaShop 1.6, le champ est automatiquement accessible via {$product->product_dlc} dans le template product.tpl.
Pour PrestaShop 1.7+, créez un override du ProductController ou utilisez le hook actionFrontControllerSetMedia pour ajouter la variable :
public function hookActionFrontControllerSetMedia(array $params): void
{
// Le champ est déjà dans l'objet Product grâce à l'override de classe
// Il sera accessible via {$product.product_dlc} dans les templates
}
Ou plus directement, overridez ProductController::assignAttributesGroups() pour ajouter la variable au template.
Template Smarty (front-office)
{* PrestaShop 1.6 *}
{if isset($product->product_dlc) && $product->product_dlc}
<div class="product-dlc">
<h3>{l s='Informations complémentaires'}</h3>
<div class="dlc-content">{$product->product_dlc}</div>
</div>
{/if}
{* PrestaShop 1.7 / 8.x *}
{if isset($product.product_dlc) && $product.product_dlc}
<div class="product-dlc">
<h3>{l s='Informations complémentaires' d='Shop.Theme.Catalog'}</h3>
<div class="dlc-content">{$product.product_dlc nofilter}</div>
</div>
{/if}
Sécurité : le filtre
nofilterest nécessaire pour le HTML, mais assurez-vous que la validationisCleanHtmlest bien en place côté ObjectModel pour éviter les injections XSS.
Erreurs fréquentes à éviter
Confondre les formats de fichier
Attention à ne pas confondre les extensions et formats : .csv (fichier de données tabulaires), .css (feuille de style) et .tpl (template Smarty) ont des rôles très différents. Une erreur de nommage peut entraîner des heures de débogage inutile.
Oublier le cache des classes
C'est l'erreur numéro un. Votre override est parfait mais ne fonctionne pas ? Le fichier class_index.php n'a pas été régénéré. Supprimez-le systématiquement après chaque modification d'override.
Modifier le core au lieu d'utiliser les overrides
Ne modifiez jamais directement classes/Product.php ou les fichiers dans controllers/admin/. Chaque mise à jour de PrestaShop écraserait vos modifications. Les overrides (ou mieux, un module dédié) survivent aux mises à jour.
Ne pas sauvegarder avant de modifier la base
Avant tout ALTER TABLE, faites un dump :
mysqldump -u root -p prestashop ps_product_lang > backup_product_lang.sql
Approche recommandée en 2024+ : le module dédié
Si les overrides fonctionnent, la meilleure pratique pour PrestaShop 1.7 et 8.x est d'encapsuler toute cette logique dans un module. Avantages :
- **Portabilité** : installation/désinstallation propre via le back-office
- **Mise à jour** : les hooks sont plus pérennes que les overrides
- **Multi-champs** : un seul module peut gérer N champs personnalisés
- **Réversibilité** : la méthode `uninstall()` peut nettoyer la base
Le module gère alors les quatre étapes (SQL, ObjectModel, formulaire BO, affichage FO) dans un package autonome et maintenable.
Questions fréquentes
Tout ce que vous devez savoir sur ce sujet.
Un projet PrestaShop ?
Discutons-en directement.
193 projets livrés
Lire sur le blog

Alexandre Carette
Expert PrestaShop & Architecture E-commerce
Développeur PrestaShop depuis 2014, 193 projets livrés. Je conçois des architectures headless Nuxt + PrestaShop et des outils d'automatisation IA pour les e-commerçants.