Todos los módulos que publicamos funcionan en PrestaShop 9. Esto es lo que hizo falta.
Empezamos a reconstruir nuestro catálogo contra las alphas de PrestaShop 9 a comienzos de 2024. Para cuando salió la versión estable 9.0, nuestro CI interno ya ejecutaba cada ZIP de módulo en siete versiones de PrestaShop y cuatro versiones de PHP antes de fusionar una sola línea. Hoy todos los módulos de nuestro catálogo de más de 140 módulos se instalan y funcionan en PS 9.0 y 9.1 desde el mismo ZIP que se instala en 8.x y 1.7.6+. Una codebase, detección de versión en runtime, sin precio de "edición PrestaShop 9".

Ese es el titular. El resto de este post es la parte que la mayoría de anuncios de "¡soportamos PS 9!" se saltan: qué se rompió realmente durante la migración, qué detectamos solo porque probamos en tiendas reales y qué deberías preguntar a otros proveedores antes de confiar en su afirmación de compatibilidad.
Qué cambió realmente en PrestaShop 9
Si solo has leído el resumen del blog de PrestaShop, podrías pensar que PS 9 es una actualización ordenada de Symfony. No lo es. Es la versión más disruptiva desde que 1.7 introdujo Symfony por primera vez, y la disrupción se concentra en las partes del framework que más tocan los módulos.
Symfony 4.4 a 6.4: dos majors en un salto
Aquí es donde caen la mayoría de módulos de terceros. En 4.4 podías escribir $this->get('service_name') dentro de un controlador admin y tomar cualquier cosa del contenedor. En 6.4 ese patrón todavía funciona (PrestaShop mantuvo una capa de compatibilidad), pero la clase base de la que depende, FrameworkBundleAdminController, está oficialmente deprecada y programada para eliminarse en PrestaShop 10.
Traducción: si las páginas admin de un módulo se renderizan hoy en PS 9 pero todavía extienden FrameworkBundleAdminController, ese módulo tiene fecha de caducidad conocida. Reescribimos todos nuestros controladores admin para extender PrestaShopAdminController con inyección adecuada por constructor. Es la parte más lenta de la migración y es la parte que no puedes saltarte.
Librerías que el core ya no te entrega
PrestaShop 9 eliminó tres librerías que los módulos recibían gratis desde el vendor/ del core:
- Guzzle: reemplazado por el cliente HTTP de Symfony. Cualquier módulo que haga
use GuzzleHttp\Clienty no incluya su propia copia lanza un fatal de clase no encontrada en cuanto intenta hacer una llamada HTTP. - SwiftMailer: reemplazado por Symfony Mailer. Los módulos que envían correo directamente con Swift no solo lanzarán una deprecación; harán fatal.
- Tactician command bus: reemplazado por Symfony Messenger. Si un módulo usaba CQRS vía Tactician, los handlers de comandos/consultas necesitan reescritura.
La parte que sorprende: estos fallos no aparecen al instalar. El módulo carga, la página de configuración se renderiza bien y luego se cae la primera vez que se ejecuta un cron o un cliente activa la ruta de envío de email. Detectamos así dos módulos nuestros durante las pruebas alpha de PS 9: se instalaban limpios, parecían sanos en el back office y solo explotaban a las 3 de la mañana cuando se ejecutaba un cron de sincronización de stock.
33 hooks eliminados
No es una errata y no es una advertencia de deprecación: han desaparecido. Las eliminaciones se agrupan en tres bloques:
- Hooks legacy del producto admin: todo el editor antiguo de producto desapareció y se llevó sus hooks (
actionAdminProductsControllerXxx,actionAdminActivateAfter/Before,actionAdminDeactivateAfter/Before,actionAdminDeleteAfter/Before,actionAdminSortAfter/Before) - Hooks de login admin: ahora gestionados por la seguridad de Symfony (
actionAdminLoginControllerBefore,actionAdminLoginControllerLogin/Forgot/Reset Before/After) - Hooks del ciclo de vida de AdminController:
initHeader,initContent,initFooter,displaytodavía se disparan en controladores legacy envueltos porLegacyController, pero las nuevas páginas admin Symfony los omiten por completo. Si tu módulo depende de ellos, prueba cada página admin donde aparece.
En la práctica esto es peor que un crash: un módulo se registra en un hook eliminado, la instalación tiene éxito, el hook simplemente nunca se dispara y la función deja de trabajar en silencio. Tuvimos uno de nuestros propios módulos en este estado en una tienda staging durante dos semanas antes de notar que un badge de notificación del admin había desaparecido sin ruido.
PHP 8.1 mínimo, y probamos hasta 8.4
PS 9 deja fuera PHP 8.0 y anteriores. Probamos cada módulo contra 8.1, 8.2, 8.3 y 8.4 porque cada versión menor tiene su propio conjunto de deprecaciones, y una deprecación en 8.3 que solo llena logs suele convertirse en error duro en 8.4. Detectarlas en CI sobre 8.4 es más barato que descubrirlas cuando un hosting sube la tienda de un cliente a 8.4 de la noche a la mañana.
Advanced Stock Management ha desaparecido
Todo el subsistema (pedidos a proveedores, almacenes, interfaz admin de ASM) se eliminó en PS 9. Las tablas de base de datos también desaparecen, así que los módulos que consultaban directamente ps_supply_order* o ps_warehouse* lanzarán errores SQL, no solo warnings PHP. Dos de nuestros módulos (mprwarehouserevolution y mprstockorder) gestionan datos de almacén de forma independiente a ASM precisamente porque nunca confiamos en que ASM sobreviviera; esa apuesta salió bien.
El singleton Context se está retirando
PS 9 introduce servicios de contexto dedicados: EmployeeContext, ShopContext, CurrencyContext, CountryContext, LanguageContext. Context::getContext() todavía funciona y lo hará durante un tiempo, pero ahora huele a código viejo. Lo migramos de forma oportunista: cuando ya estamos en un archivo arreglando otra cosa, cambiamos al servicio dedicado.
trans() ya no escapa HTML
Este cambio es peligroso porque es invisible. En PS 8 y anteriores, la función trans() escapaba entidades HTML como efecto secundario. Mucho código de módulos dependía accidentalmente de eso para protegerse contra XSS sin darse cuenta. En PS 9 debes aplicar explícitamente htmlspecialchars() a cualquier contenido dinámico antes de pasarlo a trans(). Los módulos que no lo hacen ahora tienen posibles agujeros XSS que durante años parecían funcionar bien.
Hummingbird, Bootstrap 5 y el reloj de jQuery
PS 9.1 incluye Hummingbird como theme por defecto para instalaciones nuevas, sobre Bootstrap 5.3.3 (PS 9.0 usaba Bootstrap 5; las tiendas actualizadas conservan su theme existente). Para módulos que tocan el front-end eso significa:
- Las clases utility de Bootstrap 4 desaparecen (
.no-gutterspasa a.g-0,.custom-checkboxpasa a.form-check) - Los atributos data tienen namespace (
data-togglepasa adata-bs-toggle) - jQuery está oficialmente deprecado en Hummingbird y con fecha de salida. Ya reescribimos el JS front-end de nuestros módulos de checkout, rendimiento y pestañas de producto a vanilla, en parte para adelantarnos al plazo, en parte porque el layout de checkout de Hummingbird castiga los patrones de DOM-thrash de jQuery
- Los selectores de clases específicos de PrestaShop se están sustituyendo por atributos
data-ps-*: si tu CSS o JS apunta a.cart-block, prepárate para retargeting
Cómo auditar tu stack de módulos actual
La mayoría de tiendas que migramos no ejecutan solo nuestros módulos: ejecutan un stack de quince a cuarenta módulos de una docena de proveedores, y los nuestros son cinco de ellos. Este es el proceso que usamos en cada migración de cliente.
Paso 1: Haz inventario con honestidad
Módulos → Module Manager. Exporta la lista. Para cada módulo, anota: nombre, versión actual, proveedor, fecha de última actualización y qué tan crítico es. Una pasarela de pago es crítica; un widget para compartir en redes es decoración. La prioridad por criticidad es la que dirige tu calendario, no el orden alfabético.
Paso 2: Lee el changelog del proveedor, no su titular
"Compatible con PrestaShop 9" en una homepage no significa nada. Lo que quieres es una entrada de changelog fechada después de la publicación pública de PS 9 que mencione explícitamente trabajo con Symfony 6.4, pruebas en PHP 8.1+ o sustitución de hooks eliminados. Si la actualización más reciente del proveedor es de 2023 y el texto comercial todavía empieza con "compatible con PrestaShop 1.7", probablemente el módulo está abandonado y la web aún no se ha enterado.
Paso 3: Haz grep del código del módulo
Si tienes un desarrollador (o tu propia línea de comandos), descomprime el módulo y busca los patrones que son problemas garantizados:
# Legacy Symfony 4.4 service access
grep -rn '\$this->get(' modules/yourmodule/
# Removed core libraries
grep -rn 'use GuzzleHttp' modules/yourmodule/
grep -rn 'Swift_\|SwiftMailer' modules/yourmodule/
grep -rn 'League\\Tactician' modules/yourmodule/
# Deprecated price formatting (removed in PS 9.0)
grep -rn 'Tools::displayPrice' modules/yourmodule/
# Bootstrap 4 data attributes
grep -rn 'data-toggle=' modules/yourmodule/views/templates/
# jQuery usage in front-end JS
grep -rn '\$.ajax\|\$(document)' modules/yourmodule/views/js/
Un resultado en use GuzzleHttp sin un composer.json que incluya Guzzle en la carpeta vendor propia del módulo es un crash confirmado en PS 9. Un resultado en Tools::displayPrice es un fatal duro: ese método fue eliminado, no solo deprecado. Mantenemos internamente un pequeño paquete prestashop-compat que envuelve estas llamadas para nuestros módulos; en módulos de terceros sin esa protección, la llamada muere.
Paso 4: Staging que refleje producción de verdad
Nunca pruebes compatibilidad en la tienda live. Nuestra receta mínima de staging:
- Clonar la base de datos de producción en una DB separada (la mayoría de hostings decentes tiene un botón para esto)
- Instalar PS 9.1 sobre ella: ve directo a 9.1, no pasando por 9.0, porque 9.1 es donde acabarás de todas formas
- Instalar módulos por orden de dependencia: pagos y transporte primero, luego SEO/marketing, luego cosméticos. Así un crash de un módulo pesado no bloquea tu capacidad de probar los ligeros
- Después de cada instalación, seguir el log de errores PHP y el log de PrestaShop en
var/logs/. La mayoría de problemas de compatibilidad son primero avisos de deprecación y fatals en la siguiente minor; no descartes warnings - Probar el trabajo real del módulo, no solo "abre la página de configuración". Haz un pedido de prueba real. Ejecuta una importación. Genera un sitemap real. Que la página de configuración renderice no demuestra casi nada
El hábito de mayor rendimiento que hemos adoptado:
tail -f var/logs/*en un terminal mientras haces clic por el back office en otro. El ruido de deprecaciones es el indicador adelantado de roturas en la siguiente versión. Si un módulo llena ese log en PS 9.1, es el módulo que hará fatal en 9.2.
Paso 5: Smoke test front-end en el theme que realmente usarás
Si vas a cambiar a Hummingbird, cada módulo con salida front-end necesita una revisión visual en el theme real, no en Classic dentro de un admin de prueba. Los sitios donde siempre encontramos roturas:
- Checkout: formularios de pago, bloques de transportista, validación de direcciones, cualquier cosa inyectada en el resumen de pedido
- Páginas de producto: reseñas, wishlists, guías de tallas, bloques de campos personalizados
- Header/footer: mega menús y desplegables de búsqueda son especialmente frágiles en la migración a Bootstrap 5
- Filtros de página de categoría y controles de ordenación
Si te quedas en Classic, tu riesgo es menor, pero no es cero, porque Bootstrap 5 sigue llegando al admin y cualquier módulo que comparta CSS entre front y back aún puede comportarse mal.
Las preguntas que merece la pena hacer a un proveedor
"¿Tu módulo es compatible con PrestaShop 9?" es una pregunta de sí/no que devuelve "sí" el 100% de las veces, a menudo incorrectamente. Estas son las que hacemos a proveedores cuando evaluamos sus módulos para el stack de un cliente:
- ¿El módulo está probado en 9.0 y 9.1? 9.1 añadió Bootstrap 5.3.3, eliminó
displaySearchy rehizo la convención de selectoresdata-ps-*. Probar solo en 9.0 es medio trabajo. - ¿Es el mismo ZIP para 8.x y 9.x? Si necesitas una descarga separada para PS 9, tienes una trampa de mantenimiento esperando en cada tienda que ejecuta varias versiones. Los módulos de ZIP único con detección de versión en runtime son como debería hacerse.
- ¿Habéis migrado fuera de
FrameworkBundleAdminController? Si el desarrollador no reconoce la pregunta, ya has aprendido algo importante. - ¿El JS front-end todavía necesita jQuery? Por ahora vale, pero pide el calendario de migración. Hummingbird eliminará jQuery y no quieres ser la última prioridad de un proveedor cuando ocurra.
- ¿Cuál es la matriz de pruebas PHP? La respuesta que quieres es "8.1 a 8.4", no "PHP 8".
Cuándo actualizar y cuándo esperar
Actualiza ya si tus módulos críticos tienen compatibilidad explícita con PS 9.1, ya estás en PHP 8.1+, tienes una copia de staging funcional y tu theme es Classic, Hummingbird o un child de uno de ellos.
Espera de tres a seis meses si uno o dos módulos nice-to-have no tienen confirmación de compatibilidad, tu theme es un theme de pago muy personalizado (los proveedores de themes van por detrás; hemos visto retrasos de 18 meses), o dependes de Advanced Stock Management y aún no has elegido reemplazo.
No actualices si un módulo crítico (pago, transporte, sincronización ERP) no tiene declaración sobre PS 9 y el proveedor no ha publicado nada en un año, sigues en PHP 7.4 u 8.0 (eso es otro proyecto: hazlo primero), o tu tienda tiene personalizaciones pesadas de una agencia que no ha probado PS 9.
Cómo llevamos realmente nuestros más de 140 módulos a PS 9
Merece la pena contarlo con detalle porque "soportamos PrestaShop 9" significa cosas distintas para distintos proveedores, y la diferencia importa cuando confías el live shop a un módulo de otra persona.

Fase 1: Análisis estático de todo el catálogo
Ejecutamos un scanner personalizado sobre el código fuente de cada módulo buscando los patrones anteriores: uso de controladores legacy, imports de Guzzle/Swift/Tactician, Tools::displayPrice, markup Bootstrap 4, dependencias jQuery. El resultado fue una lista de trabajo por módulo ordenada por riesgo. No confiamos en "recordar" qué módulos necesitaban qué arreglo.
Fase 2: Migración de controladores a Symfony 6.4
Cada controlador admin que tocaba el contenedor de servicios pasó de $this->get() a inyección por constructor. Cada controlador que extendía la clase base deprecada migró a PrestaShopAdminController. Esta es la fase lenta: toca la columna vertebral de cada módulo con admin y no tiene atajo.
Fase 3: Auditoría y sustitución de hooks
Cruzamos cada llamada registerHook() del catálogo con la lista de hooks eliminados de PS 9. Donde un hook había desaparecido, migramos al reemplazo o añadimos registro condicional por versión en los scripts de instalación, de modo que un módulo instalado en PS 8.x siga usando el hook antiguo y el mismo ZIP en PS 9 use el nuevo.
Fase 4: Capa compat compartida
Los métodos con más probabilidad de eliminarse en futuras minors viven detrás de wrappers en un paquete compartido (prestashop-compat). Tools::displayPrice es el ejemplo obvio: ahora es \MyPrestaRocks\Compat\PriceFormatter::format() en los más de 140 módulos, y el wrapper detecta la versión de PS y llama a la API correcta. Cuando PS 9.2 elimine otra cosa, actualizamos el wrapper una vez, sincronizamos y todos los módulos quedan cubiertos.
Fase 5: Pruebas de matriz en CI
Cada ZIP de módulo se prueba en PrestaShop 1.7.6, 1.7.7, 1.7.8, 8.0, 8.1, 9.0 y 9.1, y en cada versión contra PHP 8.1, 8.2, 8.3 y 8.4. Lo ejecutamos en contenedores Docker dedicados (ps176-dev, ps178-dev, ps8-dev, ps9-dev) en nuestra propia infraestructura, levantando contenedores temporales para versiones menores concretas cuando hace falta. Un único ZIP de módulo funciona en cada combinación porque el módulo ramifica por _PS_VERSION_ en runtime, no porque publiquemos builds múltiples.
Fase 6: Verificación en themes Hummingbird y Classic
Cada módulo con salida front-end se renderiza en ambos themes antes de la release. Cuando las plantillas tenían que diferir (y algunas tuvieron que hacerlo, sobre todo por atributos data-bs-* y componentes de formulario), usamos el helper de versión de PrestaShop para elegir la plantilla correcta. El merchant no ve esto; su views/templates/hook/*.tpl simplemente funciona en el theme que tenga.
Donde fuimos honestos
Algunos de nuestros módulos tocan áreas que PS 9 rediseñó a nivel de framework: pestañas de producto del back office, contexto multitienda, puentes AdminAPI. En esos casos, probamos manualmente cada ruta funcional en PS 9.0 y 9.1 antes de activar la bandera de compatibilidad. No afirmamos compatibilidad porque la categoría parezca segura; la afirmamos porque el módulo corrió de extremo a extremo en la versión que decimos soportar.
El resultado: todos los módulos del catálogo de mypresta.rocks se instalan y funcionan en PS 9.0 y 9.1 desde el mismo ZIP que corre en 8.x y 1.7.6+. Sin edición separada, sin tarifa de migración.
Qué falla después de una actualización exitosa
Incluso con módulos confirmados por el proveedor, este es el patrón de incidencias post-upgrade que vemos, más o menos en el orden en que ocurren.
Error 500 después de instalar un solo módulo
Casi siempre es una dependencia Composer ausente en la carpeta vendor propia del módulo. El log de errores PHP dirá "Class not found" con un nombre reconocible, normalmente GuzzleHttp\Client, Swift_Mailer o una clase de Symfony Messenger. Actualiza el módulo o, si el proveedor va lento, coloca manualmente la librería que falta en el vendor/ del módulo (lo hemos hecho en tiendas de clientes para mantenerlas funcionando mientras esperaban un arreglo real).
La página admin carga, la función está muerta en silencio
El problema de los hooks eliminados. El módulo se instaló, la página de configuración se renderiza, pero el hook del que dependía la función nunca se dispara. Revisa el install() del módulo contra la lista de hooks eliminados en PS 9. La solución es una actualización del proveedor: no hay workaround del lado del cliente que haga volver a un hook eliminado.
El front-end se ve roto en Hummingbird, bien en Classic
Deriva de clases de Bootstrap 4 a 5. Las plantillas del módulo usan .no-gutters, .custom-checkbox, data-toggle u otro markup BS4. Workaround temporal: cambiar la tienda a theme Classic mientras esperas. Arreglo real: actualización de plantillas por el proveedor.
Errores JavaScript en la consola
O se espera jQuery y no está cargado, o los selectores apuntan a nombres de clases antiguos que se movieron a data-ps-*. $ is not defined en la consola es la señal clara. A corto plazo puedes cargar jQuery manualmente en el theme; a largo plazo el módulo necesita vanilla JS.
Los emails dejan de enviarse
El módulo invoca SwiftMailer directamente en lugar de pasar por Mail::Send() de PrestaShop. PS 9 no tiene SwiftMailer que instanciar. No hay arreglo del lado del cliente; necesitas que el módulo se actualice para usar Symfony Mailer.
PrestaShop 9.1: los extras que necesitas saber
Si te saltas 9.0 y vas directo a 9.1 (sensato: es donde acabarás de todos modos), 9.1 añadió sus propios breaking changes encima de 9.0:
Theme::getDefaultTheme()ya no hardcodea "classic". Los módulos que asumían Classic como theme por defecto para lógica fallback se comportarán mal.- El hook
displaySearchdesapareció de Hummingbird: causaba conflictos de renderizado en páginas 404. Los módulos que usandisplaySearchpara personalización de búsqueda front-end necesitan otro hook. - Se actualizaron las versiones de D3 y NVD3. Si un widget de dashboard estaba atado a una API concreta de D3, puede renderizar mal en 9.1.
- Los selectores JavaScript pasaron de clases a
data-ps-*. CualquierquerySelector('.something')contra el DOM propio de PrestaShop puede dejar de coincidir.
El checklist pre-upgrade que usamos en tiendas de clientes
- Inventariar cada módulo instalado con proveedor y versión
- Comprobar el changelog de cada proveedor buscando una entrada explícita 9.0/9.1 fechada después de la release de PS 9
- Actualizar cada módulo a su última versión antes de actualizar PrestaShop
- Provisionar un entorno staging con una copia fresca de la base de datos de producción
- Instalar PS 9.1 en staging, directo a 9.1, no pasando por 9.0
- Instalar módulos por orden de dependencia, siguiendo logs después de cada uno
- Ejecutar la funcionalidad real de cada módulo: pedidos, importaciones, exportaciones, sitemaps, emails
- Renderizar el front-end en el theme que usarás en producción
- Hacer un pedido de prueba completo a través del checkout, incluida confirmación de pago
- Leer el log de errores PHP en busca de deprecaciones: son fatals futuros
- Verificar que cada módulo que envía correo haya enviado realmente su email
- Hacer una copia de seguridad completa (base de datos, archivos, configuración) y conservarla más de 30 días tras el upgrade
- Programar la actualización live para la ventana de menor tráfico de tu tienda
- Tener a mano el backup 8.x durante al menos un mes. El rollback debe ser posible hasta que estés seguro
Cierre
PS 9 es una mejora real una vez que estás en él: Symfony 6.4 es genuinamente más rápido, Hummingbird es realmente más ligero que Classic y la AdminAPI abre patrones de integración que el Webservice legacy no alcanza. Nada de eso ayuda si la actualización rompe los módulos de los que vive tu tienda.
La migración es posible. No es un trabajo de fin de semana, y "compatible" es una palabra que deberías obligar a los proveedores a respaldar con detalles. Nosotros hicimos el trabajo en todo nuestro catálogo, en nuestra propia infraestructura, contra las versiones reales de PrestaShop que afirmamos soportar, porque cada tienda que ejecuta nuestros módulos acaba actualizando y preferimos hacer el trabajo una vez antes que responder tickets de soporte para siempre.
Si quieres módulos donde el trabajo de PS 9 ya está hecho (mismo ZIP, todas las versiones de PS, sin tarifa de actualización), empieza por el catálogo de mypresta.rocks. Si quieres ayuda evaluando tu stack actual, escríbenos.
Comentarios
Aún no hay comentarios. ¡Sé el primero!
Sé el primero en hacer una pregunta o compartir una opinión útil.
Dejar un comentario
Comparte una pregunta, un detalle de instalación o una opinión que pueda ayudar a otro lector.