文章列表


magento2中的knockoutjs的使用与初始化详细讲解

<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>了解KnockoutJS的最快方法是一个基本的例子。首先,让我们创建以下 HTML 页面</p><pre class="brush:bash;toolbar:false">&lt;!--&nbsp;File:&nbsp;page.html&nbsp;--&gt;&nbsp;&nbsp; &lt;!DOCTYPE&nbsp;html&gt; &lt;html&nbsp;lang=&quot;en&quot;&gt; &lt;head&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;script&nbsp;type=&quot;text/javascript&quot;&nbsp;src=&quot;https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js&quot;&gt;&lt;/script&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;script&nbsp;src=&quot;https://code.jquery.com/jquery-3.0.0.min.js&quot;&nbsp;integrity=&quot;sha256-JmvOoLtYsmqlsWxa7mDSLMwa6dZ9rrIdtrrVYRnDRH0=&quot;&nbsp;crossorigin=&quot;anonymous&quot;&gt;&lt;/script&gt;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/head&gt; &lt;body&gt; &lt;div&nbsp;id=&quot;main&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;h1&gt;&lt;/h1&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;p&gt;&lt;/p&gt; &lt;/div&gt; &lt;/body&gt; &lt;/html&gt;</pre><p>从 cloudflare CDN 加载 KnockoutJS 库</p><p>从 jQuery 代码 CDN 加载 jQuery 库</p><p>设置一个空的 DOM 节点结构</p><p>您不需要从 CDN 加载 jQuery 和 KnockoutJS,但如果您这样做,则在本教程中它是最简单的。</p><p>如果在浏览器中加载此页面,它将完全空白。那是因为我们需要</p><p>添加创建视图模型并应用 KnockoutJS 绑定的 JavaScript 代码</p><p>将视图代码添加到从视图模型读取的 HTML 页面</p><p>解决其中的第一个问题,让我们将第三个javascript文件添加到我们的页面。我们将创建一个以以下内容命名的文件ko-init.js</p><p></p><pre class="brush:bash;toolbar:false">//File:&nbsp;ko-init.js jQuery(function(){ &nbsp;&nbsp;&nbsp;&nbsp;viewModel&nbsp;=&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;title:&quot;Hello&nbsp;World&quot;, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;content:&quot;So&nbsp;many&nbsp;years&nbsp;of&nbsp;hello&nbsp;world&quot; &nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;ko.applyBindings(viewModel); });</pre><p><span style="color: #6a9955;"></span><br/></p><p>然后使用第三个脚本标签添加到我们的页面。ko-init.js</p><pre class="brush:bash;toolbar:false">&lt;!--&nbsp;File:&nbsp;page.html&nbsp;--&gt; &lt;script&nbsp;type=&quot;text/javascript&quot;&nbsp;src=&quot;https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js&quot;&gt;&lt;/script&gt; &lt;script&nbsp;src=&quot;https://code.jquery.com/jquery-3.0.0.min.js&quot;&nbsp;integrity=&quot;sha256-JmvOoLtYsmqlsWxa7mDSLMwa6dZ9rrIdtrrVYRnDRH0=&quot;&nbsp;crossorigin=&quot;anonymous&quot;&gt;&lt;/script&gt;&nbsp;&nbsp;&nbsp;&nbsp; &lt;script&nbsp;type=&quot;text/javascript&quot;&nbsp;src=&quot;ko-init.js&quot;&gt;&lt;/script&gt; 最后,更改&nbsp;and&nbsp;标记,使其包含以下属性。h1pdata-bind &lt;!--&nbsp;File:&nbsp;page.html&nbsp;--&gt; &lt;div&nbsp;id=&quot;main&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;h1&nbsp;data-bind=&quot;text:title&quot;&gt;&lt;/h1&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;p&nbsp;data-bind=&quot;text:content&quot;&gt;&lt;/p&gt; &lt;/div&gt;</pre><p>完成上述操作后,重新加载页面,您应该会看到标题和内容已呈现。</p><p></p><pre class="brush:bash;toolbar:false">//File:&nbsp;ko-init.js jQuery(function(){ &nbsp;&nbsp;&nbsp;&nbsp;viewModel&nbsp;=&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;title:&quot;Hello&nbsp;World&quot;, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;content:&quot;So&nbsp;many&nbsp;years&nbsp;of&nbsp;hello&nbsp;world&quot; &nbsp;&nbsp;&nbsp;&nbsp;};&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;ko.applyBindings(viewModel); }); //File:&nbsp;ko-init.js viewModel&nbsp;=&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;title:&quot;Hello&nbsp;World&quot;, &nbsp;&nbsp;&nbsp;&nbsp;content:&quot;So&nbsp;many&nbsp;years&nbsp;of&nbsp;hello&nbsp;world&quot; };&nbsp; &lt;!--&nbsp;File:&nbsp;page.html&nbsp;--&gt;&nbsp;&nbsp; &lt;div&nbsp;id=&quot;main&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;h1&nbsp;data-bind=&quot;text:title&quot;&gt;&lt;/h1&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;p&nbsp;data-bind=&quot;text:content&quot;&gt;&lt;/p&gt; &lt;/div&gt; value&nbsp;=&nbsp;viewModel[&#39;title&#39;]; textNode&nbsp;=&nbsp;document.createTextNode(value); h1.appendChild(textNode);</pre><p></p><pre class="brush:bash;toolbar:false">//File:&nbsp;ko-init.js jQuery(function(){ &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;viewModelConstructor&nbsp;=&nbsp;function() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.getTitle&nbsp;=&nbsp;function() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;&quot;Hello&nbsp;Method&nbsp;World&quot;; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.content&nbsp;=&nbsp;&quot;So&nbsp;many&nbsp;years&nbsp;of&nbsp;hello&nbsp;world&quot;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;viewModel&nbsp;=&nbsp;new&nbsp;viewModelConstructor; &nbsp;&nbsp;&nbsp;&nbsp;ko.applyBindings(viewModel); });</pre><p><span style="color: #6a9955;"></span><br/></p><p>在这里,我们使用了一个javascript构造函数来创建一个简单的对象,并带有一个方法。如果我们更改视图以调用该方法,您将看到它按预期工作getTitlegetTitle</p><pre class="brush:bash;toolbar:false">&lt;!--&nbsp;File:&nbsp;page.html&nbsp;--&gt;&nbsp;&nbsp; &lt;div&nbsp;id=&quot;main&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;h1&nbsp;data-bind=&quot;text:getTitle()&quot;&gt;&lt;/h1&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;p&nbsp;data-bind=&quot;text:content&quot;&gt;&lt;/p&gt; &lt;/div&gt;</pre><p>考虑绑定参数的另一种方法是,它们是访问视图模型的值和方法的临时、有限的 JavaScript 范围。</p><p><span style="color: #6a9955;">### 其他绑定</span></p><p>虽然此示例很简单,但您可以开始了解这个基本构建块如何实现更复杂的视图逻辑。更新 DOM 的业务留给了 ings,更新模型的业务留给了纯非 DOM JavaScript 代码。data-bind</p><p>你可以开始看到它与其他绑定的价值。例如,让我们在我们的theValueviewModelConstructor</p><p></p><pre class="brush:bash;toolbar:false">//File:&nbsp;ko-init.js jQuery(function(){ &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;viewModelConstructor&nbsp;=&nbsp;function() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.getTitle&nbsp;=&nbsp;function() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;&quot;Hello&nbsp;World&quot;; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.content&nbsp;=&nbsp;&quot;So&nbsp;many&nbsp;years&nbsp;of&nbsp;hello&nbsp;world&quot;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.theValue&nbsp;=&nbsp;&quot;2&quot;; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;viewModel&nbsp;=&nbsp;new&nbsp;viewModelConstructor; &nbsp;&nbsp;&nbsp;&nbsp;ko.applyBindings(viewModel);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });</pre><p>,然后添加具有新绑定的输入标记。</p><pre class="brush:bash;toolbar:false">&lt;!--&nbsp;File:&nbsp;page.html&nbsp;--&gt;&nbsp;&nbsp; &lt;div&nbsp;id=&quot;main&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;h1&nbsp;data-bind=&quot;text:getTitle()&quot;&gt;&lt;/h1&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;p&nbsp;data-bind=&quot;text:content&quot;&gt;&lt;/p&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;input&nbsp;type=&quot;text&quot;&nbsp;data-bind=&quot;value:theValue&quot;/&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/div&gt;</pre><p>重新加载页面,您将看到值为 .2</p><pre class="brush:bash;toolbar:false">data-bind=&quot;value:theValue&quot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;!--&nbsp;File:&nbsp;page.html&nbsp;--&gt;&nbsp;&nbsp; &lt;div&nbsp;id=&quot;main&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;h1&nbsp;data-bind=&quot;text:getTitle()&quot;&gt;&lt;/h1&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;p&nbsp;data-bind=&quot;text:content&quot;&gt;&lt;/p&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;select&nbsp;data-bind=&quot;value:theValue&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;option&nbsp;value=&quot;&quot;&gt;--&nbsp;Choose&nbsp;--&lt;/option&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;option&nbsp;value=&quot;1&quot;&gt;First&lt;/option&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;option&nbsp;value=&quot;2&quot;&gt;Second&lt;/option&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;option&nbsp;value=&quot;3&quot;&gt;Third&lt;/option&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/select&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/div&gt;</pre><p>虽然这个例子很简单,但它背后的概念却不是。无需更改任何 javascript 应用程序代码,绑定允许我们更改 UI。value</p><p><span style="color: #6a9955;">### 可观察量</span></p><p>到目前为止,我们看到的是一个强大的客厅技巧。整洁,也许有用,但它只为KnockoutJS真正的“淘汰”功能——可观察量奠定了基础。</p><p>同样,我们将通过一个例子进行深入研究。更改视图,使其与以下内容匹配</p><pre class="brush:bash;toolbar:false">&lt;!--&nbsp;File:&nbsp;page.html&nbsp;--&gt; &lt;div&nbsp;id=&quot;main&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;p&nbsp;data-bind=&quot;text:theValue&quot;&gt;&lt;/p&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;select&nbsp;data-bind=&quot;value:theValue&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;option&nbsp;value=&quot;&quot;&gt;--&nbsp;Choose&nbsp;--&lt;/option&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;option&nbsp;value=&quot;1&quot;&gt;First&lt;/option&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;option&nbsp;value=&quot;2&quot;&gt;Second&lt;/option&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;option&nbsp;value=&quot;3&quot;&gt;Third&lt;/option&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/select&gt;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&lt;input&nbsp;type=&quot;text&quot;&nbsp;data-bind=&quot;value:theValue&quot;/&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;div&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;br/&gt;&lt;br/&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;button&nbsp;id=&quot;button&quot;&gt;Do&nbsp;It&lt;/button&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/div&gt; &lt;/div&gt;</pre><p>并更改视图模型和绑定,使其与以下内容匹配。</p><p></p><pre class="brush:bash;toolbar:false">//File:&nbsp;ko-init.js jQuery(function(){ &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;viewModelConstructor&nbsp;=&nbsp;function() &nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.theValue&nbsp;=&nbsp;ko.observable(&quot;1&quot;); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;window.viewModel&nbsp;=&nbsp;new&nbsp;viewModelConstructor; &nbsp;&nbsp;&nbsp;&nbsp;ko.applyBindings(window.viewModel);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });</pre><p>如果您重新加载页面,您将看到我们已将 的值绑定到 our and 标记。到目前为止,我们的观点没有什么新东西——这与我们以前所做的那种绑定相同。但是,您会注意到我们在视图模型中做了一些不同的事情。1&lt;input/&gt;&lt;p/&gt;</p><p></p><pre class="brush:bash;toolbar:false">//File:&nbsp;ko-init.js this.theValue&nbsp;=&nbsp;ko.observable(&quot;1&quot;);</pre><p>我们没有设置为硬编码值或自定义函数,而是将值设置为 KnockoutJS 称之为可观察量的值。可观察量是一种特殊的吸气者和二传手。theValue</p><p>如果你打开你的javascript控制台,并键入以下内容,你会看到我们可以通过将其作为函数调用来获取可观察量的值(可以通过控制台获得,因为我们将其定义为对象的全局对象)</p><pre class="brush:bash;toolbar:false">viewModelwindow &gt;&nbsp;viewModel.theValue()&nbsp;&nbsp;&nbsp;&nbsp; &gt;&nbsp;&quot;1&quot;</pre><p>我们可以通过传入参数在可观察量上设置一个值。下面介绍了如何设置可观察量,然后获取可观察量的值。</p><p></p><pre class="brush:bash;toolbar:false">&gt;&nbsp;viewModel.theValue(&quot;3&quot;) //... &gt;&nbsp;viewModel.theValue() &gt;&nbsp;&quot;3&quot;</pre><p>然而,可观察量的真正力量在于我们将可观察量绑定到的 DOM 节点会发生什么。尝试通过控制台更改观察器的值并观察浏览器窗口</p><p></p><pre class="brush:bash;toolbar:false">&gt;&nbsp;viewModel.theValue(&quot;3&quot;); &gt;&nbsp;viewModel.theValue(&quot;2&quot;); &gt;&nbsp;viewModel.theValue(&quot;1&quot;); &gt;&nbsp;viewModel.theValue(&quot;10&quot;);</pre><p>更新可观察量的值时,绑定节点的值会实时更改。同样,作为开发人员,我们不必担心 DOM 节点如何更新——一旦我们在模型上设置了值,这个值就会自动反映在用户界面中。</p><p>虽然它超出了本文的范围,但当我们的视图模型包含方法时,您可以看到它如何组合在一起形成复杂的 JavaScript 应用程序。</p><p></p><pre class="brush:bash;toolbar:false">//File:&nbsp;ko-init.js jQuery(function(){ &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;viewModelConstructor&nbsp;=&nbsp;function() &nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.theValue&nbsp;=&nbsp;ko.observable(&quot;1&quot;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;that&nbsp;=&nbsp;this; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.pickRandomValue&nbsp;=&nbsp;function(){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;val&nbsp;=&nbsp;Math.floor(Math.random()&nbsp;*&nbsp;(3)); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;that.theValue(val); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;window.viewModel&nbsp;=&nbsp;new&nbsp;viewModelConstructor; &nbsp;&nbsp;&nbsp;&nbsp;ko.applyBindings(window.viewModel);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });</pre><p>并且您使用 KnockoutJS 的事件绑定,例如click</p><pre class="brush:bash;toolbar:false">&lt;!--&nbsp;File:&nbsp;page.html&nbsp;--&gt;&nbsp;&nbsp; &lt;button&nbsp;data-bind=&quot;click:pickRandomValue&quot;&gt;Do&nbsp;It&lt;/button&gt;</pre><p>我们将把解析作为读者的练习</p><p><span style="color: #6a9955;">### 模板绑定</span></p><p>另一个需要理解的重要绑定是 KnockoutJS 的模板绑定。考虑这样的视图模型</p><p></p><pre class="brush:bash;toolbar:false">//File:&nbsp;ko-init.js jQuery(function(){ &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;viewModelConstructor&nbsp;=&nbsp;function() &nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.first&nbsp;=&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;theTitle:ko.observable(&quot;Hello&nbsp;World&quot;), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;theContent:ko.observable(&quot;Back&nbsp;to&nbsp;Hello&nbsp;World&quot;) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.second&nbsp;=&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;theTitle:ko.observable(&quot;Goodbye&nbsp;World&quot;), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;theContent:ko.observable(&quot;We&#39;re&nbsp;sailing&nbsp;west&nbsp;now&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;viewModel&nbsp;=&nbsp;new&nbsp;viewModelConstructor; &nbsp;&nbsp;&nbsp;&nbsp;ko.applyBindings(viewModel);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });</pre><p>在这里,我们创建了一个标准视图模型,但具有嵌套的数据对象。如果将其与这样的视图相结合</p><pre class="brush:bash;toolbar:false">&lt;!--&nbsp;File:&nbsp;page.html&nbsp;--&gt; &lt;div&nbsp;id=&quot;main&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;div&nbsp;id=&quot;one&quot;&nbsp;data-bind=&quot;template:{&#39;name&#39;:&#39;hello-world&#39;,&#39;data&#39;:first}&quot;&gt;&lt;/div&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;div&nbsp;id=&quot;two&quot;&nbsp;data-bind=&quot;template:{&#39;name&#39;:&#39;hello-world&#39;,&#39;data&#39;:second}&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/div&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;script&nbsp;type=&quot;text/html&quot;&nbsp;id=&quot;hello-world&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;h1&nbsp;data-bind=&quot;text:theTitle&quot;&gt;&lt;/h1&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;p&nbsp;data-bind=&quot;text:theContent&quot;&gt;&lt;/p&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/script&gt; &lt;/div&gt;</pre><p>模板绑定接受 javascript 对象作为参数</p><pre class="brush:bash;toolbar:false">&lt;!--&nbsp;File:&nbsp;page.html&nbsp;--&gt; &lt;div&nbsp;id=&quot;one&quot;&nbsp;data-bind=&quot;template:{&#39;name&#39;:&#39;hello-world&#39;,&#39;data&#39;:first}&quot;&gt;&lt;/div&gt;</pre><p>data 参数是我们想要用来渲染模板的视图模型的属性。模板的名称就是这样 — 要查找和呈现的模板名称。</p><p>向系统添加命名模板的最基本方法是添加带有 of 的标记。&lt;script/&gt;typetext/html</p><pre class="brush:bash;toolbar:false">&lt;!--&nbsp;File:&nbsp;page.html&nbsp;--&gt; &lt;script&nbsp;type=&quot;text/html&quot;&nbsp;id=&quot;hello-world&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;h1&nbsp;data-bind=&quot;text:theTitle&quot;&gt;&lt;/h1&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;p&nbsp;data-bind=&quot;text:theContent&quot;&gt;&lt;/p&gt; &lt;/script&gt;</pre><p>如果你以前从未见过这个,它可能看起来很奇怪/陌生,但许多现代JavaScript框架使用非标签作为将非渲染(但DOM可访问)内容添加到页面的一种方式。模板只是一组带有 KnockoutJS 绑定的标准 HTML 节点。text/javascript&lt;script/&gt;</p><p><span style="color: #6a9955;">### 组件</span></p><p>我们将要进行的最后一个绑定是组件绑定。组件是一种将 KnockoutJS 模板和 KnockoutJS 视图文件打包在一起的方法。这意味着您可以有一个相对简单的视图</p><pre class="brush:bash;toolbar:false">&lt;!--&nbsp;File:&nbsp;page.html&nbsp;--&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;div&nbsp;data-bind=&quot;component:&#39;component-hello-world&#39;&quot;&gt;&lt;/div&gt;</pre><p>这隐藏了已注册组件的复杂性。</p><p></p><pre class="brush:bash;toolbar:false">//File:&nbsp;ko-init.js jQuery(function(){&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;viewModelConstructor&nbsp;=&nbsp;function() &nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.message&nbsp;=&nbsp;&quot;Hello&nbsp;World&quot;; &nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;theTemplate&nbsp;=&nbsp;&quot;&lt;h1&nbsp;data-bind=\&quot;text:message\&quot;&gt;&lt;/h1&gt;&quot;;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;ko.components.register(&#39;component-hello-world&#39;,&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;viewModel:viewModelConstructor, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;template:theTemplate &nbsp;&nbsp;&nbsp;&nbsp;});&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;ko.applyBindings();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });</pre><p><span style="color: #6a9955;"></span><br/></p><p>组件对象的函数需要组件的名称,然后是 KnockoutJS 组件对象。组件对象是具有两个属性的 JavaScript 脚本对象。该属性需要一个视图模型构造函数,并且该属性应该是带有 KnockoutJS 模板的字符串。注册后,可以通过将组件的名称(作为字符串)传递到绑定中使用组件。registerviewModeltemplate</p><pre class="brush:bash;toolbar:false">&lt;!--&nbsp;File:&nbsp;page.html&nbsp;--&gt;&nbsp;&nbsp; &lt;div&nbsp;data-bind=&quot;component:&#39;component-hello-world&#39;&quot;&gt;&lt;/div&gt;</pre><p>如果您不想使用语法 — KnockoutJS 使您能够根据组件名称插入具有自定义标记名称的组件。在您的视图/HTML 文件中尝试此操作data-bind</p><pre class="brush:bash;toolbar:false">&lt;!--&nbsp;File:&nbsp;page.html&nbsp;--&gt;&nbsp;&nbsp; &lt;component-hello-world&gt;&lt;/component-hello-world&gt;</pre><p>这只触及了KnockoutJS可能的表面。官方文档对组件绑定有一个很好的概述。</p><p><span style="color: #6a9955;">### 自定义绑定</span></p><p>我们今天要讨论的最后一个 KnockoutJS 功能是自定义绑定功能。KnockoutJS使javascript开发人员能够创建自己的绑定。例如,这里我们调用一个名为 的自定义绑定,并向其传递 viewModel 的属性值。pulseStormHelloWorldmessage</p><pre class="brush:bash;toolbar:false">&lt;!--&nbsp;File:&nbsp;page.html&nbsp;--&gt;&nbsp;&nbsp; &lt;div&nbsp;data-bind=&quot;pulseStormHelloWorld:message&quot;&gt;&lt;/div&gt;</pre><p>如果没有实现,KnockoutJS将忽略我们的绑定。相反,请尝试以下ko-init.js</p><p></p><pre class="brush:bash;toolbar:false">//File:&nbsp;ko-init.js jQuery(function(){&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;viewModelConstructor&nbsp;=&nbsp;function() &nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.message&nbsp;=&nbsp;&quot;Hello&nbsp;World&quot;; &nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;ko.bindingHandlers.pulseStormHelloWorld&nbsp;=&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;update:&nbsp;function(element,&nbsp;valueAccessor){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jQuery(element).html(&#39;&lt;h1&gt;&#39;&nbsp;+&nbsp;valueAccessor()&nbsp;+&nbsp;&#39;&lt;/h1&gt;&#39;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;};&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;ko.applyBindings(new&nbsp;viewModelConstructor);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });</pre><p><span style="color: #6a9955;"></span><br/></p><p>要将自定义绑定添加到 KnockoutJS,我们需要做的就是向对象的对象添加一个属性。此属性的名称是我们绑定的名称。处理程序是带有方法的 JS 对象。每当调用绑定时,KnockoutJS 都会调用该方法 — 无论是在 期间还是通过可观察量。kobinidngHandlersupdateupdateapplyBindings</p><p>完成上述操作后,重新加载 HTML 页面,您将看到调用的自定义绑定。当然,这是一个微不足道的例子,但是使用自定义绑定,您可以让KnockoutJS做任何您的编程思维想到的事情。</p><p><br/></p>

