Hooks en prestashop 1.6

Sobre los hooks hay que decir que en la 1.6 no hay ningún listado, y la documentación es pobre como ella sola, managing hooks doc.

Existe eso sí un listado “aproximado” de hooks para la 1.5, listado 1.5 doc

Antes de nada hay que definir que un hook, como dice la documentación oficial, es un punto donde los módulos asocian su código a ciertos eventos.

Sin esta API de programación los módulos no servirían para nada. Este punto de anclaje viene definido por un nombre único, así que un hook en lenguaje plano es un nombre -> displayHome, displayLeftColumn, actionAddProduct..etc

prestashop_hook

Mejor interactuar con Prestashop usando hooks

El tema de hooks en prestashop es un cacao importante y al tratar de responder a la pregunta, pero cuantos hooks ahí? parece que se va liando la cosa..

Tipos de hooks: acción y display

Previamente hay que decir que existen dos tipos de hooks, los de acción y los de display, siendo estos últimos los mas ampliamente utilizados.

En la versión  1.5 se introdujo una nomenclatura consistente en que que el hook empiece por action o display de forma que de un vistazo se distingo entre ambos tipos. Aún así hay compatibilidad con nombres “antiguos” (código legacy) de forma que mediante el uso de alias podemos encontrar hooks que se llaman p.ej payment en lugar de displayPayment y updateproduct en lugar de actionProductUpdate.

Los de display tienen la peculiaridad que sabes que lo que devuelvas sera utilizado de forma visual, por lo que siempre al implementarlo hay devolver html de una forma o otra ya que sino pierden su sentido.

En los de acción se realiza algo y sabemos que ese algo no tiene una repercusión visual, es decir p.ej cuando se añade un cliente el módulo necesita realizar una acción, p.ej comunicarse con un ERP, borrar una cache, pueden servir para añadir js a la pantalla..etc, en algunos casos tienes la oportunidad de modificar algún parámetro que reciba el hook.

Como comentaba la documentación es realmente pobre, es ridículo que no haya una explicación de la API prestahsop para un aspecto tan importante como éste, cuando se ejecuta el hook, que recibe como parámetros, en caso de ser de display donde se muestra..etc.

Registro de hooks

Ningún hook sirve de nada si no hay módulos registrados en él, con la API de sistema de registro de módulos  que tiene prestashop que consiste en llamar al modulo->registerHook(‘nombre_del_hook’) (en la instalación del módulo preferiblemente, aunque luego se puede hacer uso del backoffice para registrar, des-registrar, mover..etc), tenemos que además en caso de no existir en la base de datos de la instalación, se creará automáticamente, por lo que a partir de ese momento estará disponible para trastear con él de forma administrativa en el backoffice (module positions doc). Es decir se pueden desenganchar y enganchar, mover..etc

Es importante el orden en que se enganchan los módulos a los hooks, ya que en el caso de hooks de display es evidente que nos interesa que uno salga primero que otro.

Luego el modulo aunque este registrado, debe hacer algo, es decir debe implementar ese hook de forma que ese contrato se realiza en forma de método public function hookNombreDelHook($params)

Ahora bien, en una instalación por defecto de prestashop 1.6.0.14 cuantos hooks hay?

Mirando las Tablas PS_HOOK y PS_HOOK_ALIAS

Usando esta consulta sql en una instalación 1.6.0.14

salen 161 hooks, muchos son hooks que todavía tienen un alias para poder tratar con módulos legacy (y no tan legacy..), otros son nuevos 1.5/1.6

ps_hooks_base_datos_min

captura completa phpmyadmin

link a la tabla con el listado

Aunque esta cifra y listado es una buena base, no nos podemos fiar al 100% ya que p.ej displayInvoiceLegalFreeText esta en el listado pero no “existe como hook”. Que no exista como hook quiere decir que Prestashop no lo llama.

Entonces lo que importa realmente es que en el núcleo de prestashop o directamente en la plantilla se hagan uso de ellos

Esta tabla ira creciendo a medida que instalemos módulos ya que al registrar un módulo en un hook, si éste no existe se creara. Posteriormente una vez exista en la tabla se podrá hacer uso de él en el panel del backoffice de posiciones de módulo.

Núcleo de Prestashop, Hook::exec

Repetimos, un hook es un punto donde los módulos asocian su código a ciertos eventos.

