文章列表


在Magento 2中运行cron定时任务

<h5 style="color:red;">系统学习magento二次开发,推荐小册:<a style="color:blue;" href="https://www.maxiaoke.com/manual/magento_cn_dev.html" target="_blank">《Magento中文全栈二次开发 》</a></h5> <div class="image-container"> <p> <a style="color:blue;" href="https://www.maxiaoke.com/manual/magento_cn_dev.html" target="_blank"> <img src="https://www.maxiaoke.com/uploads/images/20230218/bb9c82995c24d1105676e02f373755f5.jpg" alt="Magento中文全栈二次开发"> </a> </p> </div> <div class="text-container" style="font-size:14px; color:#888"> <p>本小册面向Magento2以上版本,书代码及示例兼容magento2.0-2.4版本。涵盖了magento前端开发,后端开发,magento2主题,magento2重写,magento2 layout,magento2控制器,magento2 block等相关内容,带领您成为magento开发技术专家。</p> </div> <hr><p>当涉及到Magento 2和cron作业时,与Magento 1相比有一些改进。</p><p>它仍然是抽象的,因为您并不真正直接运行作业,而是使用 cron 语法通过 Magento 调度程序设置定期方法执行,该调度程序在系统的 cron 实用程序之上工作。</p><p>以下是一些有用的提示,可帮助您开始设置自己的提示。</p><p>当我们将其与Magento 1进行比较时,数据库似乎没有更改,但是配置确实发生了变化。</p><p>Magento 2将执行表中cron_schedule条目,就像在Magento 1中一样。</p><p>配置中的新闻是,现在我们能够对作业进行分组,并选择是否希望将作业作为单独的进程并行执行,这有时可能会非常方便。</p><p><img src="/uploads/images/20230822/42128e7de877c33833ae4105d89f0fa4.png" title="2.png" alt="" width="856" height="539"/></p><p>因此,为了在Magento中运行计划任务,首先我们需要确保将以下作业配置为通过系统cron运行。这是最简单的方法:</p><p>*/1 * * * * /path/to/php /path/to/m2/installation/bin/magento cron:run [&gt;&gt; /log/file &amp;]</p><p>*/1 * * * * /path/to/php /path/to/m2/installation/update/cron.php [&gt;&gt; /log/file &amp;]</p><p>*/1 * * * * /path/to/php /path/to/m2/installation/bin/magento setup:cron:run [&gt;&gt; /log/file &amp;</p><p>此时,您已经准备好了所有这些 M2 默认作业!</p><p>那么,如何做好自己的工作呢?</p><p>或多或少,这是以与Magento 1类似的方式完成的。</p><p>首先,您需要在自定义模块中.xml crontab:</p><p></p><pre class="brush:bash;toolbar:false">&lt;?xml&nbsp;version=&quot;1.0&quot;?&gt; &lt;config&nbsp;xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&nbsp;xsi:noNamespaceSchemaLocation=&quot;urn:magento:module:Magento_Cron:etc/crontab.xsd&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;group&nbsp;id=&quot;default&quot;&gt;&nbsp;&lt;!--&nbsp;Doesn&#39;t&nbsp;need&nbsp;to&nbsp;be&nbsp;unique&nbsp;--&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;job&nbsp;name=&quot;cron_example&quot;&nbsp;instance=&quot;Inchoo\CronExample\Cron\Example&quot;&nbsp;method=&quot;execute&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;schedule&gt;*&nbsp;*&nbsp;*&nbsp;*&nbsp;*&lt;/schedule&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/job&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/group&gt; &lt;/config&gt;</pre><p><span style="color: #ce9178;"></span><br/></p><p><span style="color: #ce9178;">上面的配置是为了确保每分钟运行一次Inchoo</span><span style="color: #d7ba7d;">\C</span><span style="color: #ce9178;">ronExample</span><span style="color: #d7ba7d;">\C</span><span style="color: #ce9178;">ron</span><span style="color: #d7ba7d;">\E</span><span style="color: #ce9178;">xample:execute(),这将(根据下面的代码每分钟记录它的名字。</span></p><p><span style="color: #ce9178;"></span></p><pre class="brush:bash;toolbar:false">&lt;?php namespace&nbsp;Inchoo\CronExample\Cron; class&nbsp;Example&nbsp;{ &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;$_logger; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;__construct(\Psr\Log\LoggerInterface&nbsp;$logger)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;_logger&nbsp;=&nbsp;$logger; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;execute()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;_logger-&gt;info(__METHOD__); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$this; &nbsp;&nbsp;&nbsp;&nbsp;} }</pre><p><span style="color: #ce9178;"></span><br/></p><p><span style="color: #ce9178;">还值得一提的是,您当时可以选择只运行一个作业组。</span></p><p><span style="color: #ce9178;">以下是您的操作方法:</span></p><pre class="brush:bash;toolbar:false">magento&nbsp;cron:run&nbsp;[--group=&quot;cron_group_name&quot;]</pre><p><span style="color: #ce9178;"></span><br/></p><p><br/></p>

一篇文章盘点magento2中覆盖类文件以及重写类class的6种方法

<h5 style="color:red;">系统学习magento二次开发,推荐小册:<a style="color:blue;" href="https://www.maxiaoke.com/manual/magento_cn_dev.html" target="_blank">《Magento中文全栈二次开发 》</a></h5> <div class="image-container"> <p> <a style="color:blue;" href="https://www.maxiaoke.com/manual/magento_cn_dev.html" target="_blank"> <img src="https://www.maxiaoke.com/uploads/images/20230218/bb9c82995c24d1105676e02f373755f5.jpg" alt="Magento中文全栈二次开发"> </a> </p> </div> <div class="text-container" style="font-size:14px; color:#888"> <p>本小册面向Magento2以上版本,书代码及示例兼容magento2.0-2.4版本。涵盖了magento前端开发,后端开发,magento2主题,magento2重写,magento2 layout,magento2控制器,magento2 block等相关内容,带领您成为magento开发技术专家。</p> </div> <hr><p>与以前的版本相比,Magento 2提出了依赖注入的新概念,其中类为对象注入依赖关系(不同的对象),而不是该对象在内部手动创建它们。这样覆盖和操作类就容易得多,并允许我们更多扩展本机功能的方法。</p><p>必须在类中注入哪些依赖项由文件控制。每个模块都可以有一个全局和特定于区域的文件,可以根据范围使用该文件。模块 di.xml 文件的路径:di.xmldi.xml</p><p>&lt;moduleDir&gt;/etc/di.xml</p><p>&lt;moduleDir&gt;/etc/&lt;area&gt;/di.xml</p><p>请务必注意,覆盖块、模型、帮助程序、控制器或其他内容之间没有更多区别。它们都是可以重写的类。我们将介绍扩展本机Magento类和方法的三种不同方法。</p><p><span style="color: #6a9955;">### 类首选项</span></p><p>让我们称之为覆盖我们习惯的类的老式方式,但略有不同。所有类都由其接口定义,并由 di.xml 文件配置。当类的构造函数签名通过其接口请求对象时,可以实现抽象实现映射。这意味着应该在可用的情况下使用接口,并且映射将告诉应该启动哪个类。</p><p>让我们看一下目录模块的 di.xml 文件中如何定义目录产品类:</p><pre class="brush:bash;toolbar:false">&lt;config&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;preference&nbsp;for=&quot;Magento\Catalog\Api\Data\ProductInterface&quot;&nbsp;type=&quot;Magento\Catalog\Model\Product&quot;&nbsp;/&gt; &lt;/config&gt;</pre><p>要覆盖类,我们只需要定义我们的首选项并创建一个将扩展原始类的文件:Magento\Catalog\Model\Product</p><pre class="brush:bash;toolbar:false">&lt;config&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;preference&nbsp;for=&quot;Magento\Catalog\Api\Data\ProductInterface&quot;&nbsp;type=&quot;Inchoo\Catalog\Model\Product&quot;&nbsp;/&gt; &lt;/config&gt;</pre><pre class="brush:bash;toolbar:false">&lt;?php namespace&nbsp;Inchoo\Catalog\Model; &nbsp; class&nbsp;Product&nbsp;extends&nbsp;\Magento\Catalog\Model\Product { //&nbsp;code }</pre><p>为了确保模块依赖项的顺序正确,应该为示例中的Magento_Catalog定义模块序列。etc/module.xml</p><p><span style="color: #6a9955;">### 插件</span></p><p>如果多个类扩展同一原始类,则按类首选项重写可能会导致冲突。为了帮助解决这个问题,引入了插件的新概念。插件扩展了方法,并且不会像通过类首选项重写那样更改类本身,而是在其调用之前、之后或周围拦截方法调用。</p><p>插件在 di.xml 文件中配置,它们在被覆盖的方法之前、之后或周围调用。第一个参数始终是观察方法名称的对象,后跟原始方法的参数。</p><p>作为示例,我们将扩展目录产品模块中的一些方法。这是 di.xml 文件的外观:</p><pre class="brush:bash;toolbar:false">&lt;config&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;type&nbsp;name=&quot;Magento\Catalog\Api\Data\ProductInterface&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;plugin&nbsp;name=&quot;inchoo_catalog_product&quot;&nbsp;type=&quot;Inchoo\Catalog\Plugin\Model\Product&quot;&nbsp;/&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/type&gt; &lt;/config&gt;</pre><p><span style="color: #6a9955;">### before方法</span></p><p>在插件之前在观察到的方法之前运行,并且必须在数组中返回该方法接受的相同数量的参数或 null – 如果不应修改该方法。要扩展的方法必须具有相同的名称,前缀为“before”。</p><pre class="brush:bash;toolbar:false">&lt;?php namespace&nbsp;Inchoo\Catalog\Plugin\Model; &nbsp; class&nbsp;Product { &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;beforeSetPrice(\Magento\Catalog\Model\Product&nbsp;$subject,&nbsp;$price) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$price&nbsp;+=&nbsp;10; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;[$price]; &nbsp;&nbsp;&nbsp;&nbsp;} }</pre><p>after方法</p><p>在调用原始方法后执行方法之后。在类对象旁边,该方法接受另一个参数,这也是必须返回的结果。要扩展的方法必须具有相同的名称,前缀为“after”。</p><pre class="brush:bash;toolbar:false">&lt;?php namespace&nbsp;Inchoo\Catalog\Plugin\Model; &nbsp; class&nbsp;Product { &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;afterGetName(\Magento\Catalog\Model\Product&nbsp;$subject,&nbsp;$result) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$result&nbsp;.=&nbsp;&#39;&nbsp;(Inchoo)&#39;; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$result; &nbsp;&nbsp;&nbsp;&nbsp;} }</pre><p>around方法</p><p>Around 方法包装原始方法,并允许在原始方法调用之前和之后执行代码。在类对象旁边,该方法接受另一个参数接收是可调用的,允许链中的其他插件调用。要扩展的方法必须具有相同的名称,前缀为“around”。</p><pre class="brush:bash;toolbar:false">&lt;?php namespace&nbsp;Inchoo\Catalog\Plugin\Model; &nbsp; class&nbsp;Product { &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;aroundSave(\Magento\Catalog\Model\Product&nbsp;$subject,&nbsp;\callable&nbsp;$proceed) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;before&nbsp;save &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$result&nbsp;=&nbsp;$proceed(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;after&nbsp;save &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$result; &nbsp;&nbsp;&nbsp;&nbsp;} }</pre><p>使用插件看起来像是覆盖方法的理想解决方案,但它有局限性。插件不能用于所有类型的方法,在尝试扩展以下方法时,必须寻找其他解决方案:</p><p>在 Magento\Framework\Interception 引导之前实例化的对象</p><p><span style="color: #6a9955;">### 最终方法</span></p><p>包含至少一个最终公共方法的任何类</p><p>非公共方法</p><p>类方法(如静态方法)</p><p>__construct</p><p>虚拟类型</p><p>构造函数参数</p><p>di.xml 配置哪些依赖项将被注入到类中,这意味着它们可以被控制并更改为对我们有用的东西。如果更改不需要是全局的,而是针对特定类的,</p><p>那么我们可以配置类接收的参数,而不是覆盖整个类或为不同的方法创建插件。</p><p><span style="color: #6a9955;">### 类型配置</span></p><p>目录产品模块接收的参数之一是帮助程序。使用 di.xml我们可以配置为改用我们的助手:\Magento\Catalog\Helper\Product $catalogProduct</p><pre class="brush:bash;toolbar:false">&lt;config&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;type&nbsp;name=&quot;Magento\Catalog\Api\Data\ProductInterface&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;arguments&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;argument&nbsp;name=&quot;catalogProduct&quot;&nbsp;xsi:type=&quot;object&quot;&gt;Inchoo\Catalog\Helper\Product&lt;/argument&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/arguments&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/type&gt; &lt;/config&gt;</pre><p>允许不同的参数类型,具体取决于要更改的内容。允许的类型为 、、、、 和 。objectstringbooleannumberconstnullarrayinit_parameter</p><p><span style="color: #6a9955;">### 虚拟类型配置</span></p><p>在文档中,虚拟类型被定义为一种类型,它允许您更改特定可注入依赖项的参数并更改特定类的行为。</p><p>如果我们回到帮助程序示例,而不是注入新的帮助程序,有时只更改原始帮助程序中的一个参数就可以完成工作,并且创建新文件是多余的。</p><p>在我们的示例中,这意味着从 创建一个虚拟类型,更改其参数并将该虚拟帮助程序用作目录产品类的参数。Magento\Catalog\Helper\Product</p><pre class="brush:bash;toolbar:false">&lt;config&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;virtualType&nbsp;name=&quot;virtualHelper&quot;&nbsp;type=&quot;Magento\Catalog\Helper\Product&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;arguments&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;argument&nbsp;name=&quot;catalogSession&quot;&nbsp;xsi:type=&quot;object&quot;&gt;Inchoo\Catalog\Model\Session\Proxy&lt;/argument&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/arguments&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/type&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;type&nbsp;name=&quot;Magento\Catalog\Api\Data\ProductInterface&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;arguments&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;argument&nbsp;name=&quot;catalogProduct&quot;&nbsp;xsi:type=&quot;object&quot;&gt;virtualHelper&lt;/argument&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/arguments&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/type&gt; &lt;/config&gt;</pre><p>当只需要更改依赖项的构造参数而不创建任何其他文件,只需在 xml 文件中配置它时,虚拟类型会派上用场。</p><p>覆盖类和方法的方法不止一种,选择使用哪一种方法将取决于您遇到的情况。</p><p>虽然使用类首选项作为覆盖方式可能看起来是在大多数情况下都有效的最简单方法,但当不同的模块尝试覆盖相同的类和相同的方法时,</p><p>这是许多冲突的原因,这就是为什么应该考虑所有方法的原因。</p><p><br/></p>

在Magento2中如何进行外部数据库连接

<h5 style="color:red;">系统学习magento二次开发,推荐小册:<a style="color:blue;" href="https://www.maxiaoke.com/manual/magento_cn_dev.html" target="_blank">《Magento中文全栈二次开发 》</a></h5> <div class="image-container"> <p> <a style="color:blue;" href="https://www.maxiaoke.com/manual/magento_cn_dev.html" target="_blank"> <img src="https://www.maxiaoke.com/uploads/images/20230218/bb9c82995c24d1105676e02f373755f5.jpg" alt="Magento中文全栈二次开发"> </a> </p> </div> <div class="text-container" style="font-size:14px; color:#888"> <p>本小册面向Magento2以上版本,书代码及示例兼容magento2.0-2.4版本。涵盖了magento前端开发,后端开发,magento2主题,magento2重写,magento2 layout,magento2控制器,magento2 block等相关内容,带领您成为magento开发技术专家。</p> </div> <hr><p>大多数时候,使用Magento,单个数据库连接就足够了。</p><p>Magento具有出色的系统,可以在数据库中添加新表或扩展现有表。</p><p>那么,为什么需要在Magento系统之外建立外部数据库连接呢?嗯,一个例子是从另一个电子商务系统进行数据迁移。</p><p>在本文中,通过 CRUD(创建、读取、更新、删除)示例介绍了与外部数据库的简单连接。</p><p><span style="color: #6a9955;">### 配置</span></p><p>此外部数据库连接同样被定义为Magento默认连接 - 在XML配置中。不同之处在于外部连接是在特定模块的 XML 配置中定义的。它定义读取和写入适配器、设置和数据库凭据信息。外部表的定义方式与 magento 表相同。它们位于inchoo_foreignconnection_resource节点下,因此稍后可以在代码中调用模型资源。出于演示目的,XML 配置中有一个前端节点,用于定义控制器 (fconn) 的前端名称。</p><pre class="brush:bash;toolbar:false">&lt;?xml&nbsp;version=&quot;1.0&quot;?&gt; &lt;config&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;modules&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Inchoo_ForeignConnection&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;version&gt;1.4.2&lt;/version&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/Inchoo_ForeignConnection&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/modules&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;global&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;models&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;inchoo_foreignconnection&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;class&gt;Inchoo_ForeignConnection_Model&lt;/class&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;resourceModel&gt;inchoo_foreignconnection_resource&lt;/resourceModel&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/inchoo_foreignconnection&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;inchoo_foreignconnection_resource&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;class&gt;Inchoo_ForeignConnection_Model_Resource&lt;/class&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;entities&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;product&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;table&gt;product_description&lt;/table&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/product&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/entities&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/inchoo_foreignconnection_resource&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/models&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;resources&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;inchoo_foreignconnection_write&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;connection&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;use&gt;inchoo_foreignconnection_database&lt;/use&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/connection&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/inchoo_foreignconnection_write&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;inchoo_foreignconnection_read&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;connection&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;use&gt;inchoo_foreignconnection_database&lt;/use&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/connection&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/inchoo_foreignconnection_read&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;inchoo_foreignconnection_setup&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;connection&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;use&gt;core_setup&lt;/use&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/connection&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/inchoo_foreignconnection_setup&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;inchoo_foreignconnection_database&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;connection&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;host&gt;&lt;![CDATA[localhost]]&gt;&lt;/host&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;username&gt;&lt;![CDATA[username]]&gt;&lt;/username&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;password&gt;&lt;![CDATA[password]]&gt;&lt;/password&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;dbname&gt;&lt;![CDATA[db_name]]&gt;&lt;/dbname&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;initStatements&gt;&lt;![CDATA[SET&nbsp;NAMES&nbsp;utf8]]&gt;&lt;/initStatements&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;model&gt;&lt;![CDATA[mysql4]]&gt;&lt;/model&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;type&gt;&lt;![CDATA[pdo_mysql]]&gt;&lt;/type&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;pdo_type&gt;&lt;![CDATA[]]&gt;&lt;/pdo_type&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;active&gt;1&lt;/active&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/connection&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/inchoo_foreignconnection_database&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/resources&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/global&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;frontend&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;routers&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;inchoo_foreignconnection&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;use&gt;standard&lt;/use&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;args&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;module&gt;Inchoo_ForeignConnection&lt;/module&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;frontName&gt;fconn&lt;/frontName&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/args&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/inchoo_foreignconnection&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/routers&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/frontend&gt; &lt;/config&gt;</pre><p><span style="color: #6a9955;">### 模型</span></p><p>接下来是一个模型,该模型将使用定义的外部连接来获取数据或将数据保存在外部数据库中。在这里,模型使用 XML 配置中的产品表进行初始化,在本例中定义product_description表。</p><pre class="brush:bash;toolbar:false">class&nbsp;Inchoo_ForeignConnection_Model_Product&nbsp;extends&nbsp;Mage_Core_Model_Abstract { &nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;$_eventPrefix&nbsp;=&nbsp;&#39;inchoo_foreignconnection_product&#39;; &nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;$_eventObject&nbsp;=&nbsp;&#39;product&#39;; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;function&nbsp;_construct() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;_init(&#39;inchoo_foreignconnection/product&#39;); &nbsp;&nbsp;&nbsp;&nbsp;} }</pre><p>模型资源类也是使用 _init() 函数中相同的 xml 配置节点定义的,但使用 TABLE_PRIMARY_KEY 参数。在此类中,可以创建多个将处理外部数据的函数。</p><p>第一个例子是createDataInResource函数,它将数据插入模型的表中。它需要将插入的参数数组。</p><p>第二个示例是 readDataFromResource 函数,它从模型的表中获取所有数据。必须先定义读取适配器。它是来自 xml 的配置节点,用于定义读取连接。读取适配器定义后,可以使用Magento数据库函数(select(),from(),limit()等)。当查询完全构造时,可以使用读取适配器执行它。可以使用 fetchPairs() 或 fetchAll() 函数检索数据。fetchAll() 用于获取从 mysql 返回的所有记录。</p><p>updateDataInResource 和 deleteDataFromResource 函数采用额外的$id参数,用于定义将更新或删除的记录。</p><pre class="brush:bash;toolbar:false">class&nbsp;Inchoo_ForeignConnection_Model_Resource_Product&nbsp;extends&nbsp;Mage_Core_Model_Resource_Db_Abstract { &nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;TABLE_PRIMARY_KEY&nbsp;=&nbsp;&#39;product_id&#39;; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;function&nbsp;_construct() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;_init(&#39;inchoo_foreignconnection/product&#39;,&nbsp;self::TABLE_PRIMARY_KEY); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;createDataInResource($values&nbsp;=&nbsp;array()) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$writeAdapter&nbsp;=&nbsp;$this-&gt;_getWriteAdapter(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$writeAdapter-&gt;insert( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;getMainTable(), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$values &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(Exception&nbsp;$e)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Mage::log(&#39;Unable&nbsp;to&nbsp;insert&nbsp;data&nbsp;to&nbsp;external&nbsp;resource.&nbsp;&#39;&nbsp;.&nbsp;$e-&gt;getMessage(),&nbsp;null,&nbsp;null,&nbsp;true); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;readDataFromResource() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$data&nbsp;=&nbsp;array(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$readAdapter&nbsp;=&nbsp;$this-&gt;_getReadAdapter(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$select&nbsp;=&nbsp;$readAdapter-&gt;select() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&gt;from($this-&gt;getMainTable(),&nbsp;&#39;*&#39;) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&gt;limit(20); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$data&nbsp;=&nbsp;$readAdapter-&gt;fetchAll($select); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(Exception&nbsp;$e)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Mage::log(&#39;Unable&nbsp;to&nbsp;fetch&nbsp;data&nbsp;from&nbsp;external&nbsp;resource.&nbsp;&#39;&nbsp;.&nbsp;$e-&gt;getMessage(),&nbsp;null,&nbsp;null,&nbsp;true); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$data; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;updateDataInResource($id,&nbsp;$values&nbsp;=&nbsp;array()) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$writeAdapter&nbsp;=&nbsp;$this-&gt;_getWriteAdapter(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$writeAdapter-&gt;update( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;getMainTable(), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$values, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self::TABLE_PRIMARY_KEY&nbsp;.&nbsp;&#39;=&#39;&nbsp;.&nbsp;$id &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(Exception&nbsp;$e)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Mage::log(&#39;Unable&nbsp;to&nbsp;update&nbsp;data&nbsp;in&nbsp;external&nbsp;resource.&nbsp;&#39;&nbsp;.&nbsp;$e-&gt;getMessage(),&nbsp;null,&nbsp;null,&nbsp;true); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;deleteDataFromResource($id) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$writeAdapter&nbsp;=&nbsp;$this-&gt;_getWriteAdapter(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$writeAdapter-&gt;delete( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;getMainTable(), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self::TABLE_PRIMARY_KEY&nbsp;.&nbsp;&#39;=&#39;&nbsp;.&nbsp;$id &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(Exception&nbsp;$e)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Mage::log(&#39;Unable&nbsp;to&nbsp;delete&nbsp;data&nbsp;from&nbsp;external&nbsp;resource.&nbsp;&#39;&nbsp;.&nbsp;$e-&gt;getMessage(),&nbsp;null,&nbsp;null,&nbsp;true); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;} } class&nbsp;Inchoo_ForeignConnection_Model_Resource_Product_Collection&nbsp;extends&nbsp;Mage_Core_Model_Resource_Db_Collection_Abstract { &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;_construct() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;_init(&#39;inchoo_foreignconnection/product&#39;); &nbsp;&nbsp;&nbsp;&nbsp;} }</pre><p><span style="color: #6a9955;">### 控制器中的用法</span></p><p>所有这些函数都在 IndexController 类中演示,但由于它们是在模型的资源类中定义的,因此可以在任何控制器类中调用它们。</p><pre class="brush:bash;toolbar:false">class&nbsp;Inchoo_ForeignConnection_IndexController&nbsp;extends&nbsp;Mage_Core_Controller_Front_Action { &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;indexAction() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Create &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$foreignProductCreate&nbsp;=&nbsp;Mage::getModel(&#39;inchoo_foreignconnection/product&#39;)-&gt;getResource(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$foreignProductCreate-&gt;createDataInResource( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;array( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;product_name&#39;&nbsp;=&gt;&nbsp;&#39;Product&nbsp;name&#39;, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;product_description&#39;&nbsp;=&gt;&nbsp;&#39;Product&nbsp;description&#39; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Read &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$foreignProductRead&nbsp;=&nbsp;Mage::getModel(&#39;inchoo_foreignconnection/product&#39;)-&gt;getResource(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$result&nbsp;=&nbsp;$foreignProductRead-&gt;readDataFromResource(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var_dump($result); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Update &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$foreignProductUpdate&nbsp;=&nbsp;Mage::getModel(&#39;inchoo_foreignconnection/product&#39;)-&gt;getResource(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$foreignProductUpdate-&gt;updateDataInResource( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3394, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;array( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;product_name&#39;&nbsp;=&gt;&nbsp;&#39;Product&nbsp;name&nbsp;updated&#39;, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;product_description&#39;&nbsp;=&gt;&nbsp;&#39;Product&nbsp;description&nbsp;updated&#39; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Delete &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$foreignProductDelete&nbsp;=&nbsp;Mage::getModel(&#39;inchoo_foreignconnection/product&#39;)-&gt;getResource(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$foreignProductDelete-&gt;deleteDataFromResource(3394); &nbsp;&nbsp;&nbsp;&nbsp;} }</pre><p>在大多数情况下,Magento将使用不同类型的外部连接来检索或发送数据,但有时像这样的外部数据库连接将是最好的方法。</p><p>其中一个例子是,当您想使用他们的xsell或追加销售产品将产品从另一个系统导入Magento时。</p><p>在这种情况下,读取连接将用于检索产品数据,写入连接将用于将xsell或追加销售产品ID保存在临时表中,以便在导入来自外部系统的所有产品时可以将它们分配给Magento产品。</p><p><br/></p>

在Magento2中自定义产品信息选项卡

<h5 style="color:red;">系统学习magento二次开发,推荐小册:<a style="color:blue;" href="https://www.maxiaoke.com/manual/magento_cn_dev.html" target="_blank">《Magento中文全栈二次开发 》</a></h5> <div class="image-container"> <p> <a style="color:blue;" href="https://www.maxiaoke.com/manual/magento_cn_dev.html" target="_blank"> <img src="https://www.maxiaoke.com/uploads/images/20230218/bb9c82995c24d1105676e02f373755f5.jpg" alt="Magento中文全栈二次开发"> </a> </p> </div> <div class="text-container" style="font-size:14px; color:#888"> <p>本小册面向Magento2以上版本,书代码及示例兼容magento2.0-2.4版本。涵盖了magento前端开发,后端开发,magento2主题,magento2重写,magento2 layout,magento2控制器,magento2 block等相关内容,带领您成为magento开发技术专家。</p> </div> <hr><p>无论是水平(更常见)还是垂直,选项卡都是通过将大型内容组织成易于消化的数据块来避免信息过载的好方法。如果做得好,它们提供所有信息(与一个特定主题相关),而不会让用户不知所措,允许他们通过一次仅显示一个选项卡中的数据来快速浏览内容。从用户体验的角度来看,标签的主要目的是简单地促进对信息的访问,并且知道它们不会以任何方式对您的SEO和网站排名产生任何负面影响也很有用。</p><p>在Magento中,与大多数其他电子商务平台一样,产品页面上使用选项卡式导航来显示各种产品信息和数据。默认情况下,Luma和Blank主题也是如此,产品页面上有三个选项卡:</p><p>–有关产品的详细信息,即描述</p><p>–存储产品属性和值</p><p>的更多信息 –产品买家和消费者提供的评论</p><p>这些选项卡可以轻松自定义,我们将向您展示如何自定义。但是,在我们开始之前,让我们花一些时间来探索并找出我们实际要自定义的模板和布局文件。一种方法是启用模板路径提示并通过Magento管理员将块名称添加到提示中:</p><p><span style="color: #569cd6;">Stores</span> =&gt; <span style="color: #569cd6;">Configuration</span> =&gt; <span style="color: #569cd6;">Advanced</span> =&gt; <span style="color: #569cd6;">Developer</span> =&gt; Debug</p><p>虽然,至少现在我们知道哪个Magento模块(提示:模块目录)负责产品信息选项卡,因此我们可以从自定义开始,这是值得怀疑的。让我们从简单开始。</p><p><span style="color: #6a9955;">### 重命名产品选项卡</span></p><p>为了为我们的选项卡设置另一个标题,我们必须覆盖文件夹中的基本布局文件。执行此操作的标准(Magento)方法是在我们的主题范围内创建新的布局文件,并将其命名为与基本文件完全相同的名称。catalog_product_view.xmlvendor/module_catalog</p><p>我们的文件路径应如下所示:</p><p>app/design/frontend/&lt;Vendor&gt;/&lt;Theme&gt;/Magento_Catalog/layout/catalog_product_view.xml</p><p>我们文件中的代码是这样的:</p><pre class="brush:bash;toolbar:false">&lt;?xml&nbsp;version=&quot;1.0&quot;?&gt; &lt;page&nbsp;layout=&quot;1column&quot;&nbsp;xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;;;&nbsp;xsi:noNamespaceSchemaLocation=&quot;urn:magento:framework:View/Layout/etc/page_configuration.xsd&quot;&gt; &nbsp;&nbsp;&lt;body&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;referenceBlock&nbsp;name=&quot;product.info.details&quot;&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;referenceBlock&nbsp;name=&quot;product.info.description&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;arguments&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;argument&nbsp;name=&quot;title&quot;&nbsp;translate=&quot;true&quot;&nbsp;xsi:type=&quot;string&quot;&gt;Description&lt;/argument&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/arguments&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/referenceBlock&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/referenceBlock&gt; &nbsp;&nbsp;&lt;/body&gt; &lt;/page&gt;</pre><p>如果我们分析上面的代码,我们将看到第一个布局处理程序&lt;referenceBlock <span style="color: #569cd6;">name</span>=“product.info.details”&gt;引用我们的产品选项卡式导航作为一个整体,而子处理程序&lt;referenceBlock <span style="color: #569cd6;">name</span>=“product.info.description”&gt;在我们的案例详细信息选项卡中引用单个选项卡。</p><p>使用 &lt;参数名称=“title” <span style="color: #569cd6;">translate</span>=“true” xsi:<span style="color: #569cd6;">type</span>=“string”&gt;我们只需为选项卡设置新标题。 &lt;arguments&gt;处理程序只是&lt;argument&gt;的(必需)容器,它没有自己的属性。</p><p><span style="color: #6a9955;">### 删除产品选项卡</span></p><p>这个更简单。我们只需要引用我们的目标块并将 remove 属性设置为 true。所以我们看起来像这样:catalog_product_view.xml</p><pre class="brush:bash;toolbar:false">&lt;?xml&nbsp;version=&quot;1.0&quot;?&gt; &lt;page&nbsp;layout=&quot;1column&quot;&nbsp;xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;;;&nbsp;xsi:noNamespaceSchemaLocation=&quot;urn:magento:framework:View/Layout/etc/page_configuration.xsd&quot;&gt; &nbsp;&nbsp;&lt;body&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;referenceBlock&nbsp;name=&quot;product.info.review&quot;&nbsp;remove=&quot;true&quot;&nbsp;/&gt; &nbsp;&nbsp;&lt;/body&gt; &lt;/page&gt;</pre><p><span style="color: #6a9955;">### 添加自定义选项卡</span></p><p>现在,假设我们想在产品信息选项卡中创建一个额外的选项卡,并用内容填充它,例如某些特定属性的值。出于演示目的,假设我们的新选项卡将包含有关产品包装内容的信息。</p><p>首先,从Magento管理员那里,我们将创建新属性,让我们命名它并将其添加到属性集中。</p><p>接下来,我们将: – 创建新的模板文件,我们可以命名它 – 保存它</p><p>: – 粘贴以下代码:</p><p>Packagingdefaultpackaging-content.phtmlapp/design/frontend/&lt;Vendor&gt;/&lt;Theme&gt;/Magento_Catalog/templates/product/view/</p><p></p><pre class="brush:bash;toolbar:false">&lt;?php $_helper&nbsp;=&nbsp;$this-&gt;helper(&#39;Magento\Catalog\Helper\Output&#39;); $_product&nbsp;=&nbsp;$block-&gt;getProduct(); $_code&nbsp;=&nbsp;$block-&gt;getAtCode(); $_className&nbsp;=&nbsp;$block-&gt;getCssClass(); $_attributeLabel&nbsp;=&nbsp;$block-&gt;getAtLabel(); $_attributeType&nbsp;=&nbsp;$block-&gt;getAtType(); $_attributeAddAttribute&nbsp;=&nbsp;$block-&gt;getAddAttribute(); if&nbsp;($_attributeLabel&nbsp;&amp;&amp;&nbsp;$_attributeLabel&nbsp;==&nbsp;&#39;default&#39;)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;$_attributeLabel&nbsp;=&nbsp;$_product-&gt;getResource()-&gt;getAttribute($_code)-&gt;getFrontendLabel(); } &nbsp;&nbsp;$_attributeValue&nbsp;=&nbsp;$_product-&gt;getResource()-&gt;getAttribute($_code)-&gt;getFrontend()-&gt;getValue($_product); ?&gt; &nbsp; &lt;?php&nbsp;if&nbsp;($_attributeValue):&nbsp;?&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;div&nbsp;class=&quot;packaging-content&quot;&nbsp;&lt;?php&nbsp;&nbsp;echo&nbsp;$_attributeAddAttribute;?&gt;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;?php&nbsp;echo&nbsp;$_attributeValue;&nbsp;?&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/div&gt; &lt;?php&nbsp;endif;&nbsp;?&gt;</pre><p>注意:属性集(从第一步开始)必须与 if 语句中的字符串值匹配(行:9)</p><p>第三步也是最后一步是将以下代码放在我们的布局文件中:catalog_product_view.xml</p><p></p><pre class="brush:bash;toolbar:false">&lt;?xml&nbsp;version=&quot;1.0&quot;?&gt; &lt;page&nbsp;layout=&quot;1column&quot;&nbsp;xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;;;&nbsp;xsi:noNamespaceSchemaLocation=&quot;urn:magento:framework:View/Layout/etc/page_configuration.xsd&quot;&gt; &nbsp;&nbsp;&lt;body&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;referenceBlock&nbsp;name=&quot;product.info.details&quot;&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;block&nbsp;class=&quot;Magento\Catalog\Block\Product\View\Description&quot;&nbsp;name=&quot;packaging-content&quot;&nbsp;template=&quot;Magento_Catalog::product/view/packaging-content.phtml&quot;&nbsp;group=&quot;detailed_info&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;arguments&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;argument&nbsp;name=&quot;at_call&quot;&nbsp;xsi:type=&quot;string&quot;&gt;getPackaging&lt;/argument&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;argument&nbsp;name=&quot;at_code&quot;&nbsp;xsi:type=&quot;string&quot;&gt;packaging&lt;/argument&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;argument&nbsp;name=&quot;css_class&quot;&nbsp;xsi:type=&quot;string&quot;&gt;packaging&lt;/argument&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;argument&nbsp;name=&quot;at_label&quot;&nbsp;xsi:type=&quot;string”&gt;packaging&lt;/argument&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;argument&nbsp;name=&quot;add_attribute&quot;&nbsp;xsi:type=&quot;string&quot;&gt;itemprop=&quot;packaging&quot;&lt;/argument&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;argument&nbsp;name=&quot;title&quot;&nbsp;translate=&quot;true&quot;&nbsp;xsi:type=&quot;string&quot;&gt;Packaging&nbsp;content&lt;/argument&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/arguments&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/block&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/referenceBlock&gt; &nbsp;&nbsp;&lt;/body&gt; &lt;/page&gt;</pre><p><span style="color: #ce9178;">### 在选项卡式导航中添加相关产品</span></p><p><span style="color: #ce9178;">为了添加相关产品,我们还需要两个文件,模板和布局: 我们的模板文件,我们将命名它并保存它,只有一行代码:</span></p><p><span style="color: #ce9178;">related-products.phtmlapp/design/frontend/&lt;Vendor&gt;/&lt;Theme&gt;/Magento_Catalog/templates/product/</span></p><pre class="brush:bash;toolbar:false">&lt;?php&nbsp;echo&nbsp;$this-&gt;getBlockHtml(&#39;catalog.product.related&#39;);&nbsp;?&gt;</pre><p><span style="color: #ce9178;">我们的布局文件应如下所示:catalog_product_view.xml</span></p><p><span style="color: #ce9178;"></span></p><pre class="brush:bash;toolbar:false">&lt;?xml&nbsp;version=&quot;1.0&quot;?&gt; &lt;page&nbsp;layout=&quot;1column&quot;&nbsp;xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;;;&nbsp;xsi:noNamespaceSchemaLocation=&quot;urn:magento:framework:View/Layout/etc/page_configuration.xsd&quot;&gt; &nbsp;&nbsp;&lt;body&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;!—&nbsp;1st&nbsp;Code&nbsp;Block:&nbsp;Get&nbsp;Related&nbsp;Products&nbsp;as&nbsp;new&nbsp;tab&nbsp;--&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;referenceBlock&nbsp;name=&quot;product.info.details&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;block&nbsp;class=&quot;Magento\Catalog\Block\Product\View&quot;&nbsp;name=&quot;deliveryinfo.tab&quot;&nbsp;as=&quot;deliveryinfo&quot;&nbsp;template=&quot;Magento_Catalog::product/related-products.phtml&quot;&nbsp;group=&quot;detailed_info&quot;&nbsp;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;arguments&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;argument&nbsp;translate=&quot;true&quot;&nbsp;name=&quot;title&quot;&nbsp;xsi:type=&quot;string&quot;&gt;Related&nbsp;Products&lt;/argument&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/arguments&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/block&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/referenceBlock&gt; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&lt;!—&nbsp;2nd&nbsp;Code&nbsp;Block:&nbsp;Move&nbsp;original&nbsp;block&nbsp;to&nbsp;product&nbsp;info&nbsp;tabs&nbsp;--&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;move&nbsp;element=&quot;catalog.product.related&quot;&nbsp;destination=&quot;product.info.details&quot;&nbsp;/&gt; &nbsp;&nbsp;&lt;/body&gt; &lt;/page&gt;</pre><p><span style="color: #ce9178;"></span><br/></p><p><span style="color: #ce9178;">第一个代码块是设置包含相关产品的新选项卡,第二个代码块用于从布局流中删除原始块。</span></p><p><span style="color: #ce9178;">以类似的方式,也可以这样做来显示追加销售产品。我们需要做的就是将我们的模板(我们可以命名)文件更改为:upsell-products.phtml</span></p><p><span style="color: #ce9178;">&lt;?php echo $this-&gt;getBlockHtml(&#39;product.info.upsell&#39;); ?&gt;</span></p><p><span style="color: #ce9178;">在我们的布局文件中更改: – 模板文件的名称为 (行: 6) – 选项卡标题为“您可能感兴趣”或类似内容(行: 8) – 元素属性为 (行:</span></p><p><span style="color: #ce9178;">14)</span></p><p><span style="color: #ce9178;">upsell-products.phtmlproduct.info.upsell</span></p><p><span style="color: #ce9178;">总结</span></p><p><span style="color: #ce9178;">从这些示例中可以看出,自定义产品页面选项卡式导航相当容易。添加一些用于样式的CSS,您将在几个小时内拥有带有新自定义内容的新标签。</span></p><p><br/></p>

Magento 2小部件–相册小部件应用–客户推荐展示

<h5 style="color:red;">系统学习magento二次开发,推荐小册:<a style="color:blue;" href="https://www.maxiaoke.com/manual/magento_cn_dev.html" target="_blank">《Magento中文全栈二次开发 》</a></h5> <div class="image-container"> <p> <a style="color:blue;" href="https://www.maxiaoke.com/manual/magento_cn_dev.html" target="_blank"> <img src="https://www.maxiaoke.com/uploads/images/20230218/bb9c82995c24d1105676e02f373755f5.jpg" alt="Magento中文全栈二次开发"> </a> </p> </div> <div class="text-container" style="font-size:14px; color:#888"> <p>本小册面向Magento2以上版本,书代码及示例兼容magento2.0-2.4版本。涵盖了magento前端开发,后端开发,magento2主题,magento2重写,magento2 layout,magento2控制器,magento2 block等相关内容,带领您成为magento开发技术专家。</p> </div> <hr><p>继我们之前关于Magento图库小部件的文章(其中我们解释了如何构建图像库)之后,我们想展示这个小部件的另一种可能用途。因为它基于Fotorama插件,所以画廊小部件不仅可以处理图像,还可以处理其他HTML内容。我们将通过构建客户推荐库来演示如何,我们将在网店的页脚中显示该库。</p><p>我们需要的第一件事是带有实际推荐的 HTML。我们可以选择两个地方之一来存储我们的HTML内容。</p><p><span style="color: #6a9955;">### 模板文件中的库内容</span></p><p>构建推荐滑块的一种方法是将所有 HTML 标记放在一个模板文件中<span style="color: #6a9955;">;我们可以命名它.为了便于编辑和自定义,我们还将调用图库小部件的脚本放在同一个文件中,因此我们的模板将具有以下代码:client-testimonials.phtml</span></p><pre class="brush:bash;toolbar:false">&lt;--&nbsp;Container&nbsp;for&nbsp;testimonials&nbsp;--&gt; &lt;ul&nbsp;class=&quot;testimonials&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;li&gt;Testimonial&nbsp;#1&lt;/li&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;li&gt;Testimonial&nbsp;#2&lt;/li&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;li&gt;Testimonial&nbsp;#3&lt;/li&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;li&gt;...&lt;/li&gt; &lt;/ul&gt; &lt;--&nbsp;Script&nbsp;that&nbsp;calls&nbsp;gallery&nbsp;widget&nbsp;--&gt; &lt;script&gt; require&nbsp;([ &#39;jquery&#39;, &#39;mage/gallery/gallery&#39; ],&nbsp;function&nbsp;($,&nbsp;Gallery)&nbsp;{ &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;$(function&nbsp;()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;parse&nbsp;HTML&nbsp;to&nbsp;get&nbsp;client&nbsp;testimonials&nbsp;in&nbsp;array&nbsp;of&nbsp;objects &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;testimonialsList&nbsp;=&nbsp;document.querySelectorAll(&quot;.testimonials&nbsp;li&quot;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;data&nbsp;=&nbsp;[]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;i; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;testimonialsList.length;&nbsp;i++)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;obj&nbsp;=&nbsp;{&nbsp;html:&nbsp;testimonialsList[i].outerHTML}; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data.push(obj); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(&#39;.testimonials&#39;)&nbsp;//&nbsp;we&nbsp;expect&nbsp;that&nbsp;page&nbsp;contains&nbsp;markup&nbsp;tag&nbsp;with&nbsp;class&nbsp;.testimonials &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.each(function&nbsp;(index,&nbsp;element)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Gallery({ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;options:&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;nav&quot;:&nbsp;&quot;dots&quot;, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data:&nbsp;data,&nbsp;//&nbsp;contains&nbsp;previously&nbsp;parsed&nbsp;testimonials &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fullscreen:&nbsp;{} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},&nbsp;element);&nbsp;//&nbsp;&#39;element&#39;&nbsp;is&nbsp;simgle&nbsp;DOM&nbsp;node. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}); &nbsp;&nbsp;&nbsp;&nbsp;}); }); &lt;/script&gt;</pre><p>在上面的代码中,与我们上一篇文章相比,图片库的唯一区别是组的内容。与图像库不同,其中组指定图像的路径,这里的组包含我们之前解析并保存在数组中的HTML内容(作为对象数组)。datadatadatadata</p><p>由于我们已经提到我们希望推荐显示在网站页脚中,因此我们将文件放在主题的文件夹中,并通过内部文件夹引用它:testimonials.phtmlMagento_Theme/templatedefault.xmlMagento_Theme/layout</p><pre class="brush:bash;toolbar:false">&lt;referenceContainer&nbsp;name=&quot;footer-container&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;block&nbsp;class=&quot;Magento\Framework\View\Element\Template&quot;&nbsp;name=&quot;testimonials&quot;&nbsp;template=&quot;Magento_Cms::testimonials.phtml&quot;&nbsp;before=&quot;-&quot;&gt;&lt;/block&gt; &lt;/referenceContainer&gt;</pre><p>对于初学者,我们需要将我们的 HTML 标记(从)复制/粘贴到我们的静态块中。至于javascript,我们建议不要将其放在静态块中,因为js脚本中的非自愿和意外更改或拼写错误可能会破坏整个图库。这就是为什么最好将javascript保存为我们主题文件夹中的单独文件并声明它是使用requireJs的配置文件的原因。</p><pre class="brush:bash;toolbar:false">testimonials.phtmlweb/jsrequirejs-config.js var&nbsp;config&nbsp;=&nbsp;{ &nbsp;&nbsp;&quot;map&quot;:&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&quot;*&quot;:&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;testimonials&quot;:&nbsp;&quot;js/testimonials&quot;, &nbsp;&nbsp;&nbsp;&nbsp;}, &nbsp;&nbsp;}, };</pre><p>但是,我们仍然需要在静态块中调用脚本,而Magento 2的方法是使用以下属性:data-mage-init</p><pre class="brush:bash;toolbar:false">&lt;ul&nbsp;class=&quot;testimonials&quot;&nbsp;data-mage-init=&#39;{&quot;testimonials&quot;:{}}&#39;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;Client&nbsp;testimonials&nbsp;--&gt; &lt;/ul&gt;</pre><p>我们快完成了。在最后一步中,我们需要更新布局文件中的说明,因为我们正在调用静态块而不是模板文件,该文件不再有用,可以从我们的代码库中删除:default.xml</p><pre class="brush:bash;toolbar:false">&lt;referenceContainer&nbsp;name=“footer-container&quot;&gt; &nbsp;&nbsp;&lt;block&nbsp;class=&quot;Magento\Cms\Block\Block&quot;&nbsp;name=&quot;testimonials&quot;&nbsp;before=&quot;-&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;arguments&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;argument&nbsp;name=&quot;block_id&quot;&nbsp;xsi:type=“string&quot;&gt;testimonials&lt;/argument&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/arguments&gt; &nbsp;&nbsp;&nbsp;&lt;/block&gt; &lt;/referenceContainer&gt;</pre><p>至于功能,我们的内容库已经完成。剩下要做的就是参考网站的风格指南并开始使用 (s)css 来添加一些样式并在视觉上增强它。</p><p><span style="color: #6a9955;">### 总结</span></p><p>希望在这个关于Magento画廊小部件的迷你两部分系列中,我们为您提供了足够的输入来构建自己的画廊,图像或HTML内容的天气。正如我们已经提到的,小部件基于Fotorama插件,因此继承了它的所有优点和缺点。</p><p>我们认为使用此小部件的最大缺点是它仅限于每张幻灯片的一个项目(图像)。另外值得注意的是,Fotorama插件不再被维护,Magento团队可能会决定在未来的软件版本中放弃使用它,并在其他插件上构建他们的画廊小部件。</p><p>但是,目前,此小部件可以安全使用<span style="color: #6a9955;">;如果不在生产阶段,则处于开发阶段,以便于原型设计和布局试验。</span></p>

如何在Magento 2结帐(结算)页面中显示CMS内容

<h5 style="color:red;">系统学习magento二次开发,推荐小册:<a style="color:blue;" href="https://www.maxiaoke.com/manual/magento_cn_dev.html" target="_blank">《Magento中文全栈二次开发 》</a></h5> <div class="image-container"> <p> <a style="color:blue;" href="https://www.maxiaoke.com/manual/magento_cn_dev.html" target="_blank"> <img src="https://www.maxiaoke.com/uploads/images/20230218/bb9c82995c24d1105676e02f373755f5.jpg" alt="Magento中文全栈二次开发"> </a> </p> </div> <div class="text-container" style="font-size:14px; color:#888"> <p>本小册面向Magento2以上版本,书代码及示例兼容magento2.0-2.4版本。涵盖了magento前端开发,后端开发,magento2主题,magento2重写,magento2 layout,magento2控制器,magento2 block等相关内容,带领您成为magento开发技术专家。</p> </div> <hr><p>使用CMS块是Magento过去和现在如此受欢迎的原因之一。使用 CMS 块,站点管理员可以轻松操作商店的内容。CMS块可用于显示促销横幅,销售块,退货政策,商店某些部分的重要信息消息等。 CMS块可以携带纯文本或HTML / JS/CSS代码块,这意味着它们可以用于更复杂的内容交付,如滑块,产品轮播等。</p><p>我个人喜欢尽可能使用CMS块,以便商店的内容变得更加“模块化”且易于管理。</p><p>结账时的CMS块可以有很多用途,例如显示某些促销内容的特定运输方式的一些信息,以说服用户在结帐前花费更多。</p><p>将CMS块添加到某些特定位置/页面并不麻烦,我们只需要在布局中“注册”我们的CMS块并定义CMS块的顺序/位置。然后我们需要在模板中调用它,仅此而已。CMS 块现在是内容的一部分,将在需要时呈现/交付。</p><p>将CMS块添加到Magento 2 Checkout是一项更复杂的任务,因为整个结帐是由一系列KnockoutJS组件构建的,然后使用Knockout.js模板系统进行渲染。Magento 2在一个大型XML文件中定义了这些组件及其相互关系。为了从服务器中提取数据,Magento使用全局Javascript变量window.checkoutConfig,然后由Knockout使用.js在前端计算和显示信息。</p><p>简而言之,整个结帐是动态加载的,我们不能在里面放任何“静态”的东西。</p><p>希望有一种方法可以在结帐流程中插入CMS块。</p><p>由于整个结帐是从各种JS组件捆绑而来的,因此此任务的方法将根据CMS块位置而有所不同。但是,每种方法都有相同的初始步骤。</p><p>想法是从CMS块中获取内容并将其放入JS对象中,然后通过挖空绑定输出到前端。这样,我们的 CMS 内容就会成为结帐流程的一部分,并与其他组件一起加载。如果您想与组件一起闲逛,请充当组件!</p><p><span style="color: #6a9955;">### 创建模块</span></p><p>如果您不知道如何创建Magento 2模块,请按照我的同事Hrvoje Ivancic的这篇文章中的步骤进行操作。</p><p>我建议您使用 netz98 magerun CLI 工具扩展,这是开发过程中的有用资产。例如,您可以使用一个命令创建一个包含所有必要文件的模块。</p><p>根据需要命名模块。我将使用供应商作为供应商,使用模块名称作为模块名称。</p><p>创建包含所有必要文件的模块后,我们将添加/编辑其中的一些文件以实现我们的目标。</p><p>请不要忘记在创建模块后进行设置:升级。</p><p>在结帐侧边栏中添加 CMS 块</p><p>编辑Vendor/ModuleName/etc/frontend/di.xml文件:</p><pre class="brush:bash;toolbar:false">&lt;?xml&nbsp;version=&quot;1.0&quot;?&gt; &lt;config&nbsp;xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xsi:noNamespaceSchemaLocation=&quot;urn:magento:framework:ObjectManager/etc/config.xsd&quot;&gt; &nbsp;&nbsp;&nbsp;&lt;type&nbsp;name=&quot;Magento\Checkout\Model\CompositeConfigProvider&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;arguments&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;argument&nbsp;name=&quot;configProviders&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;cms_block_config_provider&quot;&nbsp;xsi:type=&quot;object&quot;&gt;Vendor\ModuleName\Model\ConfigProvider&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/argument&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/arguments&gt; &nbsp;&nbsp;&nbsp;&lt;/type&gt; &nbsp;&nbsp;&nbsp;&lt;type&nbsp;name=&quot;Vendor\ModuleName\Model\ConfigProvider&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;arguments&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;argument&nbsp;name=&quot;blockId&quot;&nbsp;xsi:type=&quot;string&quot;&gt;checkout_cms_block&lt;/argument&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/arguments&gt; &nbsp;&nbsp;&nbsp;&lt;/type&gt; &lt;/config&gt;</pre><p>使用此代码,我们将向 ConfigProvider 添加新条目,并且我们还声明了将用于解析数据的 CMS 块。</p><p>在上面的例子中,一个块被命名为“checkout_cms_block”(它与块的id或标识符一起工作)。</p><p>请确保 和 路径与您的块名称匹配。在上面的示例中,路径是供应商\模块名称\模型\配置提供者。</p><p>接下来,我们将通过创建或编辑Vendor/ModuleName/Model/ConfigProvider.php来为配置提供程序创建新条目:</p><pre class="brush:bash;toolbar:false">&lt;?php&nbsp;namespace&nbsp;Vendor\ModuleName\Model; &nbsp; use&nbsp;Magento\Checkout\Model\ConfigProviderInterface; use&nbsp;Magento\Framework\View\LayoutInterface; &nbsp; class&nbsp;ConfigProvider&nbsp;implements&nbsp;ConfigProviderInterface { &nbsp;&nbsp;&nbsp;/**&nbsp;@var&nbsp;LayoutInterface&nbsp;&nbsp;*/ &nbsp;&nbsp;&nbsp;protected&nbsp;$_layout; &nbsp;&nbsp;&nbsp;protected&nbsp;$cmsBlock; &nbsp; &nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;__construct(LayoutInterface&nbsp;$layout,&nbsp;$blockId) &nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;_layout&nbsp;=&nbsp;$layout; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;cmsBlock&nbsp;=&nbsp;$this-&gt;constructBlock($blockId); &nbsp;&nbsp;&nbsp;} &nbsp; &nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;constructBlock($blockId){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$block&nbsp;=&nbsp;$this-&gt;_layout-&gt;createBlock(&#39;Magento\Cms\Block\Block&#39;) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&gt;setBlockId($blockId)-&gt;toHtml(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$block; &nbsp;&nbsp;&nbsp;} &nbsp; &nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;getConfig() &nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;[ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;cms_block&#39;&nbsp;=&gt;&nbsp;$this-&gt;cmsBlock &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]; &nbsp;&nbsp;&nbsp;} }</pre><p>由于我们已将自己的变量添加到全局 window.checkoutConfig 变量中,我们现在可以使用window.checkoutConfig.cms_block变量调用该内容。</p><p>现在我们只需要将该变量绑定到某个 HTML 元素,Knockout .JS 将完成剩下的工作。</p><p>这是 app/design/frontend/Vendor/ThemeName/Magento_Checkout/web/template/sidebar.html</p><p><br/></p><pre class="brush:bash;toolbar:false">&lt;div&nbsp;id=&quot;opc-sidebar&quot; &nbsp;&nbsp;&nbsp;&nbsp;data-bind=&quot;afterRender:setModalElement,&nbsp;mageInit:&nbsp;{ &nbsp;&nbsp;&nbsp;&#39;Magento_Ui/js/modal/modal&#39;:{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;type&#39;:&nbsp;&#39;custom&#39;, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;modalClass&#39;:&nbsp;&#39;opc-sidebar&nbsp;opc-summary-wrapper&#39;, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;wrapperClass&#39;:&nbsp;&#39;checkout-container&#39;, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;parentModalClass&#39;:&nbsp;&#39;_has-modal-custom&#39;, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;responsive&#39;:&nbsp;true, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;responsiveClass&#39;:&nbsp;&#39;custom-slide&#39;, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;overlayClass&#39;:&nbsp;&#39;modal-custom-overlay&#39;, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;buttons&#39;:&nbsp;[] &nbsp;&nbsp;&nbsp;}}&quot;&gt; &nbsp; &nbsp;&nbsp;&nbsp;&lt;!--&nbsp;ko&nbsp;foreach:&nbsp;getRegion(&#39;summary&#39;)&nbsp;--&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;ko&nbsp;template:&nbsp;getTemplate()&nbsp;--&gt;&lt;!--&nbsp;/ko&nbsp;--&gt; &nbsp;&nbsp;&nbsp;&lt;!--/ko--&gt; &nbsp; &nbsp;&nbsp;&nbsp;&lt;div&nbsp;data-bind=&quot;html:&nbsp;window.checkoutConfig.cms_block&quot;&gt;&lt;/div&gt; &nbsp; &nbsp;&nbsp;&nbsp;&lt;div&nbsp;class=&quot;opc-block-shipping-information&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;ko&nbsp;foreach:&nbsp;getRegion(&#39;shipping-information&#39;)&nbsp;--&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;ko&nbsp;template:&nbsp;getTemplate()&nbsp;--&gt;&lt;!--&nbsp;/ko&nbsp;--&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--/ko--&gt; &nbsp;&nbsp;&nbsp;&lt;/div&gt; &lt;/div&gt;</pre><p>如果您做对了一切,您应该会在侧边栏中看到您的 CMS 块。</p><p>请注意,我已经在我的包/主题中创建了sidebar.html模板。切勿直接在Vendor/magento/* 文件夹中编辑文件。</p><p><span style="color: #6a9955;">### 将 CMS 块添加到地址表单</span></p><p>对于此任务,我们将使用一些不同的方法。</p><p>我们将app/code/Vendor/ModuleName/Model/ConfigProvider.php</p><p>更改为:</p><pre class="brush:bash;toolbar:false">&lt;?php &nbsp; namespace&nbsp;Vendor\ModuleName\Model; &nbsp; &nbsp; use&nbsp;Magento\Checkout\Model\ConfigProviderInterface; use&nbsp;Magento\Cms\Block\Widget\Block; &nbsp; class&nbsp;ConfigProvider&nbsp;implements&nbsp;ConfigProviderInterface { &nbsp;&nbsp;&nbsp;protected&nbsp;$cmsBlockWidget; &nbsp; &nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;__construct(Block&nbsp;$block,&nbsp;$blockId) &nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;cmsBlockWidget&nbsp;=&nbsp;$block; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$block-&gt;setData(&#39;block_id&#39;,&nbsp;$blockId); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$block-&gt;setTemplate(&#39;Magento_Cms::widget/static_block/default.phtml&#39;); &nbsp;&nbsp;&nbsp;} &nbsp; &nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;getConfig() &nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;[ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;cms_block&#39;&nbsp;=&gt;&nbsp;$this-&gt;cmsBlockWidget-&gt;toHtml() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]; &nbsp;&nbsp;&nbsp;} }</pre><p>然后,</p><p>使用以下内容创建应用/code/Vendor/ModuleName/view/frontend/layout/checkout_index_index.xml:</p><pre class="brush:bash;toolbar:false">&lt;?xml&nbsp;version=&quot;1.0&quot;?&gt; &nbsp; &lt;page&nbsp;xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&nbsp;layout=&quot;checkout&quot;&nbsp;xsi:noNamespaceSchemaLocation=&quot;urn:magento:framework:View/Layout/etc/page_configuration.xsd&quot;&gt; &nbsp;&nbsp;&nbsp;&lt;body&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;referenceBlock&nbsp;name=&quot;checkout.root&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;arguments&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;argument&nbsp;name=&quot;jsLayout&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;components&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;checkout&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;children&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;steps&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;children&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;shipping-step&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;children&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;shippingAddress&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;children&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;shipping-address-fieldset&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;children&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;cms-block&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;component&quot;&nbsp;xsi:type=&quot;string&quot;&gt;uiComponent&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;config&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;template&quot;&nbsp;xsi:type=&quot;string&quot;&gt;Vendor_ModuleName/cms-block&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;sortOrder&quot;&nbsp;xsi:type=&quot;string&quot;&gt;1&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/argument&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/arguments&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/referenceBlock&gt; &nbsp;&nbsp;&nbsp;&lt;/body&gt; &lt;/page&gt;</pre><p>现在,我们已将新的 UI 组件添加到地址窗体中。该组件将保存我们的 CMS 块的内容。正如我上面提到的,组件加载顺序在XML文件中管理。如您所见,我已经为 sortOrder 设置了 1,这意味着我的组件将首先加载到地址表单中。</p><p>注意此行Vendor_ModuleName/cms-block并更改它。</p><p>现在我们已经设置好了一切,我们只需要一个挖空模板来输出 CMS 块数据。</p><p>使用此内容创建 app/code/Vendor/ModuleName/view/frontend/web/template/cms-block.html:</p><pre class="brush:bash;toolbar:false">&lt;div&nbsp;data-bind=&quot;html:&nbsp;window.checkoutConfig.cms_block&quot;&gt;&lt;/div&gt;</pre><p>仅此而已。现在,您的CMS块应以地址形式显示并首先呈现。<br/></p><p>给定的示例适用于干净的Magento 2.2安装。Luma主题用于测试目的。</p><p>如果出现问题,请检查:</p><p>您的模块是否正确创建并包含所有具有正确值的配置文件?</p><p>您是否在创建模块后运行了PHP bin/magento setup:upgrade?</p><p>通过将Vendor/ModuleName替换为正确的供应商和模块名称来检查您是否正确更改了本文中的代码!</p><p><br/></p>

在Magento 2中购物结算页面的运费计算页面的字段排序

<h5 style="color:red;">系统学习magento二次开发,推荐小册:<a style="color:blue;" href="https://www.maxiaoke.com/manual/magento_cn_dev.html" target="_blank">《Magento中文全栈二次开发 》</a></h5> <div class="image-container"> <p> <a style="color:blue;" href="https://www.maxiaoke.com/manual/magento_cn_dev.html" target="_blank"> <img src="https://www.maxiaoke.com/uploads/images/20230218/bb9c82995c24d1105676e02f373755f5.jpg" alt="Magento中文全栈二次开发"> </a> </p> </div> <div class="text-container" style="font-size:14px; color:#888"> <p>本小册面向Magento2以上版本,书代码及示例兼容magento2.0-2.4版本。涵盖了magento前端开发,后端开发,magento2主题,magento2重写,magento2 layout,magento2控制器,magento2 block等相关内容,带领您成为magento开发技术专家。</p> </div> <hr><p>随着时间的流逝,我们越来越熟悉Magento 2结帐。我们正在努力进一步建立我们的知识。希望本文能在此过程中为您提供帮助。在本文中,我们将学习如何更改结帐页面上的输入字段顺序。</p><p>如果您曾经测试过Magento 2,那么您熟悉默认的Magento 2 Checkout和默认字段的排序顺序。</p><p>对于美国或其他一些国家/地区(州/省是重要且必填字段)的地址,此顺序是完全可以理解的。但在大多数欧洲国家,州/省字段并不重要。在这里,大多数欧盟客户期望其他一些字段,例如此处邮政编码或国家/地区具有更高的优先级。</p><p>请记住,我们希望更改默认的Magento结帐字段排序顺序以满足我们的需求。因此,我们的目标是实现这一目标:</p><p>此外,我们希望保持一致性,考虑了所有结帐步骤,因此我们将对运输和计费步骤中的输入字段重新排序。</p><p><span style="color: #6a9955;">### 运输步骤</span></p><p>在运输步骤中重新排序字段是一项简单的任务,我们只需要知道相关字段的排序顺序值和一些xml Magento 2特定命令。</p><p>首先,我们需要有自己的布局覆盖。如果您没有它,请创建新的xml文件,以便我们可以以正确的Magento方式操作结帐布局。文件需要位于以下路径上:checkout_index_indexcheckout_index_index</p><p>/app/design/frontend/Vendor/themeName/Magento_Checkout/layout/checkout_index_index.xml</p><p>新的布局文件需要具有结构清晰的树,以便定位正确的元素 Checkout UI 组件,如下所示:</p><pre class="brush:bash;toolbar:false">&lt;referenceBlock&nbsp;name=&quot;checkout.root&quot;&gt; &lt;arguments&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;argument&nbsp;name=&quot;jsLayout&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;components&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;checkout&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;children&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;steps&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;children&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;shipping-step&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;children&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;shippingAddress&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;children&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;The&nbsp;name&nbsp;of&nbsp;the&nbsp;form&nbsp;the&nbsp;field&nbsp;belongs&nbsp;to&nbsp;--&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;shipping-address-fieldset&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;children&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!—&nbsp;Start:&nbsp;Important&nbsp;part&nbsp;—&gt; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;postcode&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;sortOrder&quot;&nbsp;xsi:type=&quot;string&quot;&gt;71&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/item&gt; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;country_id&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;sortOrder&quot;&nbsp;xsi:type=&quot;string&quot;&gt;81&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!—&nbsp;End:&nbsp;Important&nbsp;part:&nbsp;—&gt; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/argument&gt; &lt;/arguments&gt; &lt;/referenceBlock&gt;</pre><p>有很多嵌套和很多子元素。但是在该项目下,我们针对两个表示输入字段的子元素。如果您仔细观察,您会注意到我们试图定位:shippingAddress</p><p><span style="color: #6a9955;">### 邮政编码字段 (postcode)</span></p><p>提交的国家 (country_id)</p><p>为了改变这些元素(邮政编码和国家/地区)的位置,我们需要用适合我们的想法的值更新值,以便更好地排序。默认情况下,sortOrder 值为 110,值为 115。我们已经用 71 和 81 更新了它们,在这种情况下,目标字段将很好地适应我们的新布局。sortOrderingpostcodecountry_id</p><p>清除您的Magento缓存。重新加载结帐页面,您会注意到更改。</p><p>我们还需要指出的是,XML布局更新也会影响结帐地址弹出窗口,当注册客户希望在第一个结帐步骤中使用现有地址添加新地址时,该弹出窗口将可见。</p><p>现在让我们调整计费步骤。</p><p><span style="color: #6a9955;">### 计费步骤</span></p><p>更改计费步骤请求不同的方法,然后是运输步骤。原因是计费步骤建立在动态 UI 组件上。目前,这里要知道的最重要的事情是,在计费步骤中,每种付款方式使用不同的计费地址表单(每种付款方式的不同组件)。因此,考虑到这一点,我们需要对结帐时使用的所有付款方式应用布局更改。但出于本文的目的,我们将只介绍支票/货币付款方式。</p><p>我们将通过扩展计费步骤的默认Magento布局处理器接口来做到这一点。这将需要一些 PHP 后端调整。但考虑到必要的工作水平,做起来不会太复杂。请通过在签出、块目录下创建新的 PHP 类文件来扩展:LayoutProcessorInterface</p><p>/app/code/Vendor/Checkout/Block/LayoutProcessor.php</p><p>对于我们的起点将使用简单的函数检查:</p><p><br/></p><pre class="brush:bash;toolbar:false">namespace&nbsp;Inchoo\Checkout\Block; use&nbsp;Magento\Checkout\Block\Checkout\LayoutProcessorInterface; &nbsp; class&nbsp;LayoutProcessor&nbsp;implements&nbsp;LayoutProcessorInterface { &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;process($jsLayout) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$jsLayout; &nbsp;&nbsp;&nbsp;&nbsp;} }</pre><p>此外,我们需要为配置创建,以便Magento了解布局处理器更改。XML 文件将包含以下代码:di.xml</p><pre class="brush:bash;toolbar:false">&lt;?xml&nbsp;version=&quot;1.0&quot;?&gt; &lt;config&nbsp;xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&nbsp;xsi:noNamespaceSchemaLocation=&quot;urn:magento:framework:ObjectManager/etc/config.xsd&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;type&nbsp;name=&quot;Magento\Checkout\Block\Onepage&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;arguments&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;argument&nbsp;name=&quot;layoutProcessors&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;checkoutFieldsReorder&quot;&nbsp;xsi:type=&quot;object&quot;&gt;Inchoo\Checkout\Block\LayoutProcessor&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/argument&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/arguments&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/type&gt; &lt;/config&gt;</pre><p>我们需要确保在计费步骤中定位正确的 UI 组件。为此,请检查Magento敲除在前端给我们的JSON对象。您可以通过 IDE 或某些 JSON 在线编辑器执行此操作。在结帐 JSON 中查找要重新定位的元素的值。在 JSON 树之后,我们将声明数组的相同路径。所以基本上,我们将这样做:sortOrder$jsLayout</p><pre class="brush:bash;toolbar:false">namespace&nbsp;Inchoo\Checkout\Block; use&nbsp;Magento\Checkout\Block\Checkout\LayoutProcessorInterface; class&nbsp;LayoutProcessor&nbsp;implements&nbsp;LayoutProcessorInterface { &nbsp;&nbsp;&nbsp;&nbsp;/** &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Reposition&nbsp;postcode&nbsp;to&nbsp;be&nbsp;above&nbsp;city&nbsp;input,&nbsp;and&nbsp;country&nbsp;drop&nbsp;down&nbsp;to&nbsp;be&nbsp;above&nbsp;region &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;array&nbsp;$jsLayout &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;array &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;process($jsLayout) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$jsLayout[&#39;components&#39;][&#39;checkout&#39;][&#39;children&#39;][&#39;steps&#39;][&#39;children&#39;] &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&#39;billing-step&#39;][&#39;children&#39;][&#39;payment&#39;][&#39;children&#39;] &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&#39;payments-list&#39;][&#39;children&#39;][&#39;checkmo-form&#39;][&#39;children&#39;] &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&#39;form-fields&#39;][&#39;children&#39;][&#39;postcode&#39;][&#39;sortOrder&#39;]&nbsp;=&nbsp;71; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$jsLayout[&#39;components&#39;][&#39;checkout&#39;][&#39;children&#39;][&#39;steps&#39;][&#39;children&#39;] &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&#39;billing-step&#39;][&#39;children&#39;][&#39;payment&#39;][&#39;children&#39;] &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&#39;payments-list&#39;][&#39;children&#39;][&#39;checkmo-form&#39;][&#39;children&#39;] &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&#39;form-fields&#39;][&#39;children&#39;][&#39;country_id&#39;][&#39;sortOrder&#39;]&nbsp;=&nbsp;81; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$jsLayout; &nbsp;&nbsp;&nbsp;&nbsp;} }</pre><p>清除缓存并重新加载页面。您将看到更改。</p><p>如果您想更改其他方法的布局,请随时执行此操作。您只需要更换为您的付款方式即可。但请确保您在结帐时使用哪种方法。至少检查您的 JSON 对象以及您的项目下可用的表单。这样做的原因是有时可能看起来像这样:[<span style="color: #ce9178;">&#39;checkmo-form&#39;</span>]payment-listpayment-list</p><p>因此,很难猜测我们需要针对哪种形式。</p><p><br/></p><p><br/></p>

magento2如何将自定义的列添加到后台产品列表页中展示

<h5 style="color:red;">系统学习magento二次开发,推荐小册:<a style="color:blue;" href="https://www.maxiaoke.com/manual/magento_cn_dev.html" target="_blank">《Magento中文全栈二次开发 》</a></h5> <div class="image-container"> <p> <a style="color:blue;" href="https://www.maxiaoke.com/manual/magento_cn_dev.html" target="_blank"> <img src="https://www.maxiaoke.com/uploads/images/20230218/bb9c82995c24d1105676e02f373755f5.jpg" alt="Magento中文全栈二次开发"> </a> </p> </div> <div class="text-container" style="font-size:14px; color:#888"> <p>本小册面向Magento2以上版本,书代码及示例兼容magento2.0-2.4版本。涵盖了magento前端开发,后端开发,magento2主题,magento2重写,magento2 layout,magento2控制器,magento2 block等相关内容,带领您成为magento开发技术专家。</p> </div> <hr><p>如果要在列中显示的值是产品属性,则可以轻松地向产品网格添加列。它们已存在于列控件下的产品网格工具栏中。您只需选中/取消选中要从网格中显示或删除的列。但是,如果您想显示不是产品属性的数量和网站等值,该怎么办?如果您继续阅读,您将学习如何将这样的值添加到产品网格中。</p><p><span style="color: #6a9955;">### 介绍</span></p><p>由于可以为每个产品打开/关闭库存管理,因此我们将向产品网格添加一个新列,该列将在打开或关闭库存管理时显示。 对于所有代码示例,我创建了一个名为 Inchoo_Custom 的 Magento 2 模块。</p><p>如果你想学习如何创建一个Magento 2模块,你可以检查这个:如何在Magento 2中创建基本模块</p><p>重要的是,Magento的Magento_Catalog模块在我们的模块之前加载,这就是为什么我们将它添加到模块.xml文件中的序列标签下。</p><p>app/code/Inchoo/Custom/etc/module.xml</p><pre class="brush:bash;toolbar:false">&lt;?xml&nbsp;version=&quot;1.0&quot;&nbsp;encoding=&quot;utf-8&quot;&nbsp;?&gt; &lt;config&nbsp;xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&nbsp;xsi:noNamespaceSchemaLocation=&quot;urn:magento:framework:Module/etc/module.xsd&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;module&nbsp;name=&quot;Inchoo_Custom&quot;&nbsp;setup_version=&quot;1.0.0&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;sequence&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;module&nbsp;name=&quot;Magento_Catalog&quot;/&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/sequence&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/module&gt; &lt;/config&gt;</pre><p>编辑模块后.xml我们需要使用控制台命令更新应用程序/etc/config.php文件:</p><p>php bin/magento setup:upgrade</p><p><span style="color: #6a9955;">### 产品列表 UI 组件实例</span></p><p>渲染产品网格Magento 2使用名为product_listing的列表UI组件实例和XML配置文件,因为它是Magento_Catalog/view/adminhtml/ui_component/product_listing.xml。如果我们想自定义它,我们需要在我们的模块中创建一个具有相同路径和名称的文件。</p><p>app/code/Inchoo/Custom/view/adminhtml/ui_component/product_listing.xml</p><pre class="brush:bash;toolbar:false">&lt;?xml&nbsp;version=&quot;1.0&quot;&nbsp;encoding=&quot;utf-8&quot;?&gt; &lt;listing&nbsp;xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&nbsp;xsi:noNamespaceSchemaLocation=&quot;urn:magento:module:Magento_Ui:etc/ui_configuration.xsd&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;columns&nbsp;name=&quot;product_columns&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;column&nbsp;name=&quot;manage_stock&quot;&nbsp;component=&quot;Magento_Ui/js/grid/columns/select&quot;&nbsp;sortOrder=&quot;76&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;settings&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;addField&gt;true&lt;/addField&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;options&nbsp;class=&quot;Magento\Config\Model\Config\Source\Yesno&quot;/&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;filter&gt;select&lt;/filter&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;dataType&gt;select&lt;/dataType&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;sortable&gt;false&lt;/sortable&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;label&nbsp;translate=&quot;true&quot;&gt;Manage&nbsp;Stock&lt;/label&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/settings&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/column&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/columns&gt; &lt;/listing&gt;</pre><p>要添加新列,我们需要从原始配置文件中引用名为 product_columns 的列 UI 组件,并将新列添加到其中。我们将专栏命名为manage_stock标签“管理库存”。</p><p>运行此控制台命令以清理缓存:</p><p>php bin/magento cache:clean config</p><p>清理缓存后,我们应该在产品网格中看到我们的新列,但数据丢失。这是因为我们没有将库存管理数据添加到产品系列中。</p><p><span style="color: #6a9955;">### 产品列表数据提供程序</span></p><p>将库存管理数据添加到产品集合的最佳位置是 UI 组件实例使用的数据提供程序类product_listing。</p><p>Magento_Catalog/view/adminhtml/ui_component/product_listing.xml</p><pre class="brush:bash;toolbar:false">&lt;dataSource&nbsp;name=&quot;product_listing_data_source&quot;&nbsp;component=&quot;Magento_Ui/js/grid/provider&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;settings&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;storageConfig&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param&nbsp;name=&quot;dataScope&quot;&nbsp;xsi:type=&quot;string&quot;&gt;filters.store_id&lt;/param&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/storageConfig&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;updateUrl&nbsp;path=&quot;mui/index/render&quot;/&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/settings&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;aclResource&gt;Magento_Catalog::products&lt;/aclResource&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;dataProvider&nbsp;class=&quot;Magento\Catalog\Ui\DataProvider\Product\ProductDataProvider&quot;&nbsp;name=&quot;product_listing_data_source&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;settings&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;requestFieldName&gt;id&lt;/requestFieldName&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;primaryFieldName&gt;entity_id&lt;/primaryFieldName&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/settings&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/dataProvider&gt; &lt;/dataSource&gt;</pre><p>如果我们查看 dataSource UI 组件,我们将看到 dataProvider 类是 Magento\Catalog\Ui\DataProvider\Product\ProductDataProvider。</p><p>如果我们查看这个数据提供程序类,我们将看到两个属性 addFieldStrategies 和 addFilterStrategies。它们都是数组,具有我们可以对特定列(字段)的集合执行的其他策略。它们分别在数据提供程序的 addField 和 addFilter 方法中调用。我们将为我们的库存管理专栏创建自己的策略。</p><p><span style="color: #6a9955;">### 管理库存字段策略</span></p><p>首先,我们将创建一个字段策略,将库存管理状态添加到产品系列中。</p><p>Inchoo\Custom\UI\DataProvider\Product\AddManageStockFieldToCollection</p><pre class="brush:bash;toolbar:false">&lt;?php namespace&nbsp;Inchoo\Custom\Ui\DataProvider\Product;&nbsp; class&nbsp;AddManageStockFieldToCollection&nbsp;implements&nbsp;\Magento\Ui\DataProvider\AddFieldToCollectionInterface { &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;addField(\Magento\Framework\Data\Collection&nbsp;$collection,&nbsp;$field,&nbsp;$alias&nbsp;=&nbsp;null) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$collection-&gt;joinField(&#39;manage_stock&#39;,&nbsp;&#39;cataloginventory_stock_item&#39;,&nbsp;&#39;manage_stock&#39;,&nbsp;&#39;product_id=entity_id&#39;,&nbsp;null,&nbsp;&#39;left&#39;);&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;} }</pre><p>在AddManageStockFieldToCollection字段策略中,我们从Magento\Ui\DataProvider\AddFieldToCollection接口实现了addField方法。库存管理状态来自 DB 表中cataloginventory_stock_item manage_stock列。我们使用这些信息和Magento\Eav\Model\Entity\Collection\AbstractCollection::joinField方法将库存管理状态添加到产品集合中。</p><p><br/></p><p><span style="color: #6a9955;">### 管理库存过滤器策略</span></p><p>当有人想要按库存管理状态过滤网格数据时,我们需要创建此过滤策略。</p><p>Inchoo\Custom\UI\DataProvider\Product\AddManageStockFilterToCollection</p><pre class="brush:bash;toolbar:false">&lt;?php namespace&nbsp;Inchoo\Custom\Ui\DataProvider\Product;&nbsp; class&nbsp;AddManageStockFilterToCollection&nbsp;implements&nbsp;\Magento\Ui\DataProvider\AddFilterToCollectionInterface { &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;addFilter(\Magento\Framework\Data\Collection&nbsp;$collection,&nbsp;$field,&nbsp;$condition&nbsp;=&nbsp;null) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(isset($condition[&#39;eq&#39;]))&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$collection-&gt;addFieldToFilter($field,&nbsp;$condition);&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;} }</pre><p>在AddManageStockFilterToCollection过滤器策略中,我们实现了来自Magento\Ui\DataProvider\AddFilterToCollectionInterface的addFilter方法。如果网格按库存管理状态过滤,我们将过滤器条件转发到 Magento\Eav\Model\Entity\Collection\AbstractCollection::addFieldToFilter 方法。</p><p><span style="color: #6a9955;">### 向商品信息数据提供程序添加策略</span></p><p>如果我们想使用刚刚创建的策略,我们需要将它们添加到product_listing数据提供程序中。我们将在 di.xml 文件中执行此操作。</p><p>app/code/Inchoo/Custom/etc/adminhtml/di.xml</p><pre class="brush:bash;toolbar:false">&lt;?xml&nbsp;version=&quot;1.0&quot;&nbsp;encoding=&quot;utf-8&quot;&nbsp;?&gt; &lt;config&nbsp;xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&nbsp;xsi:noNamespaceSchemaLocation=&quot;urn:magento:framework:ObjectManager/etc/config.xsd&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;type&nbsp;name=&quot;Magento\Catalog\Ui\DataProvider\Product\ProductDataProvider&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;arguments&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;argument&nbsp;name=&quot;addFieldStrategies&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;manage_stock&quot;&nbsp;xsi:type=&quot;object&quot;&gt;Inchoo\Custom\Ui\DataProvider\Product\AddManageStockFieldToCollection&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/argument&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;argument&nbsp;name=&quot;addFilterStrategies&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;manage_stock&quot;&nbsp;xsi:type=&quot;object&quot;&gt;Inchoo\Custom\Ui\DataProvider\Product\AddManageStockFilterToCollection&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/argument&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/arguments&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/type&gt; &lt;/config&gt;</pre><p>运行此控制台命令以清理缓存:</p><p>php bin/magento cache:clean config</p><p>清理缓存后,我们应该在产品网格中看到包含数据的新列。</p><p><br/></p><p><img src="/uploads/images/20230821/04b28c15a19cde0d3fae48445a283315.jpg" title="3.jpg" alt=""/></p><p><br/></p>

使用Docker构建的magento2开发环境

<h5 style="color:red;">系统学习magento二次开发,推荐小册:<a style="color:blue;" href="https://www.maxiaoke.com/manual/magento_cn_dev.html" target="_blank">《Magento中文全栈二次开发 》</a></h5> <div class="image-container"> <p> <a style="color:blue;" href="https://www.maxiaoke.com/manual/magento_cn_dev.html" target="_blank"> <img src="https://www.maxiaoke.com/uploads/images/20230218/bb9c82995c24d1105676e02f373755f5.jpg" alt="Magento中文全栈二次开发"> </a> </p> </div> <div class="text-container" style="font-size:14px; color:#888"> <p>本小册面向Magento2以上版本,书代码及示例兼容magento2.0-2.4版本。涵盖了magento前端开发,后端开发,magento2主题,magento2重写,magento2 layout,magento2控制器,magento2 block等相关内容,带领您成为magento开发技术专家。</p> </div> <hr><p>很久以前,当我第一次开始使用PHP时,我确实在设置工作环境时遇到了麻烦。</p><p>我不知道自己在做什么。</p><p>不要问我怎么做,但我最终让Apache Tomcat运行PHP。</p><p>老实说,我不知道我今天能不能设置这样的亵渎。</p><p><br/></p><p>编辑注意:由于udovicic/echo:</p><p>apache-php7.1更新,你不再需要apache配置,所以我编辑了这篇文章并删除了apache配置。</p><p>多年来,我走了从xampp,手动LAMP设置,流浪汉的整个道路......</p><p>所有这些都至少有1个交易破坏者,特别是当我开始与Magento合作时。</p><p>最后,Docker的到来使开发变得更加容易。</p><p>在这一点上,解释Docker是什么变得有点棘手。</p><p>它执行操作系统级虚拟化(容器化),这是指内核允许存在多个隔离的用户空间实例的操作系统功能。</p><p>如果上面的句子对您没有任何意义,那么也许访问 http://www.docker.com 并在某个时候回到这里是明智的,否则,请继续阅读......</p><p>我现在要分享的不是一些Docker的智慧。它更多的是关于能够通过Docker运行Magento 2的设置,所以本文假设你对Docker有些熟悉。</p><p>所以,让我们开始...</p><p>让我们运行Magento 2,假设 http://m2.docker</p><p>你应该做的第一件事是在 /etc/hosts 文件中的某个位置添加此行:</p><p>127.0.0.1 m2.docker www.m2.docker</p><p>我们将需要一些文件系统结构,因此请执行以下操作:</p><pre class="brush:bash;toolbar:false">tomas&nbsp;~&nbsp;$&nbsp;mkdir&nbsp;m2.docker tomas&nbsp;~&nbsp;$&nbsp;cd&nbsp;m2.docker/ tomas&nbsp;~/m2.docker&nbsp;$&nbsp;mkdir&nbsp;docker tomas&nbsp;~/m2.docker&nbsp;$&nbsp;mkdir&nbsp;html tomas&nbsp;~/m2.docker&nbsp;$&nbsp;mkdir&nbsp;-p&nbsp;docker/db tomas&nbsp;~/m2.docker&nbsp;$&nbsp;touch&nbsp;docker/xdebug.ini tomas&nbsp;~/m2.docker&nbsp;$&nbsp;touch&nbsp;docker/apache.conf tomas&nbsp;~/m2.docker&nbsp;$&nbsp;touch&nbsp;docker-compose.yml tomas&nbsp;~/m2.docker&nbsp;$&nbsp;touch&nbsp;.env</pre><p>现在,让我们逐个来看这些文件文件:</p><p>.env</p><p>在这个文件中,你可以编写将在docker-compose.yml</p><p>中使用的变量,我的看起来像这样:</p><pre class="brush:bash;toolbar:false">CONTAINER_PREFIX=m2docker SERVER_NAME=m2.docker SERVER_ALIAS=www.m2.docker DIRECTORY_NAME=m2.docker WEB_USER=inchoo WEB_ROOT&nbsp;=&nbsp;/var/www/html MYSQL_DB_HOST&nbsp;=&nbsp;${CONTAINER_PREFIX}_db_1 MYSQL_DATABASE=inchoo MYSQL_ROOT_USERNAME=root MYSQL_ROOT_PASSWORD=inchoo MYSQL_USER=inchoo MYSQL_PASSWORD=inchoo DOCKER_EXEC=docker&nbsp;exec DOCKER_EXEC_INTERACTIVE=docker&nbsp;exec&nbsp;-i DOCKER_EXEC_TTY=${DOCKER_EXEC_INTERACTIVE}&nbsp;-t</pre><p>对于docker-compose.yml,您将需要以下代码。</p><p>我还添加了一些带有文档链接的评论。</p><p>请注意,我使用的是我的同事Stjepan创建的apache-php图像,我强烈推荐它进行开发。</p><p><br/></p><pre class="brush:bash;toolbar:false">#&nbsp;https://docs.docker.com/compose/compose-file version:&nbsp;&quot;3.6&quot; &nbsp; #&nbsp;https://docs.docker.com/compose/compose-file/#service-configuration-reference services: &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;#custom&nbsp;name &nbsp;&nbsp;&nbsp;&nbsp;apache-php: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;https://docs.docker.com/compose/compose-file/#image &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;https://githheizenberg&nbsp;ub.com/udovicic/echo&nbsp;=&gt;&nbsp;https://hub.docker.com/r/udovicic/echo/ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;image:&nbsp;udovicic/echo:apache-php7.1 &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;https://docs.docker.com/compose/compose-file/#ports &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ports: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;&quot;80:80&quot; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;https://docs.docker.com/compose/compose-file/#expose &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;expose: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;&quot;9000&quot; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;https://docs.docker.com/compose/compose-file/#volumes &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;volumes: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;./docker/xdebug.ini:/etc/php/7.1/mods-available/xdebug.ini &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;./html:/var/www/html &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;https://docs.docker.com/compose/compose-file/#environment &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;environment: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;TERM=xterm-256color &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;APACHE_RUN_USER=1000 &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;https://docs.docker.com/compose/compose-file/#network-configuration-reference &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;networks: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;default: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;aliases: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;${SERVER_NAME} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;${SERVER_ALIAS} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;db: &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;https://hub.docker.com/_/mysql/ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;image:&nbsp;mysql:5.7 &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;volumes: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;./docker/db/data:/var/lib/mysql &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;environment: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MYSQL_ROOT_PASSWORD:&nbsp;${MYSQL_ROOT_PASSWORD} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MYSQL_DATABASE:&nbsp;${MYSQL_DATABASE} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MYSQL_USER:&nbsp;${MYSQL_USER} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MYSQL_PASSWORD:&nbsp;${MYSQL_PASSWORD} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;redis: &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;https://hub.docker.com/_/redis/ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;image:&nbsp;redis:latest &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;phpmyadmin: &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;https://hub.docker.com/r/phpmyadmin/phpmyadmin/ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;image:&nbsp;phpmyadmin/phpmyadmin &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ports: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;&quot;8080:80&quot; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;environment: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MYSQL_USERNAME:&nbsp;${MYSQL_ROOT_USERNAME} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MYSQL_ROOT_PASSWORD:&nbsp;${MYSQL_ROOT_PASSWORD} …and&nbsp;xdebug.ini zend_extension=xdebug.so xdebug.remote_autostart=0 xdebug.remote_enable=1 xdebug.remote_port=9000 xdebug.remote_connect_back=1</pre><p>这一点我们有工作环境,所以让我们尝试运行它:</p><pre class="brush:bash;toolbar:false">tomas&nbsp;~/m2.docker&nbsp;$&nbsp;docker-compose&nbsp;up&nbsp;-d Creating&nbsp;network&nbsp;&quot;m2docker_default&quot;&nbsp;with&nbsp;the&nbsp;default&nbsp;driver Creating&nbsp;m2docker_apache-php_1&nbsp;...&nbsp;done Creating&nbsp;m2docker_redis_1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...&nbsp;done Creating&nbsp;m2docker_phpmyadmin_1&nbsp;...&nbsp;done Creating&nbsp;m2docker_db_1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...&nbsp;done tomas&nbsp;~/m2.docker&nbsp;$&nbsp;docker&nbsp;ps CONTAINER&nbsp;ID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IMAGE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;COMMAND&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CREATED&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;STATUS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PORTS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NAMES e3384b0eff8c&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mysql:5.7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;docker-entrypoint.s…&quot;&nbsp;&nbsp;&nbsp;3&nbsp;seconds&nbsp;ago&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Up&nbsp;2&nbsp;seconds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3306/tcp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m2docker_db_1 d283bf018330&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;phpmyadmin/phpmyadmin&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;/run.sh&nbsp;phpmyadmin&quot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;seconds&nbsp;ago&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Up&nbsp;2&nbsp;seconds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;9000/tcp,&nbsp;0.0.0.0:8080-&gt;80/tcp&nbsp;&nbsp;&nbsp;m2docker_phpmyadmin_1 ded8bce1d993&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;redis:latest&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;docker-entrypoint.s…&quot;&nbsp;&nbsp;&nbsp;3&nbsp;seconds&nbsp;ago&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Up&nbsp;2&nbsp;seconds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6379/tcp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m2docker_redis_1 fe8a80763ac6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;udovicic/echo:apache-php7.1&nbsp;&nbsp;&nbsp;&quot;/start.sh&quot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;seconds&nbsp;ago&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Up&nbsp;2&nbsp;seconds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0.0.0.0:80-&gt;80/tcp,&nbsp;9000/tcp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m2docker_apache-php_1 tomas&nbsp;~/m2.docker&nbsp;$</pre><p>Magento应该安装在“html”目录中。</p><p>请注意,在引用数据库地址时需要使用“db”,依此类推。只需检查docker-compose.yml(服务名称)。</p><p>此外,相关凭据位于 .env 文件中。</p><p>PhpMyAdmin 可用 @ http://m2.docker:8080</p><p>这是一个非常基本的设置。我通常创建 git 存储库,它最初以 2 个分支结束,例如 m2-docker 和 master,然后我将 .git 目录复制到 html 中并签出 master 分支,而在基本目录中我签出 m2-docker 分支。</p><p><br/></p>

magento2.3版本中如何以编程的方式向系统中添加用户

<h5 style="color:red;">系统学习magento二次开发,推荐小册:<a style="color:blue;" href="https://www.maxiaoke.com/manual/magento_cn_dev.html" target="_blank">《Magento中文全栈二次开发 》</a></h5> <div class="image-container"> <p> <a style="color:blue;" href="https://www.maxiaoke.com/manual/magento_cn_dev.html" target="_blank"> <img src="https://www.maxiaoke.com/uploads/images/20230218/bb9c82995c24d1105676e02f373755f5.jpg" alt="Magento中文全栈二次开发"> </a> </p> </div> <div class="text-container" style="font-size:14px; color:#888"> <p>本小册面向Magento2以上版本,书代码及示例兼容magento2.0-2.4版本。涵盖了magento前端开发,后端开发,magento2主题,magento2重写,magento2 layout,magento2控制器,magento2 block等相关内容,带领您成为magento开发技术专家。</p> </div> <hr><p>有几种方法可以在Magento 2中创建客户。客户可以使用注册表单自行创建帐户,可以通过管理界面创建客户,甚至还有一个内置的Magento 2导入功能,可以从CSV文件中批量导入大量客户,前提是CSV中的客户数据已准备好导入。</p><p>但是,如果我们有成千上万的客户,他们的数据在创建之前仍然需要处理怎么办?执行此操作的最佳方法是以编程方式创建客户。</p><p>在本文中,我们将介绍以编程方式创建客户的主题,为此,我们将创建一个简单的Magento 2模块,</p><p>该模块将具有自定义控制台命令和几个模型,这些模型将用于读取,处理和创建客户。</p><p><span style="color: #6a9955;">### 结构</span></p><p>让我们首先在Magento 2安装的目录中创建一个模块。在此示例中,我将使用 Inchoo 作为模块供应商,并将模块命名为 CustomerCreation,但您可以根据需要命名它们。/app/code</p><p>在我们的模块中,我们将需要以下目录和文件:</p><pre class="brush:bash;toolbar:false">registration.php /etc/module.xml /Console/Command/CreateCustomers.php /etc/di.xml /Model/Customer.php /Model/Import/CustomerImport.php</pre><p>registation.php</p><p>为了使我们的客户创建模块正常工作,我们需要在Magento系统中注册我们的模块。将以下代码复制到文件中:registration.php</p><pre class="brush:bash;toolbar:false">&lt;?php &nbsp; \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, &#39;Inchoo_CustomerCreation&#39;, __DIR__ );</pre><p><span style="color: #6a9955;"></span></p><p><span style="color: #6a9955;">### module.xml</span></p><p>我们的模块还需要声明它的名称和存在。将以下代码复制到文件中:/etc/module.xml</p><p>&lt;?xml <span style="color: #569cd6;">version</span>=<span style="color: #ce9178;">&quot;1.0&quot;</span>?&gt;</p><p><br/></p><pre class="brush:bash;toolbar:false">&lt;config&nbsp;xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&nbsp;xsi:noNamespaceSchemaLocation=&quot;urn:magento:framework:Module/etc/module.xsd&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;module&nbsp;name=&quot;Inchoo_CustomerCreation&quot;&nbsp;setup_version=&quot;1.0.0&quot;&nbsp;/&gt; &lt;/config&gt;</pre><p><span style="color: #6a9955;">### 其它文件</span></p><p>现在我们已经设置了模块,我们需要一种方法来触发我们的客户创建过程。我们可以做到这一点的一种方法是创建自定义控制台命令。</p><p>让我们从在文件中导入一堆类开始,让我们也定义类并使其扩展导入的 Command 类:/Console/Command/CreateCustomers.php</p><pre class="brush:bash;toolbar:false">&lt;?php &nbsp; namespace&nbsp;Inchoo\CustomerCreation\Console\Command; &nbsp; use&nbsp;Exception; use&nbsp;Magento\Framework\App\Filesystem\DirectoryList; use&nbsp;Magento\Framework\Console\Cli; use&nbsp;Magento\Framework\Filesystem; use&nbsp;Magento\Framework\App\State; use&nbsp;Magento\Framework\App\Area; use&nbsp;Symfony\Component\Console\Command\Command; use&nbsp;Symfony\Component\Console\Input\InputInterface; use&nbsp;Symfony\Component\Console\Output\OutputInterface; use&nbsp;Inchoo\CustomerCreation\Model\Customer; &nbsp; class&nbsp;CreateCustomers&nbsp;extends&nbsp;Command { &nbsp;&nbsp;//&nbsp;everything&nbsp;else&nbsp;goes&nbsp;here }</pre><p>方法:</p><pre class="brush:bash;toolbar:false">public&nbsp;function&nbsp;__construct( &nbsp;&nbsp;&nbsp;&nbsp;Filesystem&nbsp;$filesystem, &nbsp;&nbsp;&nbsp;&nbsp;Customer&nbsp;$customer, &nbsp;&nbsp;&nbsp;&nbsp;State&nbsp;$state )&nbsp;{ parent::__construct(); &nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;filesystem&nbsp;=&nbsp;$filesystem; &nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;customer&nbsp;=&nbsp;$customer; &nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;state&nbsp;=&nbsp;$state; }</pre><p>我们还需要通过使用类中的方法为其设置名称来配置控制台命令。此方法继承自 Command 类,也可用于设置命令说明、输入参数和其他选项。configure()</p><pre class="brush:bash;toolbar:false">public&nbsp;function&nbsp;configure():&nbsp;void { &nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;setName(&#39;create:customers&#39;); }</pre><p>现在让我们定义调用命令时将触发的方法。此方法也是从 Command 类继承而来的,我们将在其中编写我们的逻辑。execute()bin/magento create:customers</p><p>在该方法中,我们首先必须将区号设置为 .如果我们不这样做,客户创建过程稍后将产生错误。execute()global</p><p>之后,我们必须获取包含所有客户数据的 CSV 文件的绝对路径。在此示例中,CSV 文件已命名并位于目录中(相对于根目录,而不是我们的模块)。customers.csv/pub/media/fixtures</p><p>获得绝对路径后,我们必须调用该方法(此方法稍后将在我们的客户模型中定义),并将 CSV 文件的绝对路径作为参数传递给它。如果有任何错误,我们需要捕获它们并在CLI中显示错误消息:install()</p><pre class="brush:bash;toolbar:false">public&nbsp;function&nbsp;execute(InputInterface&nbsp;$input,&nbsp;OutputInterface&nbsp;$output):&nbsp;?int { &nbsp;&nbsp;try&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;state-&gt;setAreaCode(Area::AREA_GLOBAL); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$mediaDir&nbsp;=&nbsp;$this-&gt;filesystem-&gt;getDirectoryWrite(DirectoryList::MEDIA); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$fixture&nbsp;=&nbsp;$mediaDir-&gt;getAbsolutePath()&nbsp;.&nbsp;&#39;fixtures/customers.csv&#39;; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;customer-&gt;install($fixture,&nbsp;$output); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;Cli::RETURN_SUCCESS; &nbsp;&nbsp;}&nbsp;catch&nbsp;(Exception&nbsp;$e)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$msg&nbsp;=&nbsp;$e-&gt;getMessage(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$output-&gt;writeln(&quot;&lt;error&gt;$msg&lt;/error&gt;&quot;,&nbsp;OutputInterface::OUTPUT_NORMAL); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;Cli::RETURN_FAILURE; &nbsp;&nbsp;} }</pre><p>为了使我们的自定义命令正常工作,我们还必须使用依赖注入来配置命令名称。</p><p>将以下代码添加到文件中:/etc/di.xml</p><pre class="brush:bash;toolbar:false">&lt;?xml&nbsp;version=&quot;1.0&quot;?&gt; &lt;config&nbsp;xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xsi:noNamespaceSchemaLocation=&quot;urn:magento:framework:ObjectManager/etc/config.xsd&quot;&gt; &nbsp;&nbsp;&nbsp;&lt;type&nbsp;name=&quot;Magento\Framework\Console\CommandList&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;arguments&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;argument&nbsp;name=&quot;commands&quot;&nbsp;xsi:type=&quot;array&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;CreateCustomers&quot;&nbsp;xsi:type=&quot;object&quot;&gt;Inchoo\CustomerCreation\Console\Command\CreateCustomers&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/argument&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/arguments&gt; &nbsp;&nbsp;&nbsp;&lt;/type&gt; &lt;/config&gt;</pre><p>是时候创建我们的客户模型了。这是我们将读取CSV数据,对其进行处理,将其存储在数组中并将其发送以进行保存的地方。</p><p>在文件中,导入以下类并定义 Customer 类:/Model/Customer.php</p><pre class="brush:bash;toolbar:false">&lt;?php &nbsp; namespace&nbsp;Inchoo\CustomerCreation\Model; &nbsp; use&nbsp;Exception; use&nbsp;Generator; use&nbsp;Magento\Framework\Filesystem\Io\File; use&nbsp;Magento\Store\Model\StoreManagerInterface; use&nbsp;Inchoo\CustomerCreation\Model\Import\CustomerImport; use&nbsp;Symfony\Component\Console\Output\OutputInterface; &nbsp; class&nbsp;Customer { &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;everything&nbsp;else&nbsp;goes&nbsp;here }</pre><p>我们还必须在此类中创建一个构造函数并注入一些依赖项:</p><pre class="brush:bash;toolbar:false">private&nbsp;$file; private&nbsp;$storeManagerInterface; private&nbsp;$customerImport; private&nbsp;$output; &nbsp; public&nbsp;function&nbsp;__construct( &nbsp;&nbsp;&nbsp;&nbsp;File&nbsp;$file, &nbsp;&nbsp;&nbsp;&nbsp;StoreManagerInterface&nbsp;$storeManagerInterface, &nbsp;&nbsp;&nbsp;&nbsp;CustomerImport&nbsp;$customerImport )&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;file&nbsp;=&nbsp;$file; &nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;storeManagerInterface&nbsp;=&nbsp;$storeManagerInterface; &nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;customerImport&nbsp;=&nbsp;$customerImport; }</pre><p>让我们在 Customer 类中定义方法。这是我们之前在自定义控制台命令中调用的方法。install()</p><p>我们首先检索商店和网站 ID。之后,我们检索 CSV 标头,然后遍历每个 CSV 行,读取这些行中包含的数据并将它们传递给我们尚未定义的方法。createCustomer()</p><pre class="brush:bash;toolbar:false">public&nbsp;function&nbsp;install(string&nbsp;$fixture,&nbsp;OutputInterface&nbsp;$output):&nbsp;void { &nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;output&nbsp;=&nbsp;$output; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;get&nbsp;store&nbsp;and&nbsp;website&nbsp;ID &nbsp;&nbsp;&nbsp;&nbsp;$store&nbsp;=&nbsp;$this-&gt;storeManagerInterface-&gt;getStore(); &nbsp;&nbsp;&nbsp;&nbsp;$websiteId&nbsp;=&nbsp;(int)&nbsp;$this-&gt;storeManagerInterface-&gt;getWebsite()-&gt;getId(); &nbsp;&nbsp;&nbsp;&nbsp;$storeId&nbsp;=&nbsp;(int)&nbsp;$store-&gt;getId(); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;read&nbsp;the&nbsp;csv&nbsp;header &nbsp;&nbsp;&nbsp;&nbsp;$header&nbsp;=&nbsp;$this-&gt;readCsvHeader($fixture)-&gt;current(); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;read&nbsp;the&nbsp;csv&nbsp;file&nbsp;and&nbsp;skip&nbsp;the&nbsp;first&nbsp;(header)&nbsp;row &nbsp;&nbsp;&nbsp;&nbsp;$row&nbsp;=&nbsp;$this-&gt;readCsvRows($fixture,&nbsp;$header); &nbsp;&nbsp;&nbsp;&nbsp;$row-&gt;next(); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;while&nbsp;the&nbsp;generator&nbsp;is&nbsp;open,&nbsp;read&nbsp;current&nbsp;row&nbsp;data,&nbsp;create&nbsp;a&nbsp;customer&nbsp;and&nbsp;resume&nbsp;the&nbsp;generator &nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;($row-&gt;valid())&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$data&nbsp;=&nbsp;$row-&gt;current(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;createCustomer($data,&nbsp;$websiteId,&nbsp;$storeId); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$row-&gt;next(); &nbsp;&nbsp;&nbsp;&nbsp;} }</pre><p>要读取 CSV 标题和行,我们使用生成器。生成器允许我们编写代码,这些代码可以迭代一组数据,而无需在内存中构建数组。如果我们有一个大的CSV文件,这可以帮助我们不超过内存限制。该方法将读取行数据并将其映射到从该方法检索的标头。readCsvRows()readCsvHeader()</p><p>创建以下方法:</p><pre class="brush:bash;toolbar:false">private&nbsp;function&nbsp;readCsvRows(string&nbsp;$file,&nbsp;array&nbsp;$header):&nbsp;?Generator { &nbsp;&nbsp;&nbsp;&nbsp;$handle&nbsp;=&nbsp;fopen($file,&nbsp;&#39;rb&#39;); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;(!feof($handle))&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$data&nbsp;=&nbsp;[]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$rowData&nbsp;=&nbsp;fgetcsv($handle); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;($rowData)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach&nbsp;($rowData&nbsp;as&nbsp;$key&nbsp;=&gt;&nbsp;$value)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$data[$header[$key]]&nbsp;=&nbsp;$value; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;yield&nbsp;$data; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;fclose($handle); } &nbsp; private&nbsp;function&nbsp;readCsvHeader(string&nbsp;$file):&nbsp;?Generator { &nbsp;&nbsp;&nbsp;&nbsp;$handle&nbsp;=&nbsp;fopen($file,&nbsp;&#39;rb&#39;); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;(!feof($handle))&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;yield&nbsp;fgetcsv($handle); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;fclose($handle); }</pre><p>我们在此类中的最后一个方法是方法。createCustomer()</p><p>传递给该方法的参数是一个关联数组,其中包含来自 CSV 文件的键值对,每个键是标题列表(例如 email_address)的不同字段名称,每个值都是关联的记录(例如 john.doe@email.com)。$data</p><p>在我们的方法中,我们需要定义数组。这也将是一个关联数组,我们需要在其中将数组中的值与该方法需要保存客户的键配对。如果发现任何错误,其错误消息将打印在我们的 CLI 中。$customerData$dataimportCustomerData()</p><p>下面的示例假设CSV文件具有Magento创建客户所需的确切数据,但是,在大多数情况下,情况并非如此。也许客户出生日期的格式不正确,或者我们可能没有客户组 ID,只有客户组名称。在这种情况下,在填充数组之前,我们需要确保处理数组中的数据,使其包含正确的值。$customerData$data</p><pre class="brush:bash;toolbar:false">private&nbsp;function&nbsp;createCustomer(array&nbsp;$data,&nbsp;int&nbsp;$websiteId,&nbsp;int&nbsp;$storeId):&nbsp;void { &nbsp;&nbsp;try&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;collect&nbsp;the&nbsp;customer&nbsp;data &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$customerData&nbsp;=&nbsp;[ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;email&#39;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt;&nbsp;$data[&#39;email_address&#39;], &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;_website&#39;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt;&nbsp;&#39;base&#39;, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;_store&#39;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt;&nbsp;&#39;default&#39;, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;confirmation&#39;&nbsp;&nbsp;=&gt;&nbsp;null, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;dob&#39;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt;&nbsp;null, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;firstname&#39;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt;&nbsp;$data[&#39;firstname&#39;], &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;gender&#39;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt;&nbsp;null, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;group_id&#39;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt;&nbsp;$data[&#39;customer_group_id&#39;], &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;lastname&#39;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt;&nbsp;$data[&#39;last_name&#39;], &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;middlename&#39;&nbsp;&nbsp;&nbsp;&nbsp;=&gt;&nbsp;null, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;password_hash&#39;&nbsp;=&gt;&nbsp;$data[&#39;password_hash&#39;], &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;prefix&#39;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt;&nbsp;null, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;store_id&#39;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt;&nbsp;$storeId, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;website_id&#39;&nbsp;&nbsp;&nbsp;&nbsp;=&gt;&nbsp;$websiteId, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;password&#39;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt;&nbsp;null, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;disable_auto_group_change&#39;&nbsp;=&gt;&nbsp;0, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;some_custom_attribute&#39;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt;&nbsp;&#39;some_custom_attribute_value&#39; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;save&nbsp;the&nbsp;customer&nbsp;data &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;customerImport-&gt;importCustomerData($customerData); &nbsp;&nbsp;}&nbsp;catch&nbsp;(Exception&nbsp;$e)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;output-&gt;writeln( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;&lt;error&gt;&#39;.&nbsp;$e-&gt;getMessage()&nbsp;.&#39;&lt;/error&gt;&#39;, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OutputInterface::OUTPUT_NORMAL &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;); &nbsp;&nbsp;} }</pre><p><span style="color: #6a9955;">### 实体</span></p><p>对于最后一步,我们需要创建客户导入模型。在文件中,让我们从Magento CustomerImportExport模块导入客户类并定义我们的CustomerImport类。使其扩展导入的客户类。/Module/Import/CustomerImport.php</p><p>我们的类将包含用于准备和保存客户数据的方法。importCustomerData()</p><pre class="brush:bash;toolbar:false">&lt;?php &nbsp; namespace&nbsp;Inchoo\CustomerCreation\Model\Import; &nbsp; use&nbsp;Magento\CustomerImportExport\Model\Import\Customer; &nbsp; class&nbsp;CustomerImport&nbsp;extends&nbsp;Customer { &nbsp;&nbsp;//&nbsp;everything&nbsp;else&nbsp;goes&nbsp;here }</pre><p>现在我们的类已经定义,我们需要创建处理客户创建过程最后步骤的方法。在此方法中,我们将创建或更新客户实体,并保存为该客户提供的任何属性数据。然后,该方法将返回客户实体 ID。此方法实际上是对我们正在扩展的 Customer 类中找到的函数的轻微修改。importCustomerData()</p><pre class="brush:bash;toolbar:false">public&nbsp;function&nbsp;importCustomerData(array&nbsp;$rowData) { &nbsp;&nbsp;$this-&gt;prepareCustomerData($rowData); &nbsp;&nbsp;$entitiesToCreate&nbsp;=&nbsp;[]; &nbsp;&nbsp;$entitiesToUpdate&nbsp;=&nbsp;[]; &nbsp;&nbsp;$entitiesToDelete&nbsp;=&nbsp;[]; &nbsp;&nbsp;$attributesToSave&nbsp;=&nbsp;[]; &nbsp; &nbsp;&nbsp;$processedData&nbsp;=&nbsp;$this-&gt;_prepareDataForUpdate($rowData); &nbsp;&nbsp;$entitiesToCreate&nbsp;=&nbsp;array_merge($entitiesToCreate,&nbsp;$processedData[self::ENTITIES_TO_CREATE_KEY]); &nbsp;&nbsp;$entitiesToUpdate&nbsp;=&nbsp;array_merge($entitiesToUpdate,&nbsp;$processedData[self::ENTITIES_TO_UPDATE_KEY]); &nbsp;&nbsp;foreach&nbsp;($processedData[self::ATTRIBUTES_TO_SAVE_KEY]&nbsp;as&nbsp;$tableName&nbsp;=&gt;&nbsp;$customerAttributes)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!isset($attributesToSave[$tableName]))&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$attributesToSave[$tableName]&nbsp;=&nbsp;[]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$attributesToSave[$tableName]&nbsp;=&nbsp;array_diff_key( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$attributesToSave[$tableName], &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$customerAttributes &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)&nbsp;+&nbsp;$customerAttributes; &nbsp;&nbsp;} &nbsp; &nbsp;&nbsp;$this-&gt;updateItemsCounterStats($entitiesToCreate,&nbsp;$entitiesToUpdate,&nbsp;$entitiesToDelete); &nbsp; &nbsp;&nbsp;/** &nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Save&nbsp;prepared&nbsp;data &nbsp;&nbsp;&nbsp;&nbsp;*/ &nbsp;&nbsp;if&nbsp;($entitiesToCreate&nbsp;||&nbsp;$entitiesToUpdate)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;_saveCustomerEntities($entitiesToCreate,&nbsp;$entitiesToUpdate); &nbsp;&nbsp;} &nbsp;&nbsp;if&nbsp;($attributesToSave)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;_saveCustomerAttributes($attributesToSave); &nbsp;&nbsp;} &nbsp; &nbsp;&nbsp;return&nbsp;$entitiesToCreate[0][&#39;entity_id&#39;]&nbsp;??&nbsp;$entitiesToUpdate[0][&#39;entity_id&#39;]&nbsp;??&nbsp;null; }</pre><p>为了完成工作,我们需要调用 and 命令来让我们的模块和自定义命令正常工作。bin/magento setup:upgradebin/magento setup:di:compile</p><p>使用 运行客户创建脚本后,还需要确保重新索引客户网格索引器。我们可以通过调用命令来做到这一点。bin/magento create:customersbin/magento indexer:reindex customer_grid</p><p><span style="color: #6a9955;">### 小结</span></p><p>就是这样,我们现在应该有一个功能齐全的模块,使我们能够在几分钟内以编程方式创建数千个客户。如果您有任何问题或问题,请在下面发表评论。</p>