magento2中的javascript初始化init方法

<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>Javascript 初始化方法</p><p>我们将要讨论的Magento javascript init方法解决了几个不同的问题。</p><p>首先,它们提供了一种标准机制来阻止将javascript直接嵌入到页面中。</p><p>其次,它们提供了一种调用独立 RequireJS 模块(定义为 )作为程序的方法。define</p><p>第三,它们提供了一种向该程序传递服务器端生成的JSON对象的方法。</p><p>第四,它们提供了一种方法来告诉该程序应该在哪些(如果有的话)DOM节点上运行。</p><p>牢记这四个目标。如果您正在努力解决这些自定义框架功能背后的心智模型,它们可能会为您提供帮助。</p><p><span style="color: #6a9955;">### 设置模块</span></p><p>我们将使用 pestle 通过运行以下三个命令来创建以单个 URL 端点命名的模块Pulsestorm_JavascriptInitTutorial</p><pre class="brush:bash;toolbar:false">$&nbsp;pestle.phar&nbsp;generate_module&nbsp;Pulsestorm&nbsp;JavascriptInitTutorial&nbsp;0.0.1 $&nbsp;pestle.phar&nbsp;generate_route&nbsp;Pulsestorm_JavascriptInitTutorial&nbsp;frontend&nbsp;pulsestorm_javascriptinittutorial $&nbsp;pestle.phar&nbsp;generate_view&nbsp;Pulsestorm_JavascriptInitTutorial&nbsp;frontend&nbsp;pulsestorm_javascriptinittutorial_index_index&nbsp;Main&nbsp;content.phtml&nbsp;1column $&nbsp;php&nbsp;bin/magento&nbsp;module:enable&nbsp;Pulsestorm_JavascriptInitTutorial $&nbsp;php&nbsp;bin/magento&nbsp;setup:upgrade</pre><p>任何通过Magento 2 for PHP MVC开发人员系列工作的人都应该熟悉这些命令。运行上述操作后,您应该能够在系统中访问以下URL</p><p>http://magento.example.com/pulsestorm_javascriptinittutorial/</p><p>并查看呈现的模板。app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/templates/content.phtml</p><p><span style="color: #6a9955;">### 设置一个 RequireJS 模块</span></p><p>现在我们已经设置了一个Magento模块,让我们做一个快速回顾并创建一个RequireJS模块。首先,创建以下文件</p><p>//File: app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/web/example.js</p><p><br/></p><pre class="brush:bash;toolbar:false">define([],&nbsp;function(){ &nbsp;&nbsp;&nbsp;&nbsp;alert(&quot;A&nbsp;simple&nbsp;RequireJS&nbsp;module&quot;); &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;{};&nbsp;&nbsp;&nbsp;&nbsp; });</pre><p>这是一个非常简单的 RequireJS 模块。由于模块在文件系统上的位置,以及Magento加载javascript文件的方式,该模块的名称/标识符是Pulsestorm_JavascriptInitTutorial/example</p><p>接下来,更改 的内容,使其与以下内容匹配。content.phtml</p><p><span style="color: #6a9955;">#File: app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/templates/content.phtml</span></p><pre class="brush:bash;toolbar:false">&lt;script&nbsp;type=&quot;text/javascript&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;requirejs([&#39;Pulsestorm_JavascriptInitTutorial/example&#39;],function(example){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(&quot;Loaded&quot;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log(example); &nbsp;&nbsp;&nbsp;&nbsp;});&nbsp; &lt;/script&gt;</pre><p>在这里,我们将创建一个具有单个模块依赖项的 RequireJS 程序。依赖项是我们刚刚创建的模块 ()。加载Pulsestorm_JavascriptInitTutorial/example</p><p>http://magento.example.com/pulsestorm_javascriptinittutorial/</p><p>系统中的 URL,您应该会看到警报。</p><p>如果以上任何内容对您来说是陌生的,您可能需要查看我们的Magento 2和RequireJS文章。</p><p><span style="color: #6a9955;">### X-Magento-Init</span></p><p>我们要讨论的第一个初始化技术是方法。此初始化方法的最基本版本允许您将 RequireJS 模块作为程序运行。更改模板的内容,使其与以下内容匹配&lt;script <span style="color: #569cd6;">type</span>=<span style="color: #ce9178;">&quot;text/x-magento-init&quot;</span>&gt;content.phtml</p><p><span style="color: #6a9955;">#File: app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/templates/content.phtml</span></p><pre class="brush:bash;toolbar:false">&lt;div&nbsp;id=&quot;one&quot;&nbsp;class=&quot;foo&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;Hello&nbsp;World &lt;/div&gt; &lt;div&nbsp;id=&quot;two&quot;&nbsp;class=&quot;foo&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;Goodbye&nbsp;World &lt;/div&gt;&nbsp;&nbsp;&nbsp;&nbsp; &lt;script&nbsp;type=&quot;text/x-magento-init&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;*&quot;:&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;Pulsestorm_JavascriptInitTutorial/example&quot;:{} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/script&gt;</pre><p>使用上述内容重新加载您的页面,您应该会看到我们文件中的声明。alertexample.js</p><p>如果您以前从未见过此语法,它看起来可能有点奇怪。让我们把它一块一块地拆开。</p><p>首先是标签&lt;script/&gt;</p><p><span style="color: #6a9955;">#File: app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/templates/content.phtml</span></p><pre class="brush:bash;toolbar:false">&lt;script&nbsp;type=&quot;text/x-magento-init&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;//... &lt;/script&gt;</pre><p>此标签不是 javascript 标签。请注意该属性。当浏览器无法识别脚本类型标记中的值时,它将忽略该标记的内容。Magento(类似于其他现代JavaScript框架)利用这种行为来发挥其优势。虽然这超出了本教程的范围,但正在运行Magento javascript代码,它将扫描脚本标签。如果您想自己探索这个问题,这个堆栈交换问题和答案是一个很好的起点。<span style="color: #569cd6;">type</span>=<span style="color: #ce9178;">&quot;text/x-magento-init&quot;</span>text/x-magento-init</p><p>我们可以立即讨论的代码块的另一部分是以下对象x-magento-init</p><p><span style="color: #6a9955;">#File: app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/templates/content.phtml</span></p><pre class="brush:bash;toolbar:false">{ &nbsp;&nbsp;&nbsp;&nbsp;&quot;Pulsestorm_JavascriptInitTutorial/example&quot;:{}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</pre><p>Magento将查看此对象的键,并将其(键)作为RequireJS模块包含在内。这就是加载脚本的内容。example.js</p><p>您可能想知道为什么这是一个没有值的对象。您可能还想知道为什么整个事物是另一个对象的一部分,带有 a 作为键。*</p><p><span style="color: #6a9955;">#File: app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/templates/content.phtml</span></p><pre class="brush:bash;toolbar:false">{ &nbsp;&nbsp;&nbsp;&nbsp;&quot;*&quot;:&nbsp;{/*...*/} }</pre><p>在我们讨论这个问题之前,我们需要谈谈javascript组件。</p><p><span style="color: #6a9955;">### Magento Javascript Components</span></p><p>上面的例子将我们的 RequireJS 模块作为一个程序运行。这是有效的,Magento本身经常使用该方法将RequireJS模块作为程序调用。然而,真正的力量是能够创建一个Magento Javascript组件。x-magento-initx-magento-init</p><p>Magento Javascript 组件是返回函数的 RequireJS 模块。Magento的系统代码将以特定的方式调用此函数,以公开额外的功能。</p><p>如果这没有意义,请尝试更改 RequireJS 模块,使其与以下内容匹配。</p><p>//File: app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/web/example.js</p><p><br/></p><pre class="brush:bash;toolbar:false">define([],&nbsp;function&nbsp;()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;mageJsComponent&nbsp;=&nbsp;function() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(&quot;A&nbsp;simple&nbsp;magento&nbsp;component.&quot;); &nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;mageJsComponent; });</pre><p>在这里,我们定义了一个函数并将其分配给一个名为 .然后,我们将其退回。mageJsComponent</p><p>如果您在上述情况下重新加载页面,您应该会在警告框中看到一个简单的 Magento 组件。</p><p>这可能看起来很愚蠢——如果Magento所做的只是调用它,那么返回一个函数有什么意义呢?你是对的,但那是因为我们遗漏了一些东西。尝试更改我们的模板,使其与以下内容匹配phtml</p><p><span style="color: #6a9955;">#File: app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/templates/content.phtml</span></p><pre class="brush:bash;toolbar:false">&lt;div&nbsp;id=&quot;one&quot;&nbsp;class=&quot;foo&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;Hello&nbsp;World &lt;/div&gt; &lt;div&nbsp;id=&quot;two&quot;&nbsp;class=&quot;foo&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;Goodbye&nbsp;World &lt;/div&gt;&nbsp;&nbsp;&nbsp;&nbsp; &lt;script&nbsp;type=&quot;text/x-magento-init&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;*&quot;:&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;Pulsestorm_JavascriptInitTutorial/example&quot;:{&quot;config&quot;:&quot;value&quot;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/script&gt;</pre><p>并更改我们的 RequireJS 模块,使其看起来像这样</p><p>//File: app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/web/example.js</p><p><br/></p><pre class="brush:bash;toolbar:false">define([],&nbsp;function&nbsp;()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;mageJsComponent&nbsp;=&nbsp;function(config) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(&quot;Look&nbsp;in&nbsp;your&nbsp;browser&#39;s&nbsp;console&quot;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log(config); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//alert(config); &nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;mageJsComponent; });</pre><p>如果重新加载页面,应会看到更改的警告消息。如果您查看浏览器的 javascript 控制台,您还应该看到以下内容</p><p>&gt; Object {config:<span style="color: #ce9178;">&quot;value&quot;</span>}</p><p>当我们创建一个 Magento Javascript 组件时,Magento 调用返回的函数并包含来自 .text/x-magento-init</p><p><span style="color: #ce9178;">&quot;Pulsestorm_JavascriptInitTutorial/example&quot;</span>:{<span style="color: #ce9178;">&quot;config&quot;</span>:<span style="color: #ce9178;">&quot;value&quot;</span>} &nbsp; &nbsp; &nbsp; &nbsp;</p><p>这就是为什么 RequireJS 模块名称是一个键 — 这个对象的值是我们想要传递给组件的对象。</p><p>在这些示例中,这似乎是一个愚蠢的抽象。但是,在实际模块中,我们将使用 PHP 生成该 JSON。这个系统允许我们在模板中渲染JSON,然后将其传递给Javascript代码。这有助于避免直接使用 PHP 生成 Javascript 的问题,这可能导致代码非常混乱,并且很容易意外地滑入错误或安全问题。phtml</p><p>在我们结束之前,还有最后一个功能要讨论。你会记得我们说过x-magento-initx-magento-init</p><p>提供了一种向该程序传递服务器端生成的 JSON 对象的方法。</p><p>提供了一种为该程序提供它应该在其上运行的 DOM 节点的方法。</p><p>我们已经介绍了如何传入服务器端生成的 JSON — 但是 DOM 节点呢?</p><p>更改您的 RequireJS 模块,使其如下所示</p><p>//File: app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/web/example.js</p><p><br/></p><pre class="brush:bash;toolbar:false">define([],&nbsp;function&nbsp;()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;mageJsComponent&nbsp;=&nbsp;function(config,&nbsp;node) &nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log(config); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log(node); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//alert(config); &nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;mageJsComponent; });</pre><p>我们在这里所做的是向函数添加第二个参数。第二个参数将是我们希望程序运行的 DOM 节点。但是,如果您在上述情况下重新加载页面,您将在控制台中看到以下内容。mageJsComponent</p><p>&gt; Object {config:<span style="color: #ce9178;">&quot;value&quot;</span>}</p><p>&gt; false</p><p>Magento确实传递了一个值 - 但该值是。什么给?nodefalse</p><p>好吧,Magento无法神奇地知道我们要在哪些DOM节点上运行。我们需要告诉它!更改模板,使其与以下内容匹配。phtml</p><p><span style="color: #6a9955;">#File: app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/templates/content.phtml</span></p><pre class="brush:bash;toolbar:false">&lt;div&nbsp;id=&quot;one&quot;&nbsp;class=&quot;foo&quot;&gt;Hello&nbsp;World&lt;/div&gt; &lt;div&nbsp;id=&quot;two&quot;&nbsp;class=&quot;foo&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;Goodbye&nbsp;World &lt;/div&gt;&nbsp;&nbsp;&nbsp;&nbsp; &lt;script&nbsp;type=&quot;text/x-magento-init&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;#one&quot;:&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;Pulsestorm_JavascriptInitTutorial/example&quot;:{&quot;config&quot;:&quot;value&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; &lt;/script&gt;</pre><p>在这里,我们已将 更改为 .我们之前使用的实际上是一个特例,用于不需要在 DOM 节点上运行的程序。这个对象的键实际上是一个CSS / jQuery样式选择器,它告诉Magento程序应该在哪些DOM节点上运行。如果我们在上述情况下重新加载页面,我们将在您的控制台中看到以下内容*<span style="color: #6a9955;">#one*Pulsestorm_JavascriptInitTutorial/example</span></p><pre class="brush:bash;toolbar:false">&gt;&nbsp;Object&nbsp;{config:&nbsp;&quot;value&quot;} &gt;&nbsp;&lt;div&nbsp;id=&quot;one&quot;&nbsp;class=&quot;foo&quot;&gt;Hello&nbsp;World&lt;/div&gt;</pre><p>您不仅限于 ID,还可以在此处使用 CSS 类标识符。将其更改为</p><p><span style="color: #6a9955;">#File: app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/templates/content.phtml</span></p><pre class="brush:bash;toolbar:false">&quot;.foo&quot;:&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&quot;Pulsestorm_JavascriptInitTutorial/example&quot;:{&quot;config&quot;:&quot;value&quot;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</pre><p>您将在控制台中看到以下内容。</p><pre class="brush:bash;toolbar:false">&gt;&nbsp;Object&nbsp;{&quot;config&quot;:&quot;value&quot;} &gt;&nbsp;&lt;div&nbsp;id=&quot;one&quot;&nbsp;class=&quot;foo&quot;&gt;Hello&nbsp;World&lt;/div&gt; &gt;&nbsp;Object&nbsp;{&quot;config&quot;:&quot;value&quot;} &gt;&nbsp;&lt;div&nbsp;id=&quot;two&quot;&nbsp;class=&quot;foo&quot;&gt;Goodbye&nbsp;World&lt;/div&gt;</pre><p>通过构建这种系统,Magento鼓励开发人员避免将他们的DOM节点硬编码到他们的RequireJS模块中。这意味着有一个系统级的路径来构建依赖于服务器端渲染的JSON的Javascript模块,并在任何任意DOM节点上运行。Magento模块开发人员总是有可能实现自己的系统来实现这种功能,但是Magento 2提供了一个标准,内置的方式来实现这一目标。x-magento-init</p><p><span style="color: #6a9955;">### 数据法师初始化属性</span></p><p>除了 之外,还有另一种方法可以在特定的 DOM 节点上调用类似的功能,那就是属性。尝试将现有模板替换为以下内容&lt;script <span style="color: #569cd6;">type</span>=<span style="color: #ce9178;">&quot;text/x-magento-init&quot;</span>&gt;data-mage-initphtml</p><pre class="brush:bash;toolbar:false">&lt;div&nbsp;data-mage-init=&#39;{&quot;Pulsestorm_JavascriptInitTutorial/example&quot;:&nbsp;{&quot;another&quot;:&quot;example&quot;}}&#39;&gt;A&nbsp;single&nbsp;div&lt;/div&gt;</pre><p>在上述操作到位的情况下重新加载页面,您应该会在 JavaScript 控制台中看到以下内容。<br/></p><pre class="brush:as3;toolbar:false">&gt;&nbsp;Object&nbsp;{another:&nbsp;&quot;example&quot;}&nbsp;&nbsp; &gt;&nbsp;&lt;div&gt;A&nbsp;single&nbsp;div&lt;/div&gt;</pre><p>在这里,我们向特定的 div 添加了一个属性。此属性的值是一个 JSON 对象。与类似,这个对象的键是我们想要作为程序或Magento Javascript组件调用的RequireJS模块,该值是一个嵌套的JSON对象,作为参数传递到我们的Magento Javascript组件函数中。data-mage-initx-magento-initconfig</p><pre class="brush:bash;toolbar:false">&lt;div&nbsp;data-mage-init=&#39;...&#39;&gt;A&nbsp;single&nbsp;div&lt;/div&gt;</pre><p>不幸的是,这是必需的。属性的值由严格的 JSON 解析器解析,这意味着 JSON 对象的引号必须是双引号——这意味着我们不能对属性使用双引号。虽然这在HTML5中技术上是可以的,但对于一定年龄的Web程序员来说,它带来了一些不好Microsoft首页记忆。data-mage-init<br/></p><p>无论您最终在特定节点中使用组件还是属性,这两种技术都提供了一种标准的、系统统一的方式来将 Javascript 入口点引入您的页面。Magento的许多前端和后端UI功能都依赖于这种语法,因此即使您个人避开它们,了解这些系统的工作原理也是成为Magento 2开发人员的重要组成部分。&lt;script <span style="color: #569cd6;">type</span>=<span style="color: #ce9178;">&quot;text/x-magento-init&quot;</span>&gt;data-mage-init</p><p><br/></p>