Estos eventos vienen orquestados por el núcleo de prestashop (controladores y clases de entidad). Técnicamente, el código de prestashop llama vía Hook::exec(‘nombre_del_hook’,parametros,.) en ciertos momentos importantes a todos los módulos que están suscritos a ese nombre_del_hook (siguiendo un orden).

Se trata de una implementación del patrón de diseño Observer.

De una forma o de otra el módulo realiza algo de interés. Si es un hook de display prestashop usará el html generado y lo meterá en el sitio y plantilla que toca y si es un hook de acción se realizará cualquier cosa que el módulo considere útil.

Se le pasa además unos parámetros. Por defecto los parámetros que recibirán los módulos serán el carrito y la cookie pero algunos privilegiados recibirán mas información. Absolutamente no se describe en ningún sitio de la documentación oficial, que hooks recibirán estos parámetros.

P.ej el hook updateOrderStatus vemos que recibe como parámetros el nuevo estado, y la id del pedido

Y aún hay mas, algunos incluso (pocos) recibirán un parámetro por referencia y podrán cambiar el valor de ese parámetro de forma que pueden afectar de forma muy directa al comportamiento de Prestashop.

P.ej

esto lo vemos por el & de la variable

Realizando una búsqueda en el código de Prestashop de llamadas a este método Hook::exec, vemos que se llama 219 veces, repartidos entre hooks de acción y de display. Evidentemente se llama al mismo hook desde distintos puntos y hay algunos casos especiales por lo que no se puede decir en ningún caso que hay 219 hooks. P.ej actionCartSave se llama cuando se guarda por primera vez y cuando se modifica un carrito.

todos_hooks_min

También se observa como se usa muchas veces el nombre legacy del hook en la propia llamada..

En las clases de entidad se llama a hooks de acción y en los controladores se llama  a hooks de display, y también a hooks de acción.

captura completa llamadas Hook::exec

tabla resumen llamadas a Hook::exec

Llamadas directas desde la plantilla tpl {hook h=”displayNombreHook”}

Un caso especial consiste en que en el sistema de plantillas smarty (archivos tpl) puede hacer una llamada directa a cualquier hook, de forma que si en nuestro tpl llamamos a {hook h="displayTuHook" } se llamará al hook displayTuHook, es posible  incluso pasarle parámetros. Solo tienen sentido hacerlo para mostrar algo, por lo que solo se encontrarán hooks de display.

Este sistema que esta desde la 1.5 ha añadido una gran flexibilidad a la hora de tunear temas mediante el uso de módulos que interese que su contenido se muestre en determinados puntos que no son los habituales de prestashop. Aunque este sistema se salta por completo el sistema MVC (Modelo Vista Controlador) ya que en la propia vista estamos llamando directamente al Módulo.

Como curiosidad este sistema se ha implementado como una función smarty

Cabe destacar que el tema default-bootstrap también hace uso de ellos…p,ej {hook h=”displayTopColumn”} ya que una instalación base de prestashop incluye un buen puñado de módulos (homeslider y themeconfigurator) que se entienden con el tema default-bootstrap.

Es fácil ver los hooks de display “normales” en la plantilla porque su nombre es bastante descriptivo y son variables smarty (con el $ delante) -> $HOOK_TOP, $HOOK_FOOTER …etc

P.ej

se llama en header.tpl. Esta variable viene rellenada previamente por el núcleo de prestashop (recordemos, por el controlador, ya que es un hook de display) que ha llamado a todos los módulos registrados vía el método Hook::exec mencionado anteriormente. En este caso el núcleo prestashop quiere decir cualquier controlador del FrontOffice, ya que el hook displayTop se necesita en todas las páginas de la tienda.

Estos hooks de display normales tienen que estar en todas las plantillas que sean compatibles con la versión de prestashop.

Mas hooks de los que podemos contar?

Hay situaciones especiales, ya que hay casos en que el nombre del hook se genera de forma dinámica. Por lo que p.ej si analizamos este trozo de código que se llama siempre previamente a que se añada una Entidad (u Objeto) en la base de datos,

vemos que en  el primer caso  cualquier método que este suscrito a actionObjectAddBefore, en el momento de que se cree cualquier entidad Prestashop (Producto, Categoría,..etc) sera informado, y se le pasará ese objeto. luego ya se encargará el de distinguirlo.  Pero sin embargo en el segundo caso  se hace una llamada dinámica de forma que si estamos creando un Producto el hook se llamará actionObjectProductAddBefore. De esta forma el método suscrito a este hook esperará recibir un producto y no una entidad genérica (producto, categoría, fabricante,cliente,pedido..etc).

