Magento 2: Sincronización de backend y frontend State / Cache

14

¿Magento 2 tiene algún sistema o abstracción para administrar el estado entre el backend y el almacenamiento local en la interfaz?

Estoy trabajando en portar una función para restaurar el carrito abandonado de un usuario a través de una URL de redireccionamiento. En forma simplificada, una URL como

http://magento.example.com/restore/the/cart?identifier=sdkfjh48v237g5

cargará una cotización en el carrito del usuario actual basado en un quote_id codificado en el identificador.

En Magento 1, esto era relativamente simple: solo necesitaba actualizar la información de la sesión de Checkout de un usuario con la ID de cotización correcta. Sin embargo, Magento 2 agrega la arruga del almacenamiento local .

La (s) aplicación (es) de JavaScript de la interfaz de Magento 2 parece almacenar información en caché en las bases de datos de almacenamiento local del navegador. Esto incluye información para construir el mini carro. Lo que esto significa es que incluso si un programador de usuario final (yo) logra cambiar la ID de sesión de la sesión en el back-end, el mini-carrito seguirá mostrando los datos del carrito antiguo .

Este es solo un ejemplo de un problema que surge de no saber (¿o no tener?) Una sola API para administrar el estado de la aplicación en el backend y la interfaz. Para mi problema específico, he tenido mi punto final que representa una página HTML que incluye algunos JavaScript que borra manualmente el almacenamiento local y luego redirige al usuario a otra página, pero esto se siente como un truco asqueroso.

¿Existe una API en Magento 2 para administrar los datos entre el frontend y el backend?

¿Existe una forma estándar de señalizar a todo el sistema que, durante el procesamiento del back-end, has hecho algo que hace necesario que invalide el caché de almacenamiento local de la interfaz?

¿Existe una técnica para inyectar un nuevo módulo RequireJS en la página que se ejecuta automáticamente y puede manipular el almacenamiento local antes de que el resto de las aplicaciones de JavaScript accedan a él?

Alan Storm
fuente
Oye. Estimado Alan Store, ¿recibiste respuesta?
Amit Bera
@AmitBera Todavía no.
Alan Storm

Respuestas:

6

Tuve un problema similar: quería que el componente del mini-carrito se actualizara después de enviar una solicitud de Ajax para agregar un artículo al carrito.

Realmente funciona bastante bien si solo recuerda algunos puntos:

  • Declare qué secciones de la página deben actualizarse después de una llamada Ajax, en etc / frontend / secciones.xml de su módulo.
  • Use jQuery.post () para enviar su solicitud de Ajax. Puede ser una solicitud POST o PUT, pero no GET.
  • Y debe ser a través de jQuery, no Prototype o vanilla JS, porque es el evento 'ajaxComplete' de jQuery el que juega un papel esencial.
  • anteponga la url de Ajax con una url base (no solo comience con /)

Aquí está mi section.xml (xyz es el nombre de nuestro cliente):

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Customer:etc/sections.xsd">
    <action name="xyz-ajax/cart/add">
        <section name="cart"/>
    </action>
</config>

Aquí, 'xyz-ajax / cart / add' está de acuerdo con el formato '[frontName] / [ActionPath] / [ActionName]'. El xml le dice a Magento que actualice 'cart' después de que la llamada ajax "xyz-ajax / cart / add" se haya completado.

Este es mi código de plantilla (.phtml):

<script type="text/javascript">
    require(['jquery', 'BigBridge_XYZ/option_selector'], function($, optionSelect) {
        optionSelect.create(<?= json_encode($componentData) ?>, $);
    })
</script>

y este es el código JS que envía la solicitud Ajax:

función requestComplete (responseData) {}

$.post(baseUrl + 'xyz-ajax/cart/add/cf/' + configurableProductId + '/simple/' + item.simpleProductId + '/amount/' + item.amount, requestComplete);

¿Qué pasa en el proceso?

Cada vez que su script envía una solicitud POST (o PUT) de Ajax al servidor a través de jQuery, y regresa, jQuery envía un evento 'ajaxComplete'. Este evento es manejado por un controlador en module-customer / view / frontend / web / js / customer-data.js. Este controlador comprueba qué secciones de página dependen de la llamada Ajax (de su section.xml) y las invalida. Estos serán actualizados.

Fuentes:

Patrick van Bergen
fuente
14

Magento 2 utiliza la API JS de datos del cliente para representar los datos de la sesión del usuario en el navegador. Se supone que todos los widgets JS recuperan datos del cliente de la API JS de datos del cliente. Los datos del cliente se dividen en secciones (carrito, lista de deseos, ...). Cada segmento es observable, por lo que cada vez que se modifica, el widget que lo utiliza se vuelve a representar para mostrar el cambio.

El marco de trabajo de Magento es responsable de la sincronización de la sesión PHP y los datos del cliente de almacenamiento local JS.

Cada vez que un visitante con cookie de ID de sesión y almacenamiento local vacío visita la página de Magento, se realiza una solicitud HTTP al servidor para recuperar los datos del cliente (todas las secciones).

Cada vez que el visitante realiza alguna operación de modificación de estado (agregar al carrito, agregar a la lista de deseos), la sección correspondiente de los datos del cliente se invalida en el almacenamiento local y se realiza otra solicitud HTTP para recuperar secciones actualizadas.

Puede usar 'secciones.xml' para vincular acciones POST a secciones de almacenamiento local que se invalidarán cuando se invoquen esas acciones. Ver https://github.com/magento/magento2/blob/develop/app/code/Magento/Checkout/etc/frontend/sections.xml por ejemplo.

Anton Kril
fuente
2

Sobre la base de estas otras respuestas, si está actualizando el carrito a través de llamadas API en require.jsarchivos Magento normales , pero no puede confiar en el ajaxCompletemétodo jQuery para actualizar el minicart (¿usa otro marco de solicitud AJAX?), Puede Magento_Customer/js/customer-datasolicitar el objeto y preguntar el minicart para actualizar de esta manera también:

<script>
    require([
        'Magento_Customer/js/customer-data'
    ], function (customerData) {
        var sections = ['cart'];
        customerData.invalidate(sections);
        customerData.reload(sections, true);
    });
</script>

Fuente: https://github.com/magento/magento2/issues/5621

thaddeusmt
fuente