系统学习magento二次开发,推荐小册:《Magento中文全栈二次开发 》
本小册面向Magento2以上版本,书代码及示例兼容magento2.0-2.4版本。涵盖了magento前端开发,后端开发,magento2主题,magento2重写,magento2 layout,magento2控制器,magento2 block等相关内容,带领您成为magento开发技术专家。
使用CMS块是Magento过去和现在如此受欢迎的原因之一。使用 CMS 块,站点管理员可以轻松操作商店的内容。CMS块可用于显示促销横幅,销售块,退货政策,商店某些部分的重要信息消息等。 CMS块可以携带纯文本或HTML / JS/CSS代码块,这意味着它们可以用于更复杂的内容交付,如滑块,产品轮播等。
我个人喜欢尽可能使用CMS块,以便商店的内容变得更加“模块化”且易于管理。
结账时的CMS块可以有很多用途,例如显示某些促销内容的特定运输方式的一些信息,以说服用户在结帐前花费更多。
将CMS块添加到某些特定位置/页面并不麻烦,我们只需要在布局中“注册”我们的CMS块并定义CMS块的顺序/位置。然后我们需要在模板中调用它,仅此而已。CMS 块现在是内容的一部分,将在需要时呈现/交付。
将CMS块添加到Magento 2 Checkout是一项更复杂的任务,因为整个结帐是由一系列KnockoutJS组件构建的,然后使用Knockout.js模板系统进行渲染。Magento 2在一个大型XML文件中定义了这些组件及其相互关系。为了从服务器中提取数据,Magento使用全局Javascript变量window.checkoutConfig,然后由Knockout使用.js在前端计算和显示信息。
简而言之,整个结帐是动态加载的,我们不能在里面放任何“静态”的东西。
希望有一种方法可以在结帐流程中插入CMS块。
由于整个结帐是从各种JS组件捆绑而来的,因此此任务的方法将根据CMS块位置而有所不同。但是,每种方法都有相同的初始步骤。
想法是从CMS块中获取内容并将其放入JS对象中,然后通过挖空绑定输出到前端。这样,我们的 CMS 内容就会成为结帐流程的一部分,并与其他组件一起加载。如果您想与组件一起闲逛,请充当组件!
### 创建模块
如果您不知道如何创建Magento 2模块,请按照我的同事Hrvoje Ivancic的这篇文章中的步骤进行操作。
我建议您使用 netz98 magerun CLI 工具扩展,这是开发过程中的有用资产。例如,您可以使用一个命令创建一个包含所有必要文件的模块。
根据需要命名模块。我将使用供应商作为供应商,使用模块名称作为模块名称。
创建包含所有必要文件的模块后,我们将添加/编辑其中的一些文件以实现我们的目标。
请不要忘记在创建模块后进行设置:升级。
在结帐侧边栏中添加 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.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 块。
请注意,我已经在我的包/主题中创建了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() ]; } }
然后,
使用以下内容创建应用/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并更改它。
现在我们已经设置好了一切,我们只需要一个挖空模板来输出 CMS 块数据。
使用此内容创建 app/code/Vendor/ModuleName/view/frontend/web/template/cms-block.html:
<div data-bind="html: window.checkoutConfig.cms_block"></div>
仅此而已。现在,您的CMS块应以地址形式显示并首先呈现。
给定的示例适用于干净的Magento 2.2安装。Luma主题用于测试目的。
如果出现问题,请检查:
您的模块是否正确创建并包含所有具有正确值的配置文件?
您是否在创建模块后运行了PHP bin/magento setup:upgrade?
通过将Vendor/ModuleName替换为正确的供应商和模块名称来检查您是否正确更改了本文中的代码!