使用Magento2布局layout将静态块添加到特定的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页面上CMS页面的标题和主要内容之间添加一个唯一的静态块。元素必须可以通过Magento管理面板完全自定义,并且必须易于在新的CMS页面上创建,易于修改和删除。由于该元素需要放置在主要内容之外,因此无法在Magento管理中使用CMS添加它。它必须使用Magento布局添加。这是我如何实现这一目标的。</p><p>如您所知,Magento仅为CMS页面提供以下句柄:</p><p><span style="color: #6a9955;">### 主页句柄和 404 页句柄</span></p><p>所有 CMS 页面的句柄</p><p>如果必须在主页上显示 CMS 块,我们将在本地.xml文件中使用主页句柄。同样,如果必须在所有CMS页面上显示相同的静态块,我们将对所有CMS页面使用句柄。</p><p>但是,单个用户创建的CMS页面呢?</p><p><span style="color: #6a9955;">### 前端开发人员的解决方案</span></p><p>幸运的是,Magento使我们能够通过从Magento管理面板上的CMS编辑器编辑每个CMS页面来定义自定义布局。这样,CMS 页面的布局就可以使用存储在数据库中的特定页面的已定义值进行修改。</p><p>首先,我们将创建一个静态块,我们要将其添加到特定的CMS页面中,我们将将其命名为static-block-1并对其应用一些简单的样式。</p><pre class="brush:bash;toolbar:false">&lt;div&nbsp;class=”element-blue”&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;h3&gt;Static&nbsp;Block&nbsp;1&lt;/h3&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;p&gt;This&nbsp;is&nbsp;blue&nbsp;static&nbsp;element&nbsp;1&nbsp;&lt;/p&gt; &lt;/div&gt;</pre><p>接下来,我们将创建一个新的 CMS 页面,其中包含创建的静态块,该块将通过“设计”选项卡上的“布局更新 XML”添加,以及一个标题和一个段落。在本例中,我们将对所有 CMS 页面使用 1 列布局。</p><pre class="brush:bash;toolbar:false">&lt;reference&nbsp;name=&quot;root&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;block&nbsp;type=&quot;cms/block&quot;&nbsp;name=&quot;myelement&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;action&nbsp;method=&quot;setBlockId&quot;&gt;&lt;block_id&gt;static-block-1&lt;/block_id&gt;&lt;/action&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/block&gt; &lt;/reference&gt;</pre><p>最后,我们必须更新我们的模板文件并添加一行调用我们的元素的代码。 由于我们对所有 CMS 页面都使用了 1 列布局,因此我们将修改 1column.phtml 模板文件。如果要将元素添加到使用其他模板(如 2 列左)的 CMS 页面,则需要修改这些文件。</p><pre class="brush:bash;toolbar:false">… &lt;div&nbsp;class=&quot;page&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;?php&nbsp;echo&nbsp;$this-&gt;getChildHtml(&#39;header&#39;)&nbsp;?&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;?php&nbsp;echo&nbsp;$this-&gt;getChildHtml(&#39;myelement&#39;)&nbsp;?&gt; …</pre><p>对于此示例,我创建了一个与第一个不同的附加静态块和两个额外的 CMS 页面 - 一个用于我创建的新元素,另一个用于没有任何布局更新,因此,它不会包含我们创建的任何元素。</p><p>结果</p><p>带有蓝色静态块的 CMS 页面 1:</p><p>CMS page 1</p><p>CMS 第 1 页的 HTML 代码:</p><p>01-code-1</p><p>带有绿色静态块的 CMS 页面 2:</p><p>02-cms-2</p><p>CMS 第 2 页的 HTML 代码:</p><p>02-code-2</p><p>CMS 第 3 页,我们没有在其 XML 中设置任何布局更新,因此它不显示任何创建的静态块。</p><p>03-cms-3</p><p>CMS 第 3 页的 HTML 代码:</p><p>03-code-3</p><p>好的、坏的和另一种选择</p><p>尽管这是一个非常快速简单的解决方案,效果很好,但当您必须为要添加的每个元素执行这些相同的步骤时,即使在具有 6 或 7 个 CMS 页面的项目中也是如此,它也会变得乏味。</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中的路由是最重要的部分之一。完整的应用程序(Magento 2)流程取决于处理URL请求和负责匹配和处理该请求的路由器类。本文介绍了Magento 2中的路由器流,并分析了默认安装附带的一些路由器。还将展示如何创建一个自定义路由器。将提到路由器如何匹配操作(控制器类),有关控制器的详细信息将在单独的文章中介绍。</p><p><span style="color: #6a9955;">### 路由流</span></p><p>首先,我们需要分析完整的路由流程,以便稍后可以更详细地了解每个部分。正如我们已经知道的,Magento 2创建了HTTP应用程序,其中类(启动方法)请求流将在其中启动。我们的流程从创建前端控制器开始:</p><pre class="brush:bash;toolbar:false">$frontController&nbsp;=&nbsp;$this-&gt;_objectManager-&gt;get(&#39;Magento\Framework\App\FrontControllerInterface&#39;);</pre><p>前端控制器负责遍历所有可用的路由器,并为当前请求匹配负责的路由器。稍后我们将详细介绍前端控制器。现在,要了解完整的流程,了解应用程序如何匹配路由器非常重要。路由器列表是在位于Magento\Framework\App的RouterList类中创建的(在Front Controller中调用用于在路由器上循环),该类负责路由器列表的排序和迭代。如果路由器负责当前请求,则路由器类负责匹配。让我们来看看Magento 2流程:<br/></p><p>index.php(运行引导程序并创建HTTP应用程序)→HTTP应用程序→FrontController →路由→控制器处理→等</p><p>现在,我们将分析路由流的每个部分,以便更好地了解Magento 2中的路由。</p><p><span style="color: #6a9955;">### 前端控制器</span></p><p>与Magento 1相同,这是在HTTP应用程序启动(启动方法)时调用的入口路由点。它负责匹配负责当前请求的路由器。它位于lib/internal/Magento/Framework/App/FrontController.php下。你可以看到在HTTP启动方法中使用了FrontControllerInterface。让我们在代码中看一下:</p><p></p><pre class="brush:bash;toolbar:false">class&nbsp;Http&nbsp;implements&nbsp;\Magento\Framework\AppInterface { &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;launch() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;... &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//Here&nbsp;Application&nbsp;is&nbsp;calling&nbsp;front&nbsp;controller&nbsp;and&nbsp;it&#39;s&nbsp;dispatch&nbsp;method &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$frontController&nbsp;=&nbsp;$this-&gt;_objectManager-&gt;get(&#39;Magento\Framework\App\FrontControllerInterface&#39;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$result&nbsp;=&nbsp;$frontController-&gt;dispatch($this-&gt;_request); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;... &nbsp;&nbsp;&nbsp;&nbsp;} }</pre><p><span style="color: #ce9178;">现在,当我们知道如何以及何时调用前端控制器时,让我们看一下前端控制器类和调度方法本身:</span></p><p><span style="color: #ce9178;">lib/internal/Magento/Framework/App/FrontController.php</span></p><p><span style="color: #ce9178;"></span></p><pre class="brush:bash;toolbar:false">class&nbsp;FrontController&nbsp;implements&nbsp;FrontControllerInterface { &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;dispatch(RequestInterface&nbsp;$request) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\Magento\Framework\Profiler::start(&#39;routers_match&#39;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$routingCycleCounter&nbsp;=&nbsp;0; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$result&nbsp;=&nbsp;null; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;(!$request-&gt;isDispatched()&nbsp;&amp;&amp;&nbsp;$routingCycleCounter++&nbsp;&lt;&nbsp;100)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/**&nbsp;@var&nbsp;\Magento\Framework\App\RouterInterface&nbsp;$router&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach&nbsp;($this-&gt;_routerList&nbsp;as&nbsp;$router)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$actionInstance&nbsp;=&nbsp;$router-&gt;match($request); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;($actionInstance)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$request-&gt;setDispatched(true); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$actionInstance-&gt;getResponse()-&gt;setNoCacheHeaders(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$result&nbsp;=&nbsp;$actionInstance-&gt;dispatch($request); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(\Magento\Framework\Exception\NotFoundException&nbsp;$e)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$request-&gt;initForward(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$request-&gt;setActionName(&#39;noroute&#39;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$request-&gt;setDispatched(false); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\Magento\Framework\Profiler::stop(&#39;routers_match&#39;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;($routingCycleCounter&nbsp;&gt;&nbsp;100)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;\LogicException(&#39;Front&nbsp;controller&nbsp;reached&nbsp;100&nbsp;router&nbsp;match&nbsp;iterations&#39;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$result; &nbsp;&nbsp;&nbsp;&nbsp;} }</pre><p><span style="color: #ce9178;">正如我们所看到的,调度方法将遍历所有路由器(启用,我们稍后将在路由器配置中介绍这一点),直到一个路由器匹配并调度请求($request→setDispatched(true);)或工艺路线周期计数器超过 100。路由器可以匹配,但是如果没有调度,它将重复环路槽路由器(向前操作)。此外,路由器可以重定向和调度,也可以匹配和处理。路由器列表类在请求流中解释。现在,我们可以继续查看路由器匹配(匹配方法)的工作原理以及路由器到底是什么。</span></p><p><span style="color: #ce9178;">### 路由器</span></p><p><span style="color: #ce9178;">简而言之,路由器是负责匹配和处理URL请求的PHP类。默认情况下,Magento框架和Magento核心中有一些路由器;Base、DefaultRouter、CMS 和 UrlRewrite。我们将涵盖所有这些内容,解释它们的目的以及它们的工作原理。路由器正在实现路由器接口。现在,让我们看一下默认路由器的流程:</span></p><p><span style="color: #ce9178;">基本路由器→ CMS 路由器→ url重写路由器→默认路由器</span></p><p><span style="color: #ce9178;">(这是路由器循环 – FrontController::d ispatch())</span></p><p><span style="color: #ce9178;">### 基础路由器</span></p><p><span style="color: #ce9178;">它位于lib/internal/Magento/Framework/App/Router/Base.php,它是循环中的第一个,如果你是Magento 1开发人员,你知道它是标准路由器。匹配方法将解析请求和匹配操作,在第二种方法中,它将设置模块前端名称、控制器路径名、操作名称、控制器模块和路由名称。在基本路由器上,标准Magento URL(前端名称/操作路径/操作/参数1/等参数/)匹配。</span></p><p><span style="color: #ce9178;">### 内容管理系统路由器</span></p><p><span style="color: #ce9178;">CMS路由器位于app/code/Magento/Cms/Controller/Router.php中,用于处理CMS页面,它将模块名称(模块前端名称)设置为“cms”,控制器名称(控制器路径名称)设置为“页面”,操作名称设置为“view” – app/code/Magento/Cms/Controller/Page/View.php控制器。设置基本控制器的格式后,它将设置页面 ID 并转发它,但不会调度它。转发意味着它将中断当前的路由器环路并再次启动环路(它最多可以这样做 100 次)。该路由器环路将匹配基本路由器,该路由器将在 Cms/控制器/页面中激活视图控制器并显示保存的页面 ID(根据 url 找到的页面 ID)。</span></p><p><span style="color: #ce9178;">### 网址重写路由器</span></p><p><span style="color: #ce9178;">在Magento 2中,UrlRewrite有自己的路由器,如果你熟悉Magento 1,那么你就会知道Url Rewrite是标准路由器的一部分。它位于:app/code/Magento/UrlRewrite/Controller/Router.php它使用Url Finder来获取与数据库中的URL匹配的url重写:</span></p><p><span style="color: #ce9178;"></span></p><pre class="brush:bash;toolbar:false">$rewrite&nbsp;=&nbsp;$this-&gt;urlFinder-&gt;findOneByData( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UrlRewrite::ENTITY_TYPE&nbsp;=&gt;&nbsp;$oldRewrite-&gt;getEntityType(), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UrlRewrite::ENTITY_ID&nbsp;=&gt;&nbsp;$oldRewrite-&gt;getEntityId(), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UrlRewrite::STORE_ID&nbsp;=&gt;&nbsp;$this-&gt;storeManager-&gt;getStore()-&gt;getId(), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UrlRewrite::IS_AUTOGENERATED&nbsp;=&gt;&nbsp;1, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;] &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);</pre><p><span style="color: #ce9178;">它将像 CMS 路由器一样转发动作。</span></p><p><span style="color: #ce9178;">### 默认路由器</span></p><p><span style="color: #ce9178;">它位于lib/internal/Magento/Framework/App/Router/DefaultRouter中.php它是路由器循环中的最后一个。当所有其他路由器不匹配时,使用它。在Magento 2中,我们可以为“未找到”页面创建自定义句柄以显示自定义内容。以下是 DefaultRouter 中没有路由处理程序列表的循环:</span></p><p><span style="color: #ce9178;"></span></p><pre class="brush:bash;toolbar:false">foreach&nbsp;($this-&gt;noRouteHandlerList-&gt;getHandlers()&nbsp;as&nbsp;$noRouteHandler)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;($noRouteHandler-&gt;process($request))&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</pre><p><span style="color: #ce9178;">### 自定义路由器(带示例)</span></p><p><span style="color: #ce9178;">前端控制器将遍历 routersList 中的所有路由器(从 routes.xml 中的配置创建),因此我们需要通过在 di.xml 模块中添加我们对新路由器的配置,在 lib/internal/Magento/Framework/App/RouterList 中添加自定义路由器.php。我们将创建一个新模块(我们称之为Inchoo/CustomRouter),然后我们将在routersList中添加新的路由器,最后,创建路由器类。</span></p><p><span style="color: #ce9178;">自定义路由器只是一个示例,您可以在其中了解如何匹配和转发要匹配的基本路由器的请求。首先,我们需要为位于app/code/Inchoo/CustomRouter中的模块创建文件夹结构,然后我们将在etc文件夹中创建模块.xml并在模块根目录中创建composer.json,其中包含模块信息。现在,我们可以通过在 etc/前端文件夹中向 di.xml 添加配置来创建自定义路由器,因为我们只想为前端提供自定义路由器。最后,我们将在控制器文件夹中创建路由器.php,其中包含用于匹配路由器的逻辑。我们将搜索 URL 并检查 URL 中是否有特定单词,然后,根据该单词,我们将设置模块前端名称、控制器路径名称、操作名称,然后转发基本控制器的请求。我们将搜索两个词:“examplerouter”和“exampletocms”。在“examplerouter”匹配中,我们将转发到基本路由器匹配格式(通过将模块前端名称设置为“inchootest”,控制器路径名称设置为“test”,操作名称设置为“test”),在“exampletocms”上,我们将转发到基本路由器以显示“关于我们”页面。</span></p><p><span style="color: #ce9178;">di.xml(位于 etc/前端)</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;!-- /** &nbsp;*&nbsp;Copyright&nbsp;©&nbsp;2015&nbsp;Inchoo&nbsp;d.o.o. &nbsp;*&nbsp;created&nbsp;by&nbsp;Zoran&nbsp;Salamun(zoran.salamun@inchoo.net) &nbsp;*&nbsp;Module&nbsp;is&nbsp;created&nbsp;for&nbsp;Custom&nbsp;Router&nbsp;demonstration &nbsp;*/ --&gt; &lt;config&nbsp;xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&nbsp;xsi:noNamespaceSchemaLocation=&quot;../../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;type&nbsp;name=&quot;Magento\Framework\App\RouterList&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;routerList&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;inchoocustomrouter&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;class&quot;&nbsp;xsi:type=&quot;string&quot;&gt;Inchoo\CustomRouter\Controller\Router&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&nbsp;name=&quot;disable&quot;&nbsp;xsi:type=&quot;boolean&quot;&gt;false&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&nbsp;name=&quot;sortOrder&quot;&nbsp;xsi:type=&quot;string&quot;&gt;22&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;/argument&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/arguments&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/type&gt; &lt;/config&gt; &lt;?php namespace&nbsp;Inchoo\CustomRouter\Controller; &nbsp; /** &nbsp;*&nbsp;Inchoo&nbsp;Custom&nbsp;router&nbsp;Controller&nbsp;Router &nbsp;* &nbsp;*&nbsp;@author&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Zoran&nbsp;Salamun&nbsp;&lt;zoran.salamun@inchoo.net&gt; &nbsp;*/ class&nbsp;Router&nbsp;implements&nbsp;\Magento\Framework\App\RouterInterface { &nbsp;&nbsp;&nbsp;&nbsp;/** &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@var&nbsp;\Magento\Framework\App\ActionFactory &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;$actionFactory; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;/** &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Response &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@var&nbsp;\Magento\Framework\App\ResponseInterface &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;$_response; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;/** &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;\Magento\Framework\App\ActionFactory&nbsp;$actionFactory &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;\Magento\Framework\App\ResponseInterface&nbsp;$response &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;__construct( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\Magento\Framework\App\ActionFactory&nbsp;$actionFactory, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\Magento\Framework\App\ResponseInterface&nbsp;$response &nbsp;&nbsp;&nbsp;&nbsp;)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;actionFactory&nbsp;=&nbsp;$actionFactory; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;_response&nbsp;=&nbsp;$response; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;/** &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Validate&nbsp;and&nbsp;Match &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;\Magento\Framework\App\RequestInterface&nbsp;$request &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;bool &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;match(\Magento\Framework\App\RequestInterface&nbsp;$request) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;We&nbsp;will&nbsp;search&nbsp;“examplerouter”&nbsp;and&nbsp;“exampletocms”&nbsp;words&nbsp;and&nbsp;make&nbsp;forward&nbsp;depend&nbsp;on&nbsp;word &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;-examplerouter&nbsp;will&nbsp;forward&nbsp;to&nbsp;base&nbsp;router&nbsp;to&nbsp;match&nbsp;inchootest&nbsp;front&nbsp;name,&nbsp;test&nbsp;controller&nbsp;path&nbsp;and&nbsp;test&nbsp;controller&nbsp;class &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;-exampletocms&nbsp;will&nbsp;set&nbsp;front&nbsp;name&nbsp;to&nbsp;cms,&nbsp;controller&nbsp;path&nbsp;to&nbsp;page&nbsp;and&nbsp;action&nbsp;to&nbsp;view &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$identifier&nbsp;=&nbsp;trim($request-&gt;getPathInfo(),&nbsp;&#39;/&#39;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(strpos($identifier,&nbsp;&#39;exampletocms&#39;)&nbsp;!==&nbsp;false)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;We&nbsp;must&nbsp;set&nbsp;module,&nbsp;controller&nbsp;path&nbsp;and&nbsp;action&nbsp;name&nbsp;+&nbsp;we&nbsp;will&nbsp;set&nbsp;page&nbsp;id&nbsp;5&nbsp;witch&nbsp;is&nbsp;about&nbsp;us&nbsp;page&nbsp;on &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;default&nbsp;magento&nbsp;2&nbsp;installation&nbsp;with&nbsp;sample&nbsp;data. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$request-&gt;setModuleName(&#39;cms&#39;)-&gt;setControllerName(&#39;page&#39;)-&gt;setActionName(&#39;view&#39;)-&gt;setParam(&#39;page_id&#39;,&nbsp;5); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;if(strpos($identifier,&nbsp;&#39;examplerouter&#39;)&nbsp;!==&nbsp;false)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;We&nbsp;must&nbsp;set&nbsp;module,&nbsp;controller&nbsp;path&nbsp;and&nbsp;action&nbsp;name&nbsp;for&nbsp;our&nbsp;controller&nbsp;class(Controller/Test/Test.php) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$request-&gt;setModuleName(&#39;inchootest&#39;)-&gt;setControllerName(&#39;test&#39;)-&gt;setActionName(&#39;test&#39;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//There&nbsp;is&nbsp;no&nbsp;match &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;We&nbsp;have&nbsp;match&nbsp;and&nbsp;now&nbsp;we&nbsp;will&nbsp;forward&nbsp;action &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$this-&gt;actionFactory-&gt;create( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;Magento\Framework\App\Action\Forward&#39;, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&#39;request&#39;&nbsp;=&gt;&nbsp;$request] &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;} }</pre><p><span style="color: #ce9178;">routes.xml (located in etc/frontend)</span></p><p><span style="color: #ce9178;"></span></p><pre class="brush:bash;toolbar:false">&lt;?xml&nbsp;version=&quot;1.0&quot;?&gt; &nbsp; &lt;config&nbsp;xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&nbsp;xsi:noNamespaceSchemaLocation=&quot;../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;router&nbsp;id=&quot;standard&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;route&nbsp;id=&quot;inchootest&quot;&nbsp;frontName=&quot;inchootest&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;module&nbsp;name=&quot;Inchoo_CustomRouter&quot;&nbsp;/&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/route&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/router&gt; &lt;/config&gt;</pre><p><span style="color: #ce9178;"></span><br/></p><p><span style="color: #ce9178;">Test.php (test controller action class)</span></p><p><br/></p><p><span style="color: #ce9178;"></span></p><pre class="brush:bash;toolbar:false">&lt;?php /** &nbsp;*&nbsp;Copyright&nbsp;©&nbsp;2015&nbsp;Inchoo&nbsp;d.o.o. &nbsp;*&nbsp;created&nbsp;by&nbsp;Zoran&nbsp;Salamun(zoran.salamun@inchoo.net) &nbsp;*/ namespace&nbsp;Inchoo\CustomRouter\Controller\Test; &nbsp; class&nbsp;Test&nbsp;extends&nbsp;\Magento\Framework\App\Action\Action { &nbsp;&nbsp;&nbsp;&nbsp;/** &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Listing&nbsp;all&nbsp;images&nbsp;in&nbsp;gallery &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;-@param&nbsp;gallery&nbsp;id &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;execute() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;die(&quot;Inchoo\\CustomRouter\\Controller\\Test\\Test&nbsp;controller&nbsp;execute()&quot;); &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;">https://github.com/zoransalamun/magento2-custom-router</span></p><p><span style="color: #ce9178;">安装:</span></p><p><span style="color: #ce9178;">首先将存储库添加到作曲家配置:</span></p><p><span style="color: #ce9178;"></span></p><pre class="brush:bash;toolbar:false">composer&nbsp;config&nbsp;repositories.inchoocustomrouter&nbsp;vcs&nbsp;git@github.com:zoransalamun/magento2-custom-router.git</pre><p><span style="color: #ce9178;">需要带有作曲家的新包:</span><br/></p><p><span style="color: #ce9178;"></span></p><pre class="brush:bash;toolbar:false">composer&nbsp;require&nbsp;inchoo/custom-router:dev-master</pre><p><span style="color: #ce9178;">启用 Inchoo 自定义路由器模块</span><br/></p><p><span style="color: #ce9178;"></span></p><pre class="brush:bash;toolbar:false">php&nbsp;bin/magento&nbsp;module:enable&nbsp;Inchoo_CustomRouter</pre><p><span style="color: #ce9178;">刷新所有内容:</span><br/></p><pre class="brush:bash;toolbar:false">php&nbsp;bin/magento&nbsp;setup:upgrade</pre><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 2中的控制器,就像其他PHP MVC框架一样,是Mvc流的重要组成部分。例如,在Magento 2中,控制器有很多变化<span style="color: #6a9955;">;与Magento 1相比,它们的结构和工作方式。如果您熟悉Magento 1控制器,那么您就会知道它们可以具有多个操作(类方法)。在Magento 2中,控制器只有一个方法(执行)将由前端控制器调用。本文介绍控制器基础知识、匹配流、控制器类型(管理员和前端)、现有控制器上的更改、创建自定义控制器的说明以及如何创建几个控制器的示例。</span></p><p><span style="color: rgb(106, 153, 85);">### 控制器</span><br/></p><p>控制器是位于模块控制器文件夹中的类,负责特定的 URL 或 URL 组。它与Magento 1中的控制器不同,因为它只有一个调用方法(在Magento 1中,我们可以根据需要使用)。所有需要的数据都通过对象管理器的 DI 填充。对于每个操作,我们都有一个带有执行方法的控制器类。当路由器与控制器操作类匹配时,将调用 Execute 方法,它负责将响应返回给前端控制器。所有控制器都在扩展\Magento\Framework\App\Action\Action类,该类具有调度方法,该方法将在控制器中调用执行方法,但我们稍后将介绍流程。有两种控制器类型:前端和管理员。它们具有类似的行为,但管理员有其他方法进行权限检查。控制器以特定方式构建,因此可以匹配。用于匹配的 URL 结构为:</p><p>www.maxiaoke.com/frontName/action 路径/操作类/</p><p>frontName – 它在路由.xml配置中设置,并且具有唯一值,将由路由器匹配</p><p>操作路径 – 控制器文件夹中的文件夹名称,默认为索引</p><p>动作类 – 我们称之为控制器的操作类,默认为索引</p><p>现在,我们将通过动作控制器方法并解释它们的用途。</p><p><span style="color: #6a9955;">### 执行方法</span></p><p>此方法是“第一个”称为控制器操作类,它继承自每个控制器类扩展的\Magento\Framework\App\Action\Action。它由\Magento\Framework\App\Action\Action::d ispatch()方法调用。在这种方法中,我们应该拥有所有的控制器逻辑(当然,我们可以在其他方法中使用逻辑,但执行方法将调用它们),它将返回响应(主要是呈现的页面)。</p><p>\Magento\Framework\App\Action\Action</p><p>这是主要的Magento框架操作类,每个控制器都必须扩展此类(管理控制器正在扩展\Magento\后端\App\Action,它扩展了\Magento\Framework\App\Action\Action)。重要的是,每个控制器都扩展此类以继承所需的方法,并允许前端控制器调用调度方法(将调用执行方法)。</p><p>此方法将首先由Front Controller(Magento\Framework\App\FrontController)调用</p><p></p><pre class="brush:bash;toolbar:false">Magento\Framework\App\FrontController::d&nbsp;ispatch()&nbsp;–&nbsp;在我们的&nbsp;Action&nbsp;类中调用&nbsp;dispatch: $result&nbsp;=&nbsp;$actionInstance-&gt;dispatch($request);</pre><p>请务必了解 Action 类中的调度方法用于前端控制器。对于管理控制器,调度方法被重写(在\Magento\后端\App\Action中),因此它可以检查是否允许用户访问。我们来分析一下我们的调度方法:</p><pre class="brush:bash;toolbar:false">/** &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Dispatch&nbsp;request &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;RequestInterface&nbsp;$request &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;ResponseInterface &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@throws&nbsp;NotFoundException &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;dispatch(RequestInterface&nbsp;$request) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;_request&nbsp;=&nbsp;$request; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$profilerKey&nbsp;=&nbsp;&#39;CONTROLLER_ACTION:&#39;&nbsp;.&nbsp;$request-&gt;getFullActionName(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$eventParameters&nbsp;=&nbsp;[&#39;controller_action&#39;&nbsp;=&gt;&nbsp;$this,&nbsp;&#39;request&#39;&nbsp;=&gt;&nbsp;$request]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;_eventManager-&gt;dispatch(&#39;controller_action_predispatch&#39;,&nbsp;$eventParameters); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;_eventManager-&gt;dispatch(&#39;controller_action_predispatch_&#39;&nbsp;.&nbsp;$request-&gt;getRouteName(),&nbsp;$eventParameters); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;_eventManager-&gt;dispatch( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;controller_action_predispatch_&#39;&nbsp;.&nbsp;$request-&gt;getFullActionName(), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$eventParameters &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\Magento\Framework\Profiler::start($profilerKey); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$result&nbsp;=&nbsp;null; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;($request-&gt;isDispatched()&nbsp;&amp;&amp;&nbsp;!$this-&gt;_actionFlag-&gt;get(&#39;&#39;,&nbsp;self::FLAG_NO_DISPATCH))&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\Magento\Framework\Profiler::start(&#39;action_body&#39;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$result&nbsp;=&nbsp;$this-&gt;execute(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\Magento\Framework\Profiler::start(&#39;postdispatch&#39;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!$this-&gt;_actionFlag-&gt;get(&#39;&#39;,&nbsp;self::FLAG_NO_POST_DISPATCH))&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;_eventManager-&gt;dispatch( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;controller_action_postdispatch_&#39;&nbsp;.&nbsp;$request-&gt;getFullActionName(), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$eventParameters &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;_eventManager-&gt;dispatch( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;controller_action_postdispatch_&#39;&nbsp;.&nbsp;$request-&gt;getRouteName(), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$eventParameters &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;_eventManager-&gt;dispatch(&#39;controller_action_postdispatch&#39;,&nbsp;$eventParameters); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\Magento\Framework\Profiler::stop(&#39;postdispatch&#39;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\Magento\Framework\Profiler::stop(&#39;action_body&#39;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\Magento\Framework\Profiler::stop($profilerKey); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$result&nbsp;?:&nbsp;$this-&gt;_response; &nbsp;&nbsp;&nbsp;&nbsp;}</pre><p>如我们所见,我们的调度方法将从上下文中返回结果或响应。它将检查请求是否已调度,然后在扩展\Magento\Framework\App\Action\Action的控制器操作类中调用执行方法:</p><p>$<span style="color: #569cd6;">result</span> = $this→execute()<span style="color: #6a9955;">;</span></p><p>在我们的行动类中,我们还需要两种更重要的方法:_forward 和 _redirect。让我们解释一下这些方法:</p><p></p><pre class="brush:bash;toolbar:false">FrontController::d&nbsp;ispatch() while&nbsp;(!$request-&gt;isDispatched()&nbsp;&amp;&amp;&nbsp;$routingCycleCounter++&nbsp;&lt;&nbsp;100)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/**&nbsp;@var&nbsp;\Magento\Framework\App\RouterInterface&nbsp;$router&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach&nbsp;($this-&gt;_routerList&nbsp;as&nbsp;$router)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$actionInstance&nbsp;=&nbsp;$router-&gt;match($request);</pre><p><span style="color: #6a9955;"></span><br/></p><p>它将首先匹配路由器,如上面的代码所示,路由器匹配将返回操作类(\Magento\Framework\App\ActionFactory)实例。之后,前端控制器将在操作类实例上调用调度方法:</p><p>$<span style="color: #569cd6;">result</span> = $actionInstance-&gt;dispatch($request)<span style="color: #6a9955;">;</span></p><p>由于我们已经介绍了调度方法,它将调用操作类执行方法:</p><p>$<span style="color: #569cd6;">result</span> = $this-&gt;execute()<span style="color: #6a9955;">;</span></p><p>这就是应用程序流进入我们的操作类执行方法的方式。</p><p>管理员和前端控制器之间的区别</p><p>这两个控制器之间的主要区别在于管理控制器中的附加检查和其他方法。两个控制器最终都会扩展 \Magento\Framework\App\Action\Action 类,但管理控制器扩展 \Magento\Backend\App\Action 类,该类扩展 \Magento\Framework\App\Action\Action。在管理控制器调度中,重写重定向和重写方法以提供检查 ACL(访问控制列表)的逻辑。</p><p><span style="color: #6a9955;">### 管理控制器</span></p><p>它扩展了\Magento\Backend\App\Action类,并具有_isAllowed检查访问控制的方法。在调度方法中,它将检查是否允许用户访问当前 URL,并将重定向到登录(如果不允许用户),或者它将设置状态为 403(禁止)的响应:</p><pre class="brush:bash;toolbar:false">public&nbsp;function&nbsp;dispatch(\Magento\Framework\App\RequestInterface&nbsp;$request) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!$this-&gt;_processUrlKeys())&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;parent::dispatch($request); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;($request-&gt;isDispatched()&nbsp;&amp;&amp;&nbsp;$request-&gt;getActionName()&nbsp;!==&nbsp;&#39;denied&#39;&nbsp;&amp;&amp;&nbsp;!$this-&gt;_isAllowed())&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;_response-&gt;setStatusHeader(403,&nbsp;&#39;1.1&#39;,&nbsp;&#39;Forbidden&#39;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!$this-&gt;_auth-&gt;isLoggedIn())&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$this-&gt;_redirect(&#39;*/auth/login&#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;$this-&gt;_view-&gt;loadLayout([&#39;default&#39;,&nbsp;&#39;adminhtml_denied&#39;],&nbsp;true,&nbsp;true,&nbsp;false); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;_view-&gt;renderLayout(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;_request-&gt;setDispatched(true); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$this-&gt;_response; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;($this-&gt;_isUrlChecked())&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;_actionFlag-&gt;set(&#39;&#39;,&nbsp;self::FLAG_IS_URLS_CHECKED,&nbsp;true); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;_processLocaleSettings(); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;parent::dispatch($request); &nbsp;&nbsp;&nbsp;&nbsp;}</pre><p>如果要创建管理控制器并想要添加一些自定义权限,则需要在_isAllowed方法中添加访问签入,例如:</p><pre class="brush:bash;toolbar:false">protected&nbsp;function&nbsp;_isAllowed() { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$this-&gt;_authorization-&gt;isAllowed(&#39;Magento_EncryptionKey::crypt_key&#39;); }</pre><p><span style="color: #6a9955;">### 现有控制器上的更改</span></p><p>要更改现有控制器,有几种方法可以更改它们。您可以通过首选项,插件或在Magento 1之后/之前使用“旧”样式来做到这一点。首选项将使用您的控制器代码更改完整的控制器(我们可以将其称为完全重写)。插件将仅更改所需的受控方法。最后,之后和之前将更改自定义前端名称的控制器位置。示例是如何在管理区域添加新控制器:</p><pre class="brush:bash;toolbar:false">&lt;router&nbsp;id=&quot;admin&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;route&nbsp;id=&quot;catalog&quot;&nbsp;frontName=&quot;catalog&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;module&nbsp;name=&quot;Magento_Catalog&quot;&nbsp;before=&quot;Magento_Backend&quot;&nbsp;/&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/route&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/router&gt;</pre><p><span style="color: #6a9955;">### 操作包装类</span></p><p>动作包装类是控制器文件夹中的一个类,它扩展了Magento\Framework\App\Action\Action,然后我们的操作类扩展了该操作包装器。如果您有多个操作类的通用逻辑,那么我们将在操作包装器类中编写逻辑,并将其用于我们需要的每个操作类。</p><p>例如,让我们看看Magento\Catalog\Controller\Product 它是动作包装器类,它用于位于Catalog\Controller\*文件夹中的许多动作类(动作类:Magento\Catalog\Controller\Product\Compare,Magento\Catalog\Controller\Product\Gallery等),它们都使用负责通过帮助程序加载产品的_initProduct。</p><pre class="brush:bash;toolbar:false">/** &nbsp;*&nbsp;Product&nbsp;controller. &nbsp;* &nbsp;*&nbsp;Copyright&nbsp;©&nbsp;2015&nbsp;Magento.&nbsp;All&nbsp;rights&nbsp;reserved. &nbsp;*&nbsp;See&nbsp;COPYING.txt&nbsp;for&nbsp;license&nbsp;details. &nbsp;*/ namespace&nbsp;Magento\Catalog\Controller; &nbsp; use&nbsp;Magento\Catalog\Controller\Product\View\ViewInterface; use&nbsp;Magento\Catalog\Model\Product&nbsp;as&nbsp;ModelProduct; &nbsp; abstract&nbsp;class&nbsp;Product&nbsp;extends&nbsp;\Magento\Framework\App\Action\Action&nbsp;implements&nbsp;ViewInterface { &nbsp;&nbsp;&nbsp;&nbsp;/** &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Initialize&nbsp;requested&nbsp;product&nbsp;object &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;ModelProduct &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;function&nbsp;_initProduct() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$categoryId&nbsp;=&nbsp;(int)$this-&gt;getRequest()-&gt;getParam(&#39;category&#39;,&nbsp;false); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$productId&nbsp;=&nbsp;(int)$this-&gt;getRequest()-&gt;getParam(&#39;id&#39;); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$params&nbsp;=&nbsp;new&nbsp;\Magento\Framework\DataObject(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$params-&gt;setCategoryId($categoryId); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/**&nbsp;@var&nbsp;\Magento\Catalog\Helper\Product&nbsp;$product&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$product&nbsp;=&nbsp;$this-&gt;_objectManager-&gt;get(&#39;Magento\Catalog\Helper\Product&#39;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$product-&gt;initProduct($productId,&nbsp;$this,&nbsp;$params); &nbsp;&nbsp;&nbsp;&nbsp;} }</pre><p><span style="color: #6a9955;">### 如何创建自定义控制器</span></p><p>在 etc/frontend 或 etc/adminhtml 文件夹中创建路由.xml(第一个用于前端,第二个用于管理控制器)。</p><p>在 routes.xml 中添加控制器的自定义配置,例如: – 路由器:ID – 标准(前端)/管理员</p><p>– 路由:ID – 您的唯一路由 ID</p><p>– 路由:</p><p>frontName – URL 中的唯一名称,这是基本路由器 (www.inchootest.net/frontName/actionpath/actionclass/)</p><p>中 URL 的第一部分 – 模块名称 – 您的模块名称</p><p>按照上面的 url 结构创建操作类:</p><p>控制器/操作路径/操作类.php</p><p>示例 – 管理员和前端控制器</p><p>我们将创建用于自定义控制器演示的示例模块。所以首先,让我们创建一个模块:</p><p>module.xml:</p><pre class="brush:bash;toolbar:false">&lt;?xml&nbsp;version=&quot;1.0&quot;?&gt; &lt;!-- /** &nbsp;*&nbsp;Copyright&nbsp;©&nbsp;2015&nbsp;Inchoo&nbsp;d.o.o. &nbsp;*&nbsp;created&nbsp;by&nbsp;Zoran&nbsp;Salamun(zoran.salamun@inchoo.net) &nbsp;*&nbsp;Module&nbsp;is&nbsp;created&nbsp;for&nbsp;Custom&nbsp;Controllers&nbsp;demonstration &nbsp;*/ --&gt; &lt;config&nbsp;xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&nbsp;xsi:noNamespaceSchemaLocation=&quot;../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;module&nbsp;name=&quot;Inchoo_CustomControllers&quot;&nbsp;setup_version=&quot;2.0.0&quot;&gt;&lt;/module&gt; &lt;/config&gt; etc/前端/路由.xml&nbsp;–&nbsp;前端的路由配置;为了演示,我们将“InchooFrontTest”作为frontname(域名后面URL的一部分&nbsp;-&nbsp;例如:www.inchootest.net/inchoofronttest/) &lt;?xml&nbsp;version=&quot;1.0&quot;?&gt; &lt;!-- /** &nbsp;*&nbsp;Copyright&nbsp;©&nbsp;2015&nbsp;Inchoo&nbsp;d.o.o. &nbsp;*&nbsp;created&nbsp;by&nbsp;Zoran&nbsp;Salamun(zoran.salamun@inchoo.net) &nbsp;*&nbsp;Module&nbsp;is&nbsp;created&nbsp;for&nbsp;Custom&nbsp;Controllers&nbsp;demonstration &nbsp;*/ --&gt; &lt;config&nbsp;xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&nbsp;xsi:noNamespaceSchemaLocation=&quot;../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;router&nbsp;id=&quot;standard&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;route&nbsp;id=&quot;inchootestfrontend&quot;&nbsp;frontName=&quot;inchoofronttest&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;module&nbsp;name=&quot;Inchoo_CustomControllers&quot;&nbsp;/&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/route&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/router&gt; &lt;/config&gt; etc/adminhtml/routes.xml&nbsp;–&nbsp;管理员的路由配置,为了演示,我们将匹配“InchooadminTest”作为frontname(/admin/之后URL的一部分) &lt;?xml&nbsp;version=&quot;1.0&quot;?&gt; &lt;!-- /** &nbsp;*&nbsp;Copyright&nbsp;©&nbsp;2015&nbsp;Inchoo&nbsp;d.o.o. &nbsp;*&nbsp;created&nbsp;by&nbsp;Zoran&nbsp;Salamun(zoran.salamun@inchoo.net) &nbsp;*&nbsp;Module&nbsp;is&nbsp;created&nbsp;for&nbsp;Custom&nbsp;Controllers&nbsp;demonstration &nbsp;*/ --&gt; &lt;config&nbsp;xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&nbsp;xsi:noNamespaceSchemaLocation=&quot;../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;router&nbsp;id=&quot;admin&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;route&nbsp;id=&quot;inchooadmintest&quot;&nbsp;frontName=&quot;inchooadmintest&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;module&nbsp;name=&quot;Inchoo_CustomControllers&quot;&nbsp;before=&quot;Magento_Backend&quot;&nbsp;/&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/route&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/router&gt; &lt;/config&gt;</pre><p>现在,我们将为两个控制器配置创建操作类。在前端,让我们为 url siteurl/inchoofronttest/demo/sayhello/ 创建操作路径和操作类。您可以看到我们在控制器文件夹中需要演示文件夹(这称为操作路径),在该文件夹中我们需要 Sayhello.php控制器操作类:</p><pre class="brush:bash;toolbar:false">&lt;?php /** &nbsp;*&nbsp;Copyright&nbsp;©&nbsp;2015&nbsp;Inchoo&nbsp;d.o.o. &nbsp;*&nbsp;created&nbsp;by&nbsp;Zoran&nbsp;Salamun(zoran.salamun@inchoo.net) &nbsp;*/ namespace&nbsp;Inchoo\CustomControllers\Controller\Demonstration; &nbsp; class&nbsp;Sayhello&nbsp;extends&nbsp;\Magento\Framework\App\Action\Action { &nbsp;&nbsp;&nbsp;&nbsp;/** &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;say&nbsp;hello&nbsp;text &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;execute() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;die(&quot;Hello&nbsp;;)&nbsp;-&nbsp;Inchoo\\CustomControllers\\Controller\\Demonstration\\Sayhello&nbsp;-&nbsp;execute()&nbsp;method&quot;); &nbsp;&nbsp;&nbsp;&nbsp;} }</pre><p>对于管理控制器,让我们匹配网址siteurl/admin/inchooadmintest/demo/sayadmin/。为此,我们需要 Controller/Adminhtml 中的演示文件夹,在该操作类中,我们需要创建 Sayadmin.php</p><pre class="brush:bash;toolbar:false">&lt;?php /** &nbsp;*&nbsp;Copyright&nbsp;©&nbsp;2015&nbsp;Inchoo&nbsp;d.o.o. &nbsp;*&nbsp;created&nbsp;by&nbsp;Zoran&nbsp;Salamun(zoran.salamun@inchoo.net) &nbsp;*/ namespace&nbsp;Inchoo\CustomControllers\Controller\Adminhtml\Demonstration; &nbsp; class&nbsp;Sayadmin&nbsp;extends&nbsp;\Magento\Backend\App\Action { &nbsp;&nbsp;&nbsp;&nbsp;/** &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;say&nbsp;admin&nbsp;text &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;execute() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;die(&quot;Admin&nbsp;;)&nbsp;-&nbsp;Inchoo\\CustomControllers\\Controller\\Adminhtml\\Demonstration\\Sayadmin&nbsp;-&nbsp;execute()&nbsp;method&quot;); &nbsp;&nbsp;&nbsp;&nbsp;} }</pre><pre class="brush:bash;toolbar:false">php&nbsp;bin/magento&nbsp;setup:upgrade php&nbsp;bin/magento&nbsp;module:enable&nbsp;Inchoo_CustomControllers php&nbsp;bin/magento&nbsp;setup:upgrade</pre><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 2模块。如果您已经熟悉Magento 1,那么所有示例都将非常清楚。创建运输方式非常简单,所以让我们举个例子。</p><p>首先,您需要创建一个Magento模块。您应该创建目录结构,如下面的屏幕截图所示:</p><p>Magento 2模块二极管结构</p><p>创建模块后,您应该使用 shell 脚本启用模块:</p><pre class="brush:bash;toolbar:false">php&nbsp;-f&nbsp;/bin/magento&nbsp;module:enable&nbsp;Inchoo_Shipping</pre><p>此外,您可以使用命令检查是否启用模块(此脚本将打印所有已启用模块的列表):<br/></p><pre class="brush:bash;toolbar:false">php&nbsp;-f&nbsp;/bin/magento&nbsp;module:status</pre><p>让我们从一个处理运输方法的类开始。首先,运输方法应在文件配置.xml中定义,如下面的屏幕截图所示。没有它,它就无法工作。xml 中的主节点是“默认”节点,节点“承运人”的子节点应与运输类“Inchoo\Shipping\Model\Carrier\Example”中的属性 $_code 具有相同的名称。</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_Store:etc/config.xsd&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;default&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;carriers&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;example&gt; &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;sallowspecific&gt;0&lt;/sallowspecific&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;model&gt;Inchoo\Shipping\Model\Carrier\Example&lt;/model&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;name&gt;Inchoo&nbsp;Example&nbsp;Shipping&lt;/name&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;price&gt;15.00&lt;/price&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;title&gt;Inchoo&nbsp;Example&lt;/title&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;type&gt;I&lt;/type&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;specificerrmsg&gt;This&nbsp;shipping&nbsp;method&nbsp;is&nbsp;not&nbsp;available.&nbsp;To&nbsp;use&nbsp;this&nbsp;shipping&nbsp;method,&nbsp;please&nbsp;contact&nbsp;us.&lt;/specificerrmsg&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/example&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/carriers&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/default&gt; &lt;/config&gt;</pre><p>在我们的配置中.xml您会注意到XML节点“模型”,它定义了php类“Inchoo\Shipping\Model\Carrier\Example”。此型号类按运输方式收费。在此类中应实现所有用于运输计算的逻辑。</p><p>此外,每种运输方式都应该在管理中具有配置选项。您可以通过 system.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:module:Magento_Config:etc/system_file.xsd&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;system&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;section&nbsp;id=&quot;carriers&quot;&nbsp;translate=&quot;label&quot;&nbsp;type=&quot;text&quot;&nbsp;sortOrder=&quot;320&quot;&nbsp;showInDefault=&quot;1&quot;&nbsp;showInWebsite=&quot;1&quot;&nbsp;showInStore=&quot;1&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;group&nbsp;id=&quot;example&quot;&nbsp;translate=&quot;label&quot;&nbsp;type=&quot;text&quot;&nbsp;sortOrder=&quot;0&quot;&nbsp;showInDefault=&quot;1&quot;&nbsp;showInWebsite=&quot;1&quot;&nbsp;showInStore=&quot;1&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;label&gt;Inchoo&nbsp;Example&lt;/label&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;field&nbsp;id=&quot;active&quot;&nbsp;translate=&quot;label&quot;&nbsp;type=&quot;select&quot;&nbsp;sortOrder=&quot;1&quot;&nbsp;showInDefault=&quot;1&quot;&nbsp;showInWebsite=&quot;1&quot;&nbsp;showInStore=&quot;0&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;label&gt;Enabled&lt;/label&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;source_model&gt;Magento\Config\Model\Config\Source\Yesno&lt;/source_model&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/field&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;field&nbsp;id=&quot;name&quot;&nbsp;translate=&quot;label&quot;&nbsp;type=&quot;text&quot;&nbsp;sortOrder=&quot;3&quot;&nbsp;showInDefault=&quot;1&quot;&nbsp;showInWebsite=&quot;1&quot;&nbsp;showInStore=&quot;1&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;label&gt;Method&nbsp;Name&lt;/label&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/field&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;field&nbsp;id=&quot;price&quot;&nbsp;translate=&quot;label&quot;&nbsp;type=&quot;text&quot;&nbsp;sortOrder=&quot;5&quot;&nbsp;showInDefault=&quot;1&quot;&nbsp;showInWebsite=&quot;1&quot;&nbsp;showInStore=&quot;0&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;label&gt;Price&lt;/label&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;validate&gt;validate-number&nbsp;validate-zero-or-greater&lt;/validate&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/field&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;field&nbsp;id=&quot;handling_type&quot;&nbsp;translate=&quot;label&quot;&nbsp;type=&quot;select&quot;&nbsp;sortOrder=&quot;7&quot;&nbsp;showInDefault=&quot;1&quot;&nbsp;showInWebsite=&quot;1&quot;&nbsp;showInStore=&quot;0&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;label&gt;Calculate&nbsp;Handling&nbsp;Fee&lt;/label&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;source_model&gt;Magento\Shipping\Model\Source\HandlingType&lt;/source_model&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/field&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;field&nbsp;id=&quot;handling_fee&quot;&nbsp;translate=&quot;label&quot;&nbsp;type=&quot;text&quot;&nbsp;sortOrder=&quot;8&quot;&nbsp;showInDefault=&quot;1&quot;&nbsp;showInWebsite=&quot;1&quot;&nbsp;showInStore=&quot;0&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;label&gt;Handling&nbsp;Fee&lt;/label&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;validate&gt;validate-number&nbsp;validate-zero-or-greater&lt;/validate&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/field&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;field&nbsp;id=&quot;sort_order&quot;&nbsp;translate=&quot;label&quot;&nbsp;type=&quot;text&quot;&nbsp;sortOrder=&quot;100&quot;&nbsp;showInDefault=&quot;1&quot;&nbsp;showInWebsite=&quot;1&quot;&nbsp;showInStore=&quot;0&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;label&gt;Sort&nbsp;Order&lt;/label&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/field&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;field&nbsp;id=&quot;title&quot;&nbsp;translate=&quot;label&quot;&nbsp;type=&quot;text&quot;&nbsp;sortOrder=&quot;2&quot;&nbsp;showInDefault=&quot;1&quot;&nbsp;showInWebsite=&quot;1&quot;&nbsp;showInStore=&quot;1&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;label&gt;Title&lt;/label&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/field&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;field&nbsp;id=&quot;sallowspecific&quot;&nbsp;translate=&quot;label&quot;&nbsp;type=&quot;select&quot;&nbsp;sortOrder=&quot;90&quot;&nbsp;showInDefault=&quot;1&quot;&nbsp;showInWebsite=&quot;1&quot;&nbsp;showInStore=&quot;0&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;label&gt;Ship&nbsp;to&nbsp;Applicable&nbsp;Countries&lt;/label&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;frontend_class&gt;shipping-applicable-country&lt;/frontend_class&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;source_model&gt;Magento\Shipping\Model\Config\Source\Allspecificcountries&lt;/source_model&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/field&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;field&nbsp;id=&quot;specificcountry&quot;&nbsp;translate=&quot;label&quot;&nbsp;type=&quot;multiselect&quot;&nbsp;sortOrder=&quot;91&quot;&nbsp;showInDefault=&quot;1&quot;&nbsp;showInWebsite=&quot;1&quot;&nbsp;showInStore=&quot;0&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;label&gt;Ship&nbsp;to&nbsp;Specific&nbsp;Countries&lt;/label&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;source_model&gt;Magento\Directory\Model\Config\Source\Country&lt;/source_model&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;can_be_empty&gt;1&lt;/can_be_empty&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/field&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;field&nbsp;id=&quot;showmethod&quot;&nbsp;translate=&quot;label&quot;&nbsp;type=&quot;select&quot;&nbsp;sortOrder=&quot;92&quot;&nbsp;showInDefault=&quot;1&quot;&nbsp;showInWebsite=&quot;1&quot;&nbsp;showInStore=&quot;0&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;label&gt;Show&nbsp;Method&nbsp;if&nbsp;Not&nbsp;Applicable&lt;/label&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;source_model&gt;Magento\Config\Model\Config\Source\Yesno&lt;/source_model&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/field&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;field&nbsp;id=&quot;specificerrmsg&quot;&nbsp;translate=&quot;label&quot;&nbsp;type=&quot;textarea&quot;&nbsp;sortOrder=&quot;80&quot;&nbsp;showInDefault=&quot;1&quot;&nbsp;showInWebsite=&quot;1&quot;&nbsp;showInStore=&quot;1&quot;&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;label&gt;Displayed&nbsp;Error&nbsp;Message&lt;/label&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/field&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/group&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/section&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/system&gt; &lt;/config&gt;</pre><p>发货类别应类似于以下示例:</p><pre class="brush:bash;toolbar:false">&lt;?php namespace&nbsp;Inchoo\Shipping\Model\Carrier; &nbsp; use&nbsp;Magento\Quote\Model\Quote\Address\RateRequest; use&nbsp;Magento\Shipping\Model\Rate\Result; &nbsp; class&nbsp;Example&nbsp;extends&nbsp;\Magento\Shipping\Model\Carrier\AbstractCarrier&nbsp;implements &nbsp;&nbsp;&nbsp;&nbsp;\Magento\Shipping\Model\Carrier\CarrierInterface { &nbsp;&nbsp;&nbsp;&nbsp;/** &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@var&nbsp;string &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;$_code&nbsp;=&nbsp;&#39;example&#39;; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;/** &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;\Magento\Framework\App\Config\ScopeConfigInterface&nbsp;$scopeConfig &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;\Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory&nbsp;$rateErrorFactory &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;\Psr\Log\LoggerInterface&nbsp;$logger &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;\Magento\Shipping\Model\Rate\ResultFactory&nbsp;$rateResultFactory &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;\Magento\Quote\Model\Quote\Address\RateResult\MethodFactory&nbsp;$rateMethodFactory &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;array&nbsp;$data &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;__construct( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\Magento\Framework\App\Config\ScopeConfigInterface&nbsp;$scopeConfig, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory&nbsp;$rateErrorFactory, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\Psr\Log\LoggerInterface&nbsp;$logger, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\Magento\Shipping\Model\Rate\ResultFactory&nbsp;$rateResultFactory, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\Magento\Quote\Model\Quote\Address\RateResult\MethodFactory&nbsp;$rateMethodFactory, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;array&nbsp;$data&nbsp;=&nbsp;[] &nbsp;&nbsp;&nbsp;&nbsp;)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;_rateResultFactory&nbsp;=&nbsp;$rateResultFactory; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;_rateMethodFactory&nbsp;=&nbsp;$rateMethodFactory; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parent::__construct($scopeConfig,&nbsp;$rateErrorFactory,&nbsp;$logger,&nbsp;$data); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;/** &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;array &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;getAllowedMethods() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;[&#39;example&#39;&nbsp;=&gt;&nbsp;$this-&gt;getConfigData(&#39;name&#39;)]; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;/** &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;RateRequest&nbsp;$request &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;bool|Result &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;collectRates(RateRequest&nbsp;$request) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!$this-&gt;getConfigFlag(&#39;active&#39;))&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;false; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/**&nbsp;@var&nbsp;\Magento\Shipping\Model\Rate\Result&nbsp;$result&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$result&nbsp;=&nbsp;$this-&gt;_rateResultFactory-&gt;create(); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/**&nbsp;@var&nbsp;\Magento\Quote\Model\Quote\Address\RateResult\Method&nbsp;$method&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$method&nbsp;=&nbsp;$this-&gt;_rateMethodFactory-&gt;create(); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$method-&gt;setCarrier(&#39;example&#39;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$method-&gt;setCarrierTitle($this-&gt;getConfigData(&#39;title&#39;)); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$method-&gt;setMethod(&#39;example&#39;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$method-&gt;setMethodTitle($this-&gt;getConfigData(&#39;name&#39;)); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*you&nbsp;can&nbsp;fetch&nbsp;shipping&nbsp;price&nbsp;from&nbsp;different&nbsp;sources&nbsp;over&nbsp;some&nbsp;APIs,&nbsp;we&nbsp;used&nbsp;price&nbsp;from&nbsp;config.xml&nbsp;-&nbsp;xml&nbsp;node&nbsp;price*/ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$amount&nbsp;=&nbsp;$this-&gt;getConfigData(&#39;price&#39;); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$method-&gt;setPrice($amount); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$method-&gt;setCost($amount); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$result-&gt;append($method); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$result; &nbsp;&nbsp;&nbsp;&nbsp;} }</pre><p>为了正确地为运输方法编写php类,您应该尊重一些Magento 2规则。每个Magento 2运输类都应该扩展“\Magento\Shipping\Model\Carrier\AbstractCarrier”并实现“\Magento\Shipping\Model\Carrier\CarrierInterface”。</p><p>在运输模型中,您需要创建至少两个 php 方法:“getAllowedMethods”和“collectRates”。抽象类和接口需要此方法。此外,您应该使用值定义属性 $_code。在我们的例子中,这就是“例子”。它与配置.xml和节点结构有关。</p><p>Php 方法 “collectRates” 接受参数 “$request”,它是类 “Magento\Quote\Model\Quote\Address\RateRequest” 的实例。此类包含有关购物车/报价、重量、送货地址等物料的所有信息。在此方法中,您可以实现运费计算的所有逻辑。通过此方法,您可以调用其他服务进行运费计算,但这取决于您的集成。</p><p>您可以在下面的屏幕截图中看到更多信息。</p><p>装运请求对象</p><p>如果您按照我写的格式实现了所有内容,您将能够在结帐时看到运输方式。</p><p><br/></p>