Esta estrategia dinámica se utiliza en algunos puntos mas y hace que el número total de hooks que entiende prestashop en su núcleo sea bastante grande

Resultado final de llamadas a hooks desde el núcleo de Prestashop

Entonces, si cogemos y filtramos el resultado anterior (219 resultados) quedan 177

lista_definitiva_hooks_min

Ver imagen completa. En amarillo los hooks con nombre dinámico y en naranja los pocos que reciben por referencia alguna variable. He intentado que se vean los parámetros que reciben estos hooks.

Ver listado completo en tabla

Sobre las llamadas dinámicas a nombres de hooks, tenemos p.ej que, en una instalación Prestashop, tenemos 97 entidades (Productos, paginas CMS , etc..) con los 6 hooks que hay antes y después respecto a la creación/edición/borrado de entidades, pasamos que de 6 se han multiplicado a 582.

De la misma forma este sistema de nombres dinámico se usa en los controladores del Backoffice antes y después de realizar alguna acción

P.ej

 

P.ej el hook actionAdminProductControllerProductQuantityBefore y actionAdminProductControllerProductQuantityAfter se ejecutarán antes y después de que se llame a ajaxProcessProductQuantity en el controlador de Productos del Backoffice

Como hay un porrón de controladores en el Backoffice (95) y cada uno hace bastantes cosas (acciones) el numero de hooks posibles a usar es realmente muy grande.

 

  • Javier Jacobo

    Muy buena información, yo tengo días queriendo llamar un .tpl personalizado, que llamo después desde un formulario al realizar una búsqueda. Espero con esta información, lo pueda resolver.

  • Javi Oliver

    Buen resumen. gracias

  • juancamba81

    Buen resumen.
    Tengo una pregunta. He construido un modulo con los hooks hookDisplayCarrierList y hookDisplayShoppingCart. El tema es que quiero hacer una comprobación de los cart_rules por necesidades de negocio y en caso de que no pase la comprobación solo muestre lo que tiene este hook. Me explico por ejemplo en displayCarrierList, quiero que me muestre “error blblbla”, este se logra con return ‘Puntos insuficientes'; o retornando un .tpl. El problema es que me está mostrando la lista de carriers tambien y no quiero eso, es decir que en caso de ese error que he generado no muestre la lista de carrier. La verdad que no se me ocurre como hacerlo. Por cierto no quiero hacer overriedes
    La verdad que es lamentable la documentación de prestashop.

    • https://pelechano.es/ Enrique Gómez

      Lamentablemente en muchos casos suele ser buena idea tirar de overrides. También se puede añadir código javascript en el tpl para que manipule la lista de carriers

      • juancamba81

        Gracias, si al final es lo que nos queda

  • jv

    Hola, no sé si tiene que ver con Hooks, pero quiero crear enlaces dinámicos. Así cuando pase la tienda a otro dominio no tenga que modificar todos los enlaces.
    Gracias

    • https://pelechano.es/ Enrique Gómez

      Hola, no no tiene nada que ver. Mover la tienda a otro dominio no es complicado y prestashop esta montado para que el dominio este centralizado en un punto (aunque hay excepciones en algunos módulos)

  • Isa Nieto

    Hola amigo, me has aclarado unas dudas, ahora me dejas con otra, cuando en una plantilla colocan ese objeto smarty, algo como {$variable}, donde lo puedo encontrar?, mencionas controladores, y hook::exec, pero hay una forma de encontrar esa variable smarty si no se cual es el controller?

    • https://pelechano.es/ Enrique Gómez

      Hola Isa. Efectivamente si en una plantilla existe la variable alguien la ha metido.
      Si esa plantilla es de un módulo, puedes ver como en el modulo.php en un método hook..etc se mete y llama a la plantilla.
      En cambio para las plantillas del tema, los controladores que se encuentran en controllers/front, son los encargados de meter esas variables. P.ej ProductController mete la información en product.tpl que es la plantilla encargada de mostrar la ficha del producto. Si cuentas con un Editor de código es fácil buscar el nombre de la plantilla o incluso la variable (sin el $) en los ficheros .php del core de prestashop.
      Mas info en http://doc.prestashop.com/display/PS16/Developer+Guide