使Magento 2全页面缓存适用于以编程方式登录的客户

目录

  1. 引言
  2. 了解问题
  3. 使程序化登录与FPC正常工作
  4. 结论
  5. 常见问题

引言

在线零售商不断寻找优化购物体验的方法,而Magento 2是一个强大的平台,提供了许多功能来实现这一目标。Magento 2的一个关键组件是全页面缓存(FPC),旨在通过减少服务器负载并加快页面加载速度来改善站点性能。然而,实施FPC有时可能会引发复杂的问题,特别是在管理程序化客户登录时。

如果您在启用FPC时遇到了客户不一致登录的问题,那么您并不孤单。本博客文章将深入研究为什么会出现这种情况以及如何解决这个问题。阅读完这篇详细指南后,您将对如何使Magento 2的全页面缓存与以编程方式登录的客户无缝配合工作有着坚实的理解。

了解问题

全页面缓存通过在缓存中存储渲染页面的完整副本来工作。当用户请求页面时,会提供缓存的版本,大大减少生成页面所需的时间。这通常可以很好地提高页面加载时间和整体站点性能。

然而,当尝试以编程方式登录客户时,通常使用AJAX调用,会出现一个常见问题:登录后可能会发现行为不一致:有时客户登录成功,而其他时候却没有登录成功。让我们一起探讨为什么会出现这种不一致性。

为什么全页面缓存会导致与程序化登录相关的问题

当Magento 2生成页面并启用缓存时,DepersonalizePlugin在布局生成阶段清除了客户会话。该插件与全页面缓存进行交互,并确保个性化会话数据不会干扰缓存页面,缓存页面会提供给多个用户。

由于此行为:

  1. 客户会话数据丢失:启用FPC时,直接访问客户会话数据存在问题,因为会话在页面创建过程的可缓存阶段被清除。
  2. HTTP上下文限制:HTTP上下文维护了一些用户会话信息,但默认情况下不包含详细的客户属性,如ID、名称或电子邮件。只有客户组和“未登录”状态可用。

使程序化登录与FPC正常工作

为了解决这个问题,我们可以使用Magento的插件来扩展HTTP上下文以获取额外的客户会话数据。下面是解决不一致性的逐步指南。

第1步:创建依赖注入配置(di.xml)

首先,我们需要在自定义模块中创建一个di.xml配置文件。该文件将指示Magento使用我们的自定义插件。

路径app/code/[Vendor]/[ModuleName]/etc/frontend/di.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Framework\App\Http\Context">
        <plugin name="customer_session_context" type="[Vendor]\[ModuleName]\Plugin\SessionContext" />
    </type>
</config>

第2步:创建插件类

接下来,我们需要定义插件类,该类将向HTTP上下文添加客户会话数据。

路径app/code/[Vendor]/[ModuleName]/Plugin/SessionContext.php

namespace [Vendor]\[ModuleName]\Plugin;

use Magento\Customer\Model\Session as CustomerSession;
use Magento\Framework\App\Http\Context as HttpContext;

class SessionContext
{
    protected $customerSession;
    protected $httpContext;

    public function __construct(CustomerSession $customerSession, HttpContext $httpContext)
    {
        $this->customerSession = $customerSession;
        $this->httpContext = $httpContext;
    }

    public function beforeGetValue(HttpContext $subject, $key, $defaultValue)
    {
        if ($key === 'customer_id' && !$this->httpContext->getValue('customer_id')) {
            $this->httpContext->setValue('customer_id', $this->customerSession->getCustomerId(), false);
        }

        if ($key === 'customer_email' && !$this->httpContext->getValue('customer_email')) {
            $this->httpContext->setValue('customer_email', $this->customerSession->getCustomer()->getEmail(), false);
        }

        return [$key, $defaultValue];
    }
}

第3步:从HTTP上下文访问会话数据

现在,客户会话数据在HTTP上下文中可用,您可以在前端代码中轻松访问它。

例如,您可以像下面这样检查客户是否已登录并检索会话详细信息:

use Magento\Framework\App\Http\Context as HttpContext;

class YourCustomBlock extends \Magento\Framework\View\Element\Template
{
    protected $httpContext;

    public function __construct(
        \Magento\Framework\View\Element\Template\Context $context,
        HttpContext $httpContext,
        array $data = []
    ) {
        $this->httpContext = $httpContext;
        parent::__construct($context, $data);
    }

    public function getCustomerId()
    {
        return $this->httpContext->getValue('customer_id');
    }

    public function getCustomerEmail()
    {
        return $this->httpContext->getValue('customer_email');
    }
}

结论

Magento 2启用全页面缓存后,在以编程方式登录客户时不一致的问题归结为在页面布局生成阶段清除客户会话数据。通过向HTTP上下文添加必要的客户会话信息,我们可以确保客户保持登录状态,提供无缝体验。

通过实施插件以包含此附加数据来解决该问题,如本指南所示。现在,您可以享受全页面缓存的性能优势,而不会影响客户登录的可靠性。

常见问题

Q:为什么启用全页面缓存会导致会话数据丢失?

A:Magento 2中的全页面缓存在页面布局生成阶段清除了客户会话数据,以去除缓存内容中的个性化信息,防止存储特定用户信息。

Q:Magento 2中的HTTP上下文的作用是什么?

A:Magento 2中的HTTP上下文存储和管理与会话相关的信息,可以在可缓存和不可缓存的页面之间共享,以确保一致的用户体验。

Q:如何确保在缓存页面上可访问基本的客户数据?

A:通过创建自定义插件,可以扩展HTTP上下文以包括客户会话数据,确保在启用全页面缓存的情况下仍然可以访问客户ID和电子邮件地址等详细信息。

Q:自定义HTTP上下文会对性能产生什么影响?

A:尽管任何自定义都会带来一定的性能开销,但通常维护一致的客户会话数据的好处通常超过了这些成本。始终应进行适当的测试。

Q:此解决方案适用于Magento中的其他领域吗?

A:是的,扩展HTTP上下文的方法可以应用于其他情况,其中数据一致性尽管启用全页面缓存也是至关重要的。