使用CMS块是Magento如此受欢迎的原因之一。使用CMS块,网站管理员可以轻松地操作商店的内容。CMS块可以用来显示促销横幅,销售模块,退货政策,商店某些重要信息等。CMS块可以是纯文本或HTML/JS/CSS代码块,这意味着它们可以用于更复杂的内容,如滑块,产品轮播等。

我个人喜欢尽可能使用CMS块,以便商店的内容变得更“模块化”,易于管理。

CMS块在结账时可以有很多用途,比如显示某些促销内容的特定配送方式的某些信息,以便说服用户在结账前花费更多。

将CMS块添加到某个特定位置/页面并不是一件麻烦事,我们只需要在布局中“注册”我们的CMS块并定义CMS块的顺序/位置。然后我们在模板中调用它,就这样。CMS块现在是内容的一部分,将在需要时渲染/显示。

将CMS块添加到Magento 2结账中要复杂一些,因为整个结账是由一系列KnockoutJS组件构建的,然后使用knockout.js模板系统进行渲染。Magento 2在一个大的XML文件中定义了这些组件及其相互关系。为了从服务器提取数据,Magento使用全局Javascript变量window.checkoutConfig,然后由Knockout.js使用它来计算和显示前端的信息。

简而言之,整个结账是动态加载的,我们不能把任何“静态”内容放在里面。

希望有方法可以在结帐流程中插入CMS块。

由于整个结账是从各种JS组件构建的,因此根据CMS块位置的不同,实现此目标的方法也会有所不同,但是,每种方法都有相同的初始步骤。

我们想实现的是从CMS块中获取内容并将其放入JS对象中,然后通过Knockout Bindings将其输出到前端。这样,我们的CMS内容就成为结帐流程的一部分,并与其他组件一起加载。

 

创建一个模块

如果您不知道如何创建Magento 2模块,请按照这篇博客步骤进行操作

我建议你使用netz98 magerun CLI工具扩展,这在开发过程中是一个有用的支援。例如,您可以使用一个命令创建包含所有必需文件的模块。

根据需要命名模块,我将使用Vendor for vendorModuleName作为模块名称。

在创建包含所有必要文件的模块后,我们将添加/编辑其中的一些文件以实现我们的目标。
请不要忘记在创建模块后进行设置:upgrade

 

在结账页面侧边栏中添加CMS块

编辑Vendor/ModuleName/etc/frontend/di.xml文件:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
   <type name="Magento\Checkout\Model\CompositeConfigProvider">
       <arguments>
           <argument name="configProviders" xsi:type="array">
               <item name="cms_block_config_provider" xsi:type="object">Vendor\ModuleName\Model\ConfigProvider</item>
           </argument>
       </arguments>
   </type>
   <type name="Vendor\ModuleName\Model\ConfigProvider">
       <arguments>
           <argument name="blockId" xsi:type="string">checkout_cms_block</argument>
       </arguments>
   </type>
</config>

使用此代码,我们将向ConfigProvider添加新条目,我们还将声明这将用于解析数据的CMS块。
在上面的示例中,块名为“checkout_cms_block”(它与块的id或标识符一起使用)。

请确保该路径与路径名称匹配,在上面的示例中路径是Vendor\ModuleName\Model\ConfigProvider

接下来,我们将通过创建或编辑Vendor/ModuleName/Model/ConfigProvider.php创建新条目

<?php namespace Vendor\ModuleName\Model;
 
use Magento\Checkout\Model\ConfigProviderInterface;
use Magento\Framework\View\LayoutInterface;
 
class ConfigProvider implements ConfigProviderInterface
{
   /** @var LayoutInterface  */
   protected $_layout;
   protected $cmsBlock;
 
   public function __construct(LayoutInterface $layout, $blockId)
   {
       $this->_layout = $layout;
       $this->cmsBlock = $this->constructBlock($blockId);
   }
 
   public function constructBlock($blockId){
       $block = $this->_layout->createBlock('Magento\Cms\Block\Block')
           ->setBlockId($blockId)->toHtml();
       return $block;
   }
 
   public function getConfig()
   {
       return [
           'cms_block' => $this->cmsBlock
       ];
   }
}

由于我们已将自己的变量添加到全局window.checkoutConfig变量,因此我们现在可以使用window.checkoutConfig.cms_block变量调用该内容

现在我们只需要将该变量绑定到某个HTML元素,Knockout.JS将完成其余的工作。

