使用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模块,请按照Magento2 创建基础模块的步骤进行操作。
我建议你使用netz98 magerun CLI工具扩展,这在开发过程中是一个有用的支援。例如,您可以使用一个命令创建包含所有必需文件的模块。
根据需要命名模块,我将使用Vendor for vendor和ModuleName作为模块名称。
在创建包含所有必要文件的模块后,我们将添加/编辑其中的一些文件以实现我们的目标。
请不要忘记在创建模块后进行设置: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和您的模块名称!