如何使用requireJS在Magento2中添加自定义javascript

<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在javascript中带来了一些新功能。其中一个是“requireJS”(javascript文件加载器),第二个是“jQuery”,一个非常流行的js库。最大的好处之一是使用requireJS,这意味着Magento 2已经为即将推出的HTTP2协议做好了准备。在接下来的几个步骤中,我们将解释如何创建有效的 javascript 代码以在 requireJS 中使用。让我们从一个例子开始。</p><p>像往常一样,我们需要创建一个有效的Magento 2模块,如下面的屏幕所示:</p><p><img src="/uploads/images/20230822/0431acdef3f69c10d2695b308ad0f925.png" title="3.png" alt=""/></p><p>您可能会注意到Magento 1和Magento 2之间的一些差异,因为所有javascript,layout和template phtml文件现在都属于该模块。此外,我们的javascript文件位于位于目录路径上的模块中:“app/code/Inchoo/Js/view/frontend/web/js/”。在这个例子中,我们创建了两个js文件:“inchoo.js”和“logger.js”</p><p>看看我们的javascript代码,它适用于requireJS环境。</p><p><br/></p><pre class="brush:bash;toolbar:false">define([ &nbsp;&nbsp;&nbsp;&nbsp;&quot;jquery&quot;, &nbsp;&nbsp;&nbsp;&nbsp;&quot;logger&quot;, &nbsp;&nbsp;&nbsp;&nbsp;&quot;jquery/ui&quot; ],&nbsp;function($,&nbsp;logger)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&quot;use&nbsp;strict&quot;; &nbsp;&nbsp;&nbsp;&nbsp;logger.log(&#39;inchoo.js&nbsp;is&nbsp;loaded!!&#39;); &nbsp;&nbsp;&nbsp;&nbsp;logger.log(logger); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//creating&nbsp;jquery&nbsp;widget &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$.widget(&#39;inchoo.js&#39;,&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_create:&nbsp;function()&nbsp;{ &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//options&nbsp;which&nbsp;you&nbsp;can&nbsp;pass&nbsp;from&nbsp;js.phtml&nbsp;file&nbsp;in&nbsp;json&nbsp;format &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.log(this.options); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//access&nbsp;to&nbsp;element&nbsp;p#test &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.log(this.element); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//for&nbsp;exmple,&nbsp;you&nbsp;can&nbsp;create&nbsp;some&nbsp;click&nbsp;event&nbsp;or&nbsp;something&nbsp;else &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.element.on(&#39;click&#39;,&nbsp;function(e){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.log(&quot;You&nbsp;click&nbsp;on&nbsp;element:&nbsp;&quot;&nbsp;+&nbsp;e.target); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}); &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$.inchoo.js; });</pre><p>您会注意到顶部的javascript代码使用了“define”函数。</p><p>这个函数来自requireJs – “define”函数的第一个参数是依赖数组,第二个参数是我们函数的定义。</p><p>定义函数应始终返回一个对象。在我们的示例中,我们的函数返回 “$.inchoo.js”。</p><p>您可以在 url 上阅读有关定义函数的更多信息: http://requirejs.org/docs/api.html<span style="color: #6a9955;">#define</span></p><p>在我们的示例中,我们的javascript使用jQuery,jQueryUI和logger。所有依赖项都应在“定义”函数中声明。您可以看到我们将下一个数组作为第一个参数:</p><p>[&quot;jquery&quot;, &quot;logger&quot;, &quot;jquery/ui&quot;]</p><p>在函数的定义中,我们创建了jquery小部件,并将所有逻辑放在小部件构造函数“_create”中。JQuery 和记录器作为下一个参数传递:“$”和“记录器”。</p><p>我们的记录器类的源代码如下。你可以注意到我们的类不需要任何依赖关系,在“define”函数中,只有定义函数返回我们之前提到的对象。</p><p><br/></p><pre class="brush:bash;toolbar:false">define(function()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&quot;use&nbsp;strict&quot;; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log&nbsp;:&nbsp;function(param){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log(param); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;}; });</pre><p>所有文件都应该在“requirejs-config.js”文件中声明 - 这是使用requireJs的配置文件。</p><pre class="brush:bash;toolbar:false">var&nbsp;config&nbsp;=&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;map:&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;*&#39;:&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inchoojs:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;Inchoo_Js/js/inchoo&#39;, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;Inchoo_Js/js/logger&#39; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;} };</pre><p>下一步将是解释如何加载和使用我们的 JavaScript。为了使用/加载我们的javascript,你必须在某个phtml文件中添加下一个代码。我们完整的js.phtml文件示例如下:</p><p>测试元件</p><p>&lt;script <span style="color: #569cd6;">type</span>=<span style="color: #ce9178;">&quot;text/x-magento-init&quot;</span>&gt;// &lt;![CDATA[ { <span style="color: #ce9178;">&quot;#test&quot;</span>: { <span style="color: #ce9178;">&quot;Inchoo_Js/js/inchoo&quot;</span>: {<span style="color: #ce9178;">&quot;url&quot;</span>:<span style="color: #ce9178;">&quot;http://www.example.url&quot;</span>, <span style="color: #ce9178;">&quot;method&quot;</span>:<span style="color: #ce9178;">&quot;post&quot;</span>} } } // ]]&gt;&lt;/script&gt;</p><p>在Magento 2中,有一个javascript解析器(位于脚本“lib/web/mage/apply/scripts.js中),它读取属性类型=”text/x-magento-init“的脚本标签,并使用卷曲的brakets中的”子“json数据加载/处理它们:</p><pre class="brush:bash;toolbar:false"> &quot;#test&quot;:&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;Inchoo_Js/js/inchoo&quot;: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&quot;url&quot;:&quot;http://www.example.url&quot;,&nbsp;&quot;method&quot;:&quot;post&quot;} &nbsp;&nbsp;&nbsp;&nbsp;}</pre><p>你会注意到“<span style="color: #6a9955;">#test”,这是传递给jquery小部件的html元素的id,它在我们的脚本中可用,通过属性“this.element”。其他元素“url”和“method”是选项,它们也从json对象传递到我们的小部件,这些选项在js属性“this.options”的脚本中可用。可以根据需要定义这些选项。</span></p><p>如果您按照上述方式执行了所有操作,javascript 应该可以工作,并且您应该在 html head 中有一个脚本标签</p><p><br/></p>

在Magento2中添加新的控制台命令Command

<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 shell或php脚本来执行一些操作,但不知道把它放在哪里吗?</p><p>还记得根 Magento 安装中的 /shell 文件夹(或根文件夹,就此而言)吗?</p><p>还记得它曾经是如何混合 50 个 shell 和 php 脚本的,光看它们你就头疼吗?</p><p>Pepperidge Farm记得。</p><p>那是美好的旧时光,像所有美好的时光一样,它们现在已经过去。街区上有一个新的孩子,更强大,更酷,最好的部分是 - 它被集成到Magento 2中。</p><p>当然,我们正在谈论Magento 2的新功能,即其控制台组件。</p><p>根文件夹现在包含一个新目录 – ,其中有一个“magento”脚本,用于启动控制台组件。通过在终端中输入,我们会收到许多可以运行的命令,例如:/binbin/magento</p><p>创建管理员用户(管理员:用户:创建)</p><p>清除、禁用、启用缓存(缓存:清理、缓存:启用、缓存:禁用等)</p><p>运行 cron (cron:run)</p><p>启用和禁用模块(模块:启用,模块:禁用)</p><p>检查索引器状态,并在需要时重新索引(索引器:信息、索引器:重新索引等)</p><p>等等</p><p>与Magento 1相比,这是一个重大改进,就像Magento所做的一切一样(尽管这个是从Symfony借来的),它是高度可定制和可扩展的。我们可以相当轻松地添加自己的命令,这正是我们将在本文中要做的。</p><p>我们不会详细介绍在Magento 2中创建新模块,因为已经有很多教程可以遵循。</p><p>为了添加新命令,我们只需要执行几个步骤。首先,在模块的 etc 文件夹中创建一个 di.xml 文件(如果您还没有),并将其放入:</p><pre class="brush:bash;toolbar:false">&lt;?xml&nbsp;version=&quot;1.0&quot;?&gt; &nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&lt;type&nbsp;name=&quot;Magento\Framework\Console\CommandList&quot;&gt; &nbsp;&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item&nbsp;name=&quot;hello_world&quot;&nbsp;xsi:type=&quot;object&quot;&gt;Inchoo\Console\Console\Command\HelloWorldCommand&lt;/item&gt; &nbsp;&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;&nbsp;&lt;/arguments&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/type&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/config&gt;</pre><p>我们在 di.xml 文件中添加了一个新条目。它有什么作用?如果我们检查类型标签及其名称,我们会看到它指向我们。此外,它还具有一些名为“命令”的参数和一个项目标签。看起来很奇怪。让我们去上课,看看有什么大惊小怪的:<span style="color: #ce9178;">&quot;Magento\Framework\Console\CommandList&quot;</span>CommandList</p><pre class="brush:bash;toolbar:false">class&nbsp;CommandList&nbsp;implements&nbsp;CommandListInterface { &nbsp;&nbsp;&nbsp;&nbsp;/** &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@var&nbsp;string[] &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;$commands; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;/** &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Constructor &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;array&nbsp;$commands &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;__construct(array&nbsp;$commands&nbsp;=&nbsp;[]) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;commands&nbsp;=&nbsp;$commands; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;/** &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;{@inheritdoc} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;getCommands() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$this-&gt;commands; &nbsp;&nbsp;&nbsp;&nbsp;} }</pre><p>这里没有太多事情发生。简单类,其中构造函数接收数组作为参数,并且它有一个 getter 方法和一个受保护的变量,以及。嗯..等等,构造函数正在接收数组?这看起来很熟悉。我们有一些东西提到了一个名为 .让我们再看一遍:commandscommandsdi.xmlcommands</p><pre class="brush:bash;toolbar:false">&lt;arguments&gt; &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;&lt;item&nbsp;name=&quot;hello_world&quot;&nbsp;xsi:type=&quot;object&quot;&gt;Inchoo\Console\Console\Command\HelloWorldCommand&lt;/item&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;/argument&gt; &lt;/arguments&gt;</pre><p>有趣。我们的参数标签确实被调用,并且它的类型设置为“数组”。看起来Magento正在使用某种魔法将我们的参数发送到CommandList类。 有一个 ,这必须是它发送的东西。</p><p>如果我们检查Magento文档(是的,您没看错):di.xmlscommands&lt;argument&gt;&lt;item&gt;</p><p>“参数在创建类实例期间注入到类实例中。参数名称必须与已配置类的构造函数参数相对应。</p><p>我们看到这实际上是工作中的依赖注入——将我们的 Command 对象注入到所有命令的数组中。整洁。</p><p>让我们看看这个 HelloWorldCommand 类(它位于我们模块的控制台目录中)。</p><pre class="brush:bash;toolbar:false">class&nbsp;HelloWorldCommand&nbsp;extends&nbsp;Command { &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;function&nbsp;configure() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;setName(&#39;inchoo:hello_world&#39;)-&gt;setDescription(&#39;Prints&nbsp;hello&nbsp;world.&#39;); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;function&nbsp;execute(InputInterface&nbsp;$input,&nbsp;OutputInterface&nbsp;$output) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$output-&gt;writeln(&#39;Hello&nbsp;World!&#39;); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp; }</pre><p>这里只有两种方法:和 。我们从父类 () 继承它们,它们允许我们设置命令。configureexecuteCommand</p><p>Configure方法用于将初始配置设置为命令,例如:名称,描述,命令行参数等。 方法是您编写逻辑的地方。</p><p>在这个例子中,我们刚刚将“Hello World!”打印到屏幕上,但希望你会有更多的想象力。Execute</p><p>要查看该命令的运行情况,请使用 bin/magento 调用它,如下所示:</p><p>bin/magento inchoo:hello_world</p><p>你会受到命令行的欢迎。什么感觉。</p><p>为了让您的生活更轻松,我们准备了一个可以安装的作曲家存储库,无需键入所有内容即可尝试该命令。</p><p>以下是说明:</p><p>将我们的模块添加为依赖项:</p><pre class="brush:bash;toolbar:false">composer&nbsp;config&nbsp;repositories.inchoo_console&nbsp;vcs&nbsp;git@bitbucket.org:lurajcevi/inchoo_console.git</pre><p>请composer下载它:</p><pre class="brush:bash;toolbar:false">composer&nbsp;require&nbsp;inchoo/console:dev-master</pre><p>如果 Composer 要求您提供一组凭据,请按照这些说明操作。</p><p>当composer施展魔法时,我们可以启用我们的模块:</p><pre class="brush:bash;toolbar:false">bin/magento&nbsp;module:enable&nbsp;Inchoo_Console</pre><p>及以后</p><pre class="brush:bash;toolbar:false">bin/magento&nbsp;setup:upgrade</pre><p>我们的模块已启用,我们可以使用它。由于这个想法是向控制台应用程序添加新命令,让我们看看它是否有效。再次呼叫。bin/magento</p><p>希望您会看到以下命令(以及其他所有命令):</p><p>...</p><p>inchoo</p><p>inchoo:hello_world Prints hello world.</p><p>...</p><p>让我们调用它:</p><p>bin/magento inchoo:hello_world</p><p>响应是,正如预期的那样:</p><pre class="brush:bash;toolbar:false">Hello&nbsp;World!</pre><p><br/></p>

扩展Magento2默认JS组件

<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>在这篇文章中,我将演示如何处理平台的默认javascript组件(widget实例)。更准确地说,是负责网站主导航功能的javascript组件。如果您有兴趣,请继续阅读。</p><p><span style="color: #6a9955;">### 介绍</span></p><p>Magento 2中主导航的前端部分是用javascript逻辑构建的,负责从移动设备的转换到台式计算机的悬停延迟计时的众多操作。在大多数情况下,默认方法就足够了,并且基本上涵盖了所有需求,但有时,在项目需要特定/自定义方法的情况下,我们迟早会发现自己处于修改默认逻辑的情况。</p><p>让我们把自己放在一个位置,我们的项目需要对主导航javascript部分进行某些修改。首先,我们需要了解该过程涉及的一些基本文件架构和技术。</p><p>Magento 2使用Require JS(AMD或异步模块加载器和jQuery/jQuery UI库)作为创建系统上当前存在的javascript组件的基础。</p><p>我不会进一步介绍requireJS,但如果您需要了解更多信息,您可以查看我们涵盖此主题的博客文章。另外,我强烈建议访问requireJS网站,以便在使用Magento 2之前获得AMD的坚实基础知识并要求JS基本用法。</p><p>另一个重要的注意事项是,jQuery UI widget factory用于提供简单的可扩展技术,与Magento 1中的旧原型类方法非常相似。如果你不熟悉jQuery UI小部件,我强烈建议你访问学习jQuery网站,其中包含小部件工厂示例,以熟悉这个概念。</p><p><span style="color: #6a9955;">### 扩展默认值</span></p><p>负责导航菜单功能的主文件是menu.js位于[project_root]/lib/web/mage/下,以及其他默认的js系统组件。</p><p>现在,如果我们不想扩展或覆盖它,我们需要确保我们遵循以下步骤。</p><p><span style="color: #6a9955;">### 步骤 1</span></p><p>要使用我们的自定义内容正确扩展菜单.js部分,第一步是映射我们的 js 文件,以便系统加载它而不是默认文件。</p><p>Magento使用requirejs-config.js文件成功地映射系统上的js组件。首先重要的是知道在哪里放置requirejs-config.js。它可以放置在多个层次上。</p><p>所有requireJS配置将按以下顺序合并和执行:</p><p>模块级别</p><p>主题模块级别(父主题)</p><p>主题模块级别(当前主题)</p><p>主题级别(父主题)</p><p>主题级别(当前主题)</p><p>让我们用一个真实的例子看看它是如何工作的。默认文件是菜单.js我们希望将其替换为我们的自定义文件。请注意,之后我仍将加载默认菜单.js文件作为依赖项。</p><p>我们需要创建将替换菜单.js文件的文件。我们称之为menu-custom.js并将其放在[current_theme]/web/js/目录下。</p><p><span style="color: #6a9955;">### 步骤 2</span></p><p>接下来,我们需要创建requirejs-config.js文件并将其放在[current_theme]/root目录下。这样我们就可以成功映射我们的文件以替换默认文件。请参阅以下示例:</p><pre class="brush:bash;toolbar:false">var&nbsp;config&nbsp;=&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&quot;map&quot;:&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;*&quot;:&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;menu&quot;:&nbsp;&quot;js/menu-custom&quot; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;} };</pre><p>要真正确定该过程是否成功,请确保在加载新文件时签入开发人员工具。</p><p><img src="/uploads/images/20230822/209495ef98a89ddbd9a3fe51f81df742.png" title="6.png" alt=""/></p><p><span style="color: #6a9955;">### 步骤 3</span></p><p>现在是有趣的部分!我们不想扩展默认功能,这就是jQuery小部件工厂发挥作用的地方。我们将以下代码放入我们新创建的菜单自定义.js文件中。</p><p>检查以下示例:</p><pre class="brush:bash;toolbar:false">define([ &nbsp;&nbsp;&nbsp;&nbsp;&#39;jquery&#39;, &nbsp;&nbsp;&nbsp;&nbsp;&#39;jquery/ui&#39;, &nbsp;&nbsp;&nbsp;&nbsp;&#39;mage/menu&#39;], &nbsp;&nbsp;&nbsp;&nbsp;function($){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$.widget(&#39;inchoo.menu&#39;,&nbsp;$.mage.menu,&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_init:&nbsp;function&nbsp;()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(&quot;I&#39;m&nbsp;Inchoo&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;toggle:&nbsp;function&nbsp;()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(&quot;I&#39;m&nbsp;Inchoo&quot;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;}); &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$.inchoo.menu; &nbsp;&nbsp;&nbsp;&nbsp;});</pre><p><span style="color: #6a9955;"></span><br/></p><p>从上面的例子中我们可以看到,我们正在使用 require js 来定义我们的依赖项。第一个是jquery,第二个是jquery/ui,最后一个是mage/menu。</p><p>这意味着在这 3 个完全加载之前,我们的脚本不会加载,因为我们的逻辑依赖于它。</p><p>我们名为 inchoo.menu 的自定义小部件实例正在扩展默认的 $.mage.menu,在本例中,为了本教程,我将扩展两种方法,_init 和切换。切换方法负责切换智能手机和平板电脑上的导航_init而该方法负责组件初始化。</p><p>默认菜单中的原始切换方法示例.js</p><pre class="brush:bash;toolbar:false">toggle:&nbsp;function&nbsp;()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;($(&#39;html&#39;).hasClass(&#39;nav-open&#39;))&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(&#39;html&#39;).removeClass(&#39;nav-open&#39;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setTimeout(function&nbsp;()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(&#39;html&#39;).removeClass(&#39;nav-before-open&#39;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},&nbsp;300); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(&#39;html&#39;).addClass(&#39;nav-before-open&#39;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setTimeout(function&nbsp;()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(&#39;html&#39;).addClass(&#39;nav-open&#39;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},&nbsp;42); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},</pre><p><span style="color: #6a9955;">### 覆盖文件</span></p><p>在某些情况下(尽管在相对罕见的情况下),您会发现自己可以完全覆盖菜单逻辑(创建自定义导航)。在这种特定情况下,我们可以应用步骤 1 和步骤 2,并在菜单自定义.js文件中创建自定义导航逻辑。</p><p>就是这样!我们已经成功地扩展了默认菜单.js小部件实例。该过程可以应用于系统上当前显示的任何小部件实例。</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缺乏大多数请求的功能,开发人员不得不寻找其他解决方案或编写自己的解决方案。让我们看看Magento 2的情况如何。</p><p>为了最终解决这个问题,Magento 2附带了一个新的小部件,可以根据来自各种属性和类别的基于条件的过滤器进行产品选择。如果有人曾经使用过购物车价格规则,这种方法对他们来说并不是什么新鲜事。可以根据产品属性和类别的任意组合创建条件,其中仅显示与规则匹配的产品。</p><p><img src="/uploads/images/20230822/b59a091ad9cf2bfb1100773e8a5cd7e1.png" title="4.png" alt="" width="652" height="746"/></p><p><span style="color: #6a9955;">### 配置选项有哪些?</span></p><p>除了定义条件外,小部件还提供了一些其他配置选项,例如定义标题,启用分页,模板选择,从中创建简单的产品列表。定义条件是一个非常好的功能,它提供了产品选择的灵活性,而不是简单的产品选择(也可以通过SKU属性定义条件来实现),但这种方法有一个缺点。通过定义条件,而不是特定的产品,输出可以做的事情不多,在前端显示之前基本上是未知的。我们大多数人需要和想要的一件事是定义产品列表中的项目顺序或排序,这在这种方法中是不可能的。</p><p><span style="color: #6a9955;">### 如何创建一个?</span></p><p>嗯,有两种方法可以做到这一点。第一种方法是创建并将它们作为CMS块和页面内容的一部分(在管理中可用,位于内容&gt;元素&gt;页面/块)。在所见即所得的编辑器中,有一个插入小部件按钮,允许它们快速创建并插入内容中的光标位置。从下拉列表中选择目录产品列表选项并填写字段。</p><p>另一种方法是创建它们并插入布局更新的位置。导航到内容&gt;元素&gt;微件,然后选择目录产品列表作为类型和您当前的设计主题。布局更新部分允许选择小部件将显示在哪些页面上以及在页面的哪个部分显示。</p><p><img src="/uploads/images/20230822/e67b17588e7d4ce5f2a96f0ee98a8f61.png" title="5.png" alt=""/></p><p>将产品列表小部件包含在Magento中是向前迈出的一步,由于安装中已经打包了这样的功能,因此开发变得更加容易。创建和包含产品列表小部件既简单又快速,对于那些不需要完全控制产品列表的人来说,肯定会在许多新网站上使用。</p><p><br/></p>