这是app/design/frontend/Vendor/ThemeName/Magento_Checkout/web/template/sidebar.html

 <div id="opc-sidebar"
    data-bind="afterRender:setModalElement, mageInit: {
   'Magento_Ui/js/modal/modal':{
       'type': 'custom',
       'modalClass': 'opc-sidebar opc-summary-wrapper',
       'wrapperClass': 'checkout-container',
       'parentModalClass': '_has-modal-custom',
       'responsive': true,
       'responsiveClass': 'custom-slide',
       'overlayClass': 'modal-custom-overlay',
       'buttons': []
   }}">
 
   <!-- ko foreach: getRegion('summary') -->
       <!-- ko template: getTemplate() --><!-- /ko -->
   <!--/ko-->
 
   <div data-bind="html: window.checkoutConfig.cms_block"></div>
 
   <div class="opc-block-shipping-information">
       <!-- ko foreach: getRegion('shipping-information') -->
       <!-- ko template: getTemplate() --><!-- /ko -->
       <!--/ko-->
   </div>
</div>

如果您的操作都正确,您应该会在侧栏中看到您的CMS块。

请注意,我已在我的package/theme中创建了sidebar.html模板,切勿直接在vendor/magento/*文件夹中编辑文件。

 

将CMS块添加到地址表单

对于此目标,我们将使用一种不同的方法。
我们将app/code/Vendor/ModuleName/Model/ConfigProvider.php的内容更改为

<?php
 
namespace Vendor\ModuleName\Model;
 
 
use Magento\Checkout\Model\ConfigProviderInterface;
use Magento\Cms\Block\Widget\Block;
 
class ConfigProvider implements ConfigProviderInterface
{
   protected $cmsBlockWidget;
 
   public function __construct(Block $block, $blockId)
   {
       $this->cmsBlockWidget = $block;
       $block->setData('block_id', $blockId);
       $block->setTemplate('Magento_Cms::widget/static_block/default.phtml');
   }
 
   public function getConfig()
   {
       return [
           'cms_block' => $this->cmsBlockWidget->toHtml()
       ];
   }
}

然后,使用以下内容创建app/code/Vendor/ModuleName/view/frontend/layout/checkout_index_index.xml

<?xml version="1.0"?>
 
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="checkout" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
   <body>
       <referenceBlock name="checkout.root">
           <arguments>
               <argument name="jsLayout" xsi:type="array">
                   <item name="components" xsi:type="array">
                       <item name="checkout" xsi:type="array">
                           <item name="children" xsi:type="array">
                               <item name="steps" xsi:type="array">
                                   <item name="children" xsi:type="array">
                                       <item name="shipping-step" xsi:type="array">
                                           <item name="children" xsi:type="array">
                                               <item name="shippingAddress" xsi:type="array">
                                                   <item name="children" xsi:type="array">
                                                       <item name="shipping-address-fieldset" xsi:type="array">
                                                           <item name="children" xsi:type="array">
                                                               <item name="cms-block" xsi:type="array">
                                                                   <item name="component" xsi:type="string">uiComponent</item>
                                                                   <item name="config" xsi:type="array">
                                                                       <item name="template" xsi:type="string">Vendor_ModuleName/cms-block</item>
                                                                   </item>
                                                                   <item name="sortOrder" xsi:type="string">1</item>
                                                               </item>
                                                           </item>
                                                       </item>
                                                   </item>
                                               </item>
                                           </item>
                                       </item>
                                   </item>
                               </item>
                           </item>
                       </item>
                   </item>
               </argument>
           </arguments>
       </referenceBlock>
   </body>
</page>

我们现在已经在地址表单中添加了新的UI组件,该组件将保留我们的CMS块的内容。如上所述,组件加载顺序在XML文件中进行管理。正如您所看到的,我为sortOrder设置了1,意味着我的组件将首先在地址表单中加载。
注意这一行Vendor_ModuleName/cms-block并更改它。
现在我们已经完成了所有设置,我们只需要一个knockout模板来输出CMS块内容。

使用以下内容创建app/code/Vendor/ModuleName/view/frontend/web/template/cms-block.html

<div data-bind="html: window.checkoutConfig.cms_block"></div>

现在,您的CMS块应在地址表单中首先显示。

如果出现问题,请检查:

  • 你的模块是否正确创建并包含所有配置文件,其中包含适当的值吗?
  • 你在创建模块后运行php bin/magento setup:upgrade了吗?
  • 检查您是否正确地修改了博客中的代码,将Vendor/ModuleName替换为合适的Vendor和您的模块名称!