Table des matières :
- Compatibilité PHP 8.1–8.5 avec PrestaShop 9.1 : ce que “supporté” veut dire côté code et dépendances
- Dépréciations et ruptures PHP 8.1+ qui cassent typiquement des modules PrestaShop
- CLI sur PrestaShop 9.1 : exécuter, diagnostiquer et industrialiser sans effets de bord
- Nouveautés développeurs à cadrer en 9.1 : dépendances, BC breaks, perf et trajectoire 9.x
Compatibilité PHP 8.1–8.5 avec PrestaShop 9.1 : ce que “supporté” veut dire côté code et dépendances
La compatibilité PHP d’un PrestaShop 9.1 ne se résume pas à « ça s’installe » sur un runtime donné. Dans la pratique, la plage PHP réellement exploitable est l’intersection de (1) la contrainte php déclarée par le cœur (Composer), (2) les contraintes des dépendances Symfony/Doctrine/Twig, (3) les extensions PHP présentes (intl, gd, curl, mbstring, zip, sodium…), et (4) votre code (modules, overrides, thèmes) qui peut exploiter des comportements retirés ou dépréciés.
Autrement dit, “supporté” côté projet peut vouloir dire :
- Le cœur fonctionne sur une version de PHP (installation + BO/FO + parcours clés).
- Les dépendances déclarées (via
composer.json/composer.lock) acceptent cette version. - Votre production (extensions PHP, configuration, et modules tiers) ne génère pas une cascade de dépréciations/erreurs.
- Votre organisation a les moyens de maintenir cette version (patchs de sécurité, image Docker, repo APT, compatibilité infra).
C’est particulièrement important en contexte e-commerce : de nombreux prestataires (paiement, fraude, ERP/CRM) conditionnent la stabilité des intégrations à un environnement maintenu. Un repère objectif est le cycle de vie PHP publié officiellement (support actif + support sécurité), utile pour arbitrer “on vise 8.1” vs “on investit pour 8.4/8.5” : versions supportées PHP (php.net)
Le point dur, c’est que PrestaShop traîne encore un volume significatif de legacy (classes historiques, patterns non typés, surcharge via overrides). Or, PHP 8.1+ durcit progressivement les règles, surtout autour des propriétés dynamiques, du typage implicite et de certains comportements silencieux. L’effet “ça marchait en 8.0” peut donc se transformer en avalanche de dépréciations en 8.2, puis en erreurs fatales dans une version ultérieure si vous laissez les warnings s’installer.
Un autre angle “terrain” (souvent sous-estimé) : la divergence CLI vs FPM. Sur beaucoup de stacks Linux (Debian/Ubuntu — très fréquentes chez des hébergeurs européens), php -v (CLI) peut pointer vers une version différente de celle de PHP-FPM/Apache, et les modules chargés (php -m) peuvent diverger. Résultat : une installation “OK” en HTTP mais des imports CLI qui échouent, ou l’inverse.
Le minimum côté audit, avant même de parler de PHP 8.5 :
- Vérifier la contrainte PHP du projet (dans le
composer.jsondu cœur si vous l’avez en dépôt, ou via la release officielle), puis exécutercomposer check-platform-reqspour confronter runtime et exigences. - Cartographier vos modules : lesquels embarquent leurs propres dépendances Composer, lesquels patchent des classes PrestaShop via override, lesquels appellent des API PHP “fragiles” (ctype/intl, mbstring, libxml, DOM, GD).
- Fixer une matrice de tests explicite PHP 8.1 → 8.5 (CI), au lieu de faire un upgrade “big bang”. La plage 8.1–8.5 implique de traiter les dépréciations comme de la dette qui doit être remboursée, sinon vous bloquez le prochain saut de runtime.
Deux commandes très concrètes (et rapides) à ajouter à votre routine d’audit quand un “pourquoi ça ne passe pas sur PHP 8.3/8.4 ?” arrive :
- Diagnostiquer un blocage de dépendances :
composer why-not php 8.4(ou 8.5) pour identifier le package qui empêche la montée.- Lister les extensions manquantes côté runtime :
composer check-platform-reqs(et côté OS :php -m/php --ini).
“Dynamic properties are deprecated, unless the class opts in by using the #[\AllowDynamicProperties] attribute.” — PHP Manual, Migration 8.2 (php.net)
Dans un écosystème comme PrestaShop, où beaucoup de modules ont historiquement “injecté” des propriétés à la volée ($this->foo = ...), cette seule ligne explique une grosse partie des logs en 8.2 et des comportements instables en production (surtout si vous transformez les dépréciations en exceptions via votre gestionnaire d’erreurs).
Enfin, un conseil pragmatique : distinguez “compatible” et “acceptable en prod”. Vous pouvez réussir une montée PHP techniquement, tout en gardant des milliers de E_DEPRECATED/jour (typiquement sur des boutiques à fort trafic). Même si “ça vend”, vous vous privez d’un signal précieux, et vous augmentez le risque qu’une future version transforme ces dépréciations en erreur fatale.
Dépréciations et ruptures PHP 8.1+ qui cassent typiquement des modules PrestaShop
Le cas le plus fréquent en migration 8.1/8.2 n’est pas un bug “métier”, mais un écart entre vos patterns legacy et la direction de PHP : typage plus strict, objets plus “fermés”, erreurs plus bruyantes. En modules PrestaShop, ça se matérialise souvent par des classes qui stockent des données temporaires en propriétés non déclarées (propriétés dynamiques), des callbacks avec signatures incompatibles, ou des décorateurs autour de classes natives/SPL dont les signatures changent.
Typiquement, vous voyez apparaître (en logs) des familles de problèmes :
- Propriétés dynamiques : un module assigne
$this->contextFoo = ...sans déclaration préalable. Sur PHP 8.2+, cela déclenche une dépréciation ; dans certains environnements (qui transforment les dépréciations en exceptions), ça casse le front/back-office. - Signatures incompatibles : une classe qui implémente une interface SPL (ou hérite d’une classe interne) sans respecter les types/retours attendus devient plus fragile à mesure que PHP ajoute des informations de types.
- Comparaisons/typage implicite : certains cas limites (null, chaînes numériques, etc.) qui passaient “silencieusement” peuvent maintenant générer des warnings plus explicites, puis des erreurs selon le contexte.
Sur PHP 8.1, plusieurs changements augmentent la probabilité d’exceptions à l’exécution (au lieu de simples warnings) selon les extensions. Même si le détail dépend du module, il faut systématiquement lire les notes de migration officielles et lister les points qui touchent votre code (intl, PDO, libxml, GD, curl). Point de méthode : partez de vos “hot paths” (checkout, search, import, génération PDF, webhooks) et instrumentez les logs d’erreurs PHP avant le basculement.
Un exemple très réaliste côté PrestaShop : un module de personnalisation panier, qui attache “à la volée” un état temporaire sur un objet (ex. Cart ou un service) pendant le cycle de requête. En PHP 8.2, la dépréciation se déclenche ; si votre boutique est configurée pour remonter les erreurs (ou si un middleware convertit les erreurs en exceptions), vous obtenez un échec aléatoire en tunnel.
Une correction “propre” (au lieu d’un pansement) ressemble souvent à :
- déclarer la propriété explicitement (si c’est réellement un état d’objet),
- ou stocker l’état dans une structure dédiée (tableau interne, cache, service).
Exemple minimal (principe) :
final class FooService
{
/** @var array<string, mixed> */
private array $state = [];
public function set(string $key, mixed $value): void
{
$this->state[$key] = $value;
}
public function get(string $key, mixed $default = null): mixed
{
return $this->state[$key] ?? $default;
}
}
Cela a un autre avantage : vous rendez l’état testable (et donc compatible CI), au lieu de dépendre de propriétés “magiques”.
“The Console component eases the creation of beautiful and testable command line interfaces.” — Symfony Docs
Cette phrase n’est pas anodine côté PrestaShop : plus vous déportez vos traitements lourds vers des commandes CLI (imports, resync, purge cache, jobs), moins vous subissez les limites du FPM (timeouts, memory_limit agressif, concurrence). Et plus vous pouvez tester sur une matrice PHP 8.1–8.5 de manière déterministe.
Pour traiter proprement les dépréciations sans “masquer” le problème :
- Interdire les propriétés dynamiques dans votre code module (déclarez les propriétés, ou utilisez un tableau interne). L’attribut
#[AllowDynamicProperties]est un pansement acceptable en court terme, mais c’est un choix de dette technique. - Rendre explicites les types de retour dans vos classes qui implémentent des interfaces PHP/SPL (IteratorAggregate, ArrayAccess…), car PHP ajoute/renforce des signatures au fil des versions.
- Automatiser : exécutez PHPUnit + un analyseur statique (PHPStan/Psalm) + un refactorer (Rector) sur chaque version de PHP ciblée. Rector sait, par exemple, remplacer des patterns obsolètes ou ajouter des types lorsque c’est safe.
Pour que “dépréciation” ne rime pas avec “on ne la voit jamais”, une pratique qui marche bien en staging est de séparer les canaux :
- garder
log_errors=1partout, - logger
E_DEPRECATED/E_USER_DEPRECATED(au minimum) dans un fichier dédié, - et monitorer le volume (même un simple compteur/jour par module est déjà utile).
Cela évite l’effet “on noie tout dans error.log” et rend l’assainissement priorisable.
Exemple d’un job CI minimal (GitHub Actions) pour votre module, orienté compatibilité 8.1–8.5. L’idée : vous validez le code sans devoir installer PrestaShop complet à chaque run (tests unitaires + lint + statique), puis vous ajoutez une job d’intégration si nécessaire.
name: php-compat
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
php: ['8.1', '8.2', '8.3', '8.4']
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
coverage: none
- run: composer install --no-interaction --prefer-dist
- run: vendor/bin/phpunit
- run: vendor/bin/phpstan analyse -l 6 src/
Pour PHP 8.5, si vous le visez dès maintenant, faites-le en job séparé (nightly/RC) et acceptez que ce soit un “canary” : l’objectif n’est pas de bloquer les merges, mais d’obtenir un signal précoce sur des BC breaks du langage (référez-vous au fichier UPGRADING de php-src).
Une bonne règle de décision pour ne pas transformer la CI en “bruit” : si 8.5 échoue, on ouvre une issue et on étiquette “compat” (mais on ne bloque pas la livraison), tant que la version n’est pas celle réellement visée en prod.
CLI sur PrestaShop 9.1 : exécuter, diagnostiquer et industrialiser sans effets de bord
PrestaShop 9.x s’appuie toujours sur un socle Symfony, et donc sur un point d’entrée CLI de type bin/console. Ce n’est pas un gadget : c’est votre voie la plus propre pour exécuter des traitements non-interactifs avec des codes de retour exploitables (supervision), des logs, et un environnement isolé (prod vs dev). En production, c’est aussi le moyen de contourner les limites structurelles des actions “back-office” déclenchées via HTTP.
En pratique, le piège n°1 n’est pas la commande, c’est le contexte d’exécution : utilisateur système, droits d’écriture sur var/, configuration OPcache, variables d’environnement, et configuration PHP CLI différente de PHP-FPM. Pour éviter les surprises :
- Forcez explicitement l’environnement :
APP_ENV=prod APP_DEBUG=0 php bin/console …. - Sur des commandes gourmandes (imports, rebuild index), fixez
memory_limitau niveau CLI :php -d memory_limit=1024M bin/console …. - Faites attention aux permissions de cache/logs : lancer la CLI en
rootpeut “verrouiller” les répertoires pour FPM ensuite.
Ajoutez aussi un réflexe “diagnostic” (très utile quand vous êtes sur des environnements infogérés ou mutualisés) :
- Vérifier quel binaire est réellement utilisé :
which phppuisphp -v- Vérifier quels fichiers ini sont chargés :
php --ini- Vérifier rapidement les extensions critiques :
php -m | egrep 'intl|mbstring|gd|curl|zip|sodium'
Cela vous évite de perdre du temps à débugger “PrestaShop” alors que le problème est un simple écart de configuration entre SAPI.
La valeur ajoutée côté dev, c’est la possibilité d’embarquer des commandes dans vos modules plutôt que d’empiler des endpoints “cron”. Exemple minimal (PrestaShop 9.1, PHP 8.1+), en supposant que votre module charge des services Symfony.
src/Command/ReindexFooCommand.php :
<?php
declare(strict_types=1);
namespace Vendor\Module\Command;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
#[AsCommand(name: 'vendor:module:reindex-foo', description: 'Reindexation Foo (idempotente)')]
final class ReindexFooCommand extends Command
{
protected function execute(InputInterface $input, OutputInterface $output): int
{
// 1) lock (éviter la concurrence)
// 2) batch par 500/1000 (éviter OOM)
// 3) logs structurés
$output->writeln('OK');
return Command::SUCCESS;
}
}
Le cœur de PrestaShop ne vous donnera pas “gratuitement” les patterns DevOps (verrous, retries, métriques). Si vous voulez une exécution robuste, imposez-les : lock (flock/Redis), idempotence, batch, et journalisation. Ensuite, branchez vos commandes sur systemd timers / cron, et surveillez les codes de sortie.
Checklist “industrialisation” (courte, mais efficace) pour une commande de module :
- Idempotence : si la commande est relancée, elle ne corrompt pas l’état (ou sait reprendre).
- Verrou : empêcher 2 exécutions simultanées (cron doublé, déploiement, opérateur).
- Pagination/batch : ne jamais charger “tout” en mémoire (produits, clients, commandes).
- Timeouts contrôlés : surtout si la commande appelle des API (ERP, transporteur).
- Sortie process :
0si OK, non-zéro si KO (pour supervision). - Logs actionnables : un identifiant de run + compteurs (ex.
processed,failed).
Côté “effets de bord”, un piège fréquent : une commande qui réchauffe le cache ou reconstruit des fichiers (templates, assets, exports) doit s’exécuter avec le même user (ou groupe) que FPM, sinon vous créez un incident différé (“le site marchait, puis plus rien après le cron”). En pratique, sur beaucoup d’installations, exécuter en www-data (ou l’utilisateur dédié) est plus sûr que root.
Nouveautés développeurs à cadrer en 9.1 : dépendances, BC breaks, perf et trajectoire 9.x
Sur une 9.1, le vrai sujet n’est pas une feature “magique”, mais le durcissement du contrat entre le cœur et votre code : types plus stricts, dépendances Symfony/Doctrine plus récentes, et moins de tolérance aux comportements implicites. Concrètement, votre process doit intégrer une étape de diff technique entre 9.0 et 9.1 : comparer composer.lock, scanner les classes du cœur que vous étendez/surchargez, et identifier les points d’extension officiels (hooks, services, événements) qui remplacent des overrides “à l’ancienne”. Les overrides restent une arme utile, mais c’est aussi le meilleur moyen de se faire casser au prochain patch si vous dépendez d’une signature interne.
Un moyen simple (et très “rentable”) de cadrer le risque est de classer vos dépendances aux points d’extension en trois catégories :
| Zone | Exemple | Risque de BC break | Action recommandée |
|---|---|---|---|
| API publique | hooks documentés, services exposés, contrats stables | Faible à moyen | Favoriser systématiquement |
| Intégration “grise” | classes internes utilisées “parce que ça marche” | Moyen à élevé | Encapsuler dans un adaptateur (anti-corruption layer) |
| Override / patch | surcharge de classes, modification de comportements internes | Élevé | Limiter, documenter, tester sur chaque patch |
La méthode la plus fiable : réduire l’interface de contact entre vos modules et le core. Favorisez l’injection de dépendances via le container Symfony, utilisez les hooks documentés, et encapsulez les appels au cœur dans des adaptateurs. Pour les modules existants, faites une passe de “stabilisation PHP 8.1–8.5” avant d’essayer d’exploiter des syntaxes modernes : en e-commerce, une erreur fatale pendant le checkout coûte plus cher que n’importe quel gain de propreté de code.
Côté performance, PHP 8.1+ apporte des gains réels, mais ils ne se matérialisent pas si la plateforme est mal configurée. Recommandations pragmatiques :
- OPcache activé et dimensionné (FPM + CLI si vous exécutez beaucoup de commandes). OPcache mal réglé = invalidations fréquentes, CPU inutile.
- Cache applicatif (Redis/Memcached) : utile si votre stack PrestaShop le supporte proprement, mais mesurez : réduisez le TTFB sur pages non cachées (checkout, compte) plutôt que de sur-optimiser la home.
- SQL : index et requêtes générées par modules. La majorité des lenteurs en boutique PrestaShop vient d’add-ons qui font du N+1 ou des agrégations coûteuses sans index.
Une approche “mesurable” (plutôt que “on a l’impression que c’est plus rapide”) consiste à définir, avant migration, 3–5 indicateurs simples :
- temps de génération côté serveur sur une page produit (sans cache full page),
- latence et taux d’erreurs du checkout,
- durée d’un import (produits/stock) via CLI,
- nombre de
E_DEPRECATED/ heure en staging.
Cela permet de valider que la montée de version PHP (ou de PrestaShop) améliore réellement l’exploitation, et pas seulement “l’état de l’art”.
Pour cadrer l’upgrade (et éviter l’improvisation), enchaînez : (1) snapshot VM + dump SQL, (2) duplication sur staging, (3) bascule PHP par paliers (8.1 → 8.2 → 8.3 → …), (4) traitement des dépréciations comme des bugs, (5) seulement ensuite, déploiement prod. Si vous migrez aussi de version majeure, référez-vous à votre trajectoire 1.7/8 → 9 : l’article interne “PrestaShop 9 : guide de migration depuis 1.7 et 8 avec 1-Click Upgrade” donne un cadre opérationnel pour sécuriser la montée de version (expertise-prestashop.fr).
Dernier point, volontairement non “confortable” : viser PHP 8.5 sur PrestaShop 9.1 est un objectif raisonnable pour un SI qui veut rester à jour, mais c’est un projet de compatibilité, pas un switch dans le panel. Tant que vos modules (et parfois le cœur) laissent traîner des dépréciations, vous achetez des incidents futurs. La seule approche propre est de rendre votre code indépendant des comportements obsolètes, d’avoir une CI multi-PHP, et d’utiliser la CLI pour fiabiliser les traitements lourds hors HTTP.




