今天,我们要介绍的几个Magento的路由系统的高级功能,并讨论一些看似急性锐边的历史。虽然所有在这篇文章中提供的技术可能不是最好的方式来实现自己的目标,作为工作的Magento开发者你需要知道他们是可能的,而其他开发者(包括Magento的核心工程团队)可能已经使用他们。

本文假定您有较好的Magento 2模块经验,这可能不适合初学者。如果这是你,用评论来问你的问题或指向你的堆叠交换的问题。

Magento的URL在Action中

作为一个PHP程序员,当你需要创建在Magento的URL,可以使用getUrl块或URL模型对象的方法。

Mage::getUrl('foo/baz/bar');
$urlModel->getUrl('foo/baz/bar');
$this->getUrl('foo/baz/bar');

这是Magento的1和2的Magento真正在Magento 2你没有进入全球Mage::getUrl的方法,所以你需要注入要通过特定的URL模式自动构造函数依赖注入。网址模型允许PHP程序员治疗的URL作为一个简单的操作字符串,然后让核心系统构建代码的最终呈现的网址。如果你只做过前端的工作,这似乎有点小题大做,但如果URL结构需要在将来改变或适应多种环境是有利的。大多数Web编程框架认为这是一个必要的功能。

我们不会太深入探究网址模型今天-我们都感兴趣的是操作字符串,这些URL方法接受。乍一看,你可能会觉得foo/baz/baz结构直接映射到frontName/controllerName/actionName一个URL的Magento的结构。你几乎是正确的。实际的结构。routeId/controllerName/actionName

当你设置一个routes.xml为你的模块文件,可以使用XML结构看起来像这样

<!-- File: app/code/Package/Module/etc/[area]/routes.xml -->
<route id="routerId" frontName="urlFrontName">
    <module name="Package_Module" />
</route>

也就是说,你设置一个<route/>节点与id和frontName属性。该id标识唯一路由节点在Magento的系统,并frontName定义了你的URL的第一部分。

当Magento的产生从操作字符串的URL一样foo/baz/bar,它采用了第一段查找一个<route/>在合并后的XML树节点,然后使用该路由节点的frontName作为第一个URL段。

这不是明显的事情,你可以在Magento的多年而不自知地发展。这是因为大多数模块使用的路线ID和相同的名字前面。

例如,您可以在中看到这个catalog模块

<!-- File: app/code/Magento/Catalog/etc/frontend/routes.xml -->
<route id="catalog" frontName="catalog">
    <module name="Magento_Catalog" />
</route>

无论是id和frontName属性catalog。该公约还存在在Magento 1。

<!-- File: app/code/core/Mage/Catalog/etc/catalog.xml -->
<frontend>
    <routers>
        <catalog>
            <use>standard</use>
            <args>
                <module>Mage_Catalog</module>
                <frontName>catalog</frontName>
            </args>
        </catalog>
    </routers>
    <!-- ... -->
</frontend>

以上是Magento的1的目录路由器配置。单个<catalog/>节点下<routers/>配置了一个frontName名为catalog。在Magento 2,该节点下<routers/>已打开的<module/>,与id替换Magento的1个节点name属性。(即<catalog/>变<module id="catalog"/>。

这种约定可以很容易地看一个URL操作字符串,并获得最终的URL将是什么样子一个粗略的想法。然而,有一个巨大的例外:Magento的管理网址。

Magento管理网址

在Magento 1,主要管理路径是与以下配置(在Magento的核心)

<!-- File: app/code/core/Mage/Adminhtml/etc/config.xml -->
<admin>
    <routers>
        <adminhtml>
            <use>admin</use>
            <args>
                <module>Mage_Adminhtml</module>
                <frontName>admin</frontName>
            </args>
        </adminhtml>
    </routers>
</admin>

也就是说,在单个节点<routers/>命名<adminhtml/>建立一个frontName命名admin。这延续到Magento的2。

File: vendor/magento/module-backend/etc/adminhtml/routes.xml

<route id="adminhtml" frontName="admin">
    <module name="Magento_Backend" />
</route>

这意味着,在Magento 1,操作字符串一样adminhtml/foo/bar会翻译成看起来像一个完整的URL http://example.magento.com/ad...。也就是说,第一网址段,和前面的名称,将admin代替adminhtml。

这是一个奇怪的例外,Magento的匹配前面的名字和路由器ID的一般惯例,并有可能少了刻意的设计决定比它的Magento 1发射一个半完成的概念区(adminhtml,frontend)实现的。

无论如何,你仍然可以找到在Magento 2的代码库这种非决定的证据。

Magento的管理员入口网址

在Magento 1,adminhtml路由器ID是什么保证了管理的URL开始以字符串的一部分/admin,而Magento的区域被设置为adminhtml。

然而,在Magento 2,每一个在路线设置etc/adminhtml/routes.xml文件将自动与该字符串前缀admin。这就是让我们用我们自己的frontName这些adminhtml/routes.xml文件。

这最终有上仍然使用旧的管理网址,一个奇怪的副作用adminhtml路由器ID。考虑URL重写模块

<!-- File: vendor/magento/module-url-rewrite/etc/adminhtml/menu.xml -->
<add id="Magento_UrlRewrite::urlrewrite" 
     title="URL Rewrites" module="Magento_UrlRewrite"
     sortOrder="20" 
     parent="Magento_Backend::marketing_seo"
     action="adminhtml/url_rewrite/index"
     resource="Magento_UrlRewrite::urlrewrite"
     />

以上menu.xml文件文件使用的操作字符串adminhtml/url_rewrite/index。Magento的结束产生这样的网址

http://magento.example.com/ad...
这是与开头的URL /admin/admin。这是2管理员字符串。第一个来自/admin该Magento的预先考虑到URL段每一个管理URL。第二个使用来自Magento的adminhtml路线ID查找一个frontName属性。

这似乎是传统的URL自动转换成菜单项,虽然当我问起这个在一月份Magento的建筑师,他们最初对这个问题感到困惑,然后说这两种管理URL格式(adminhtml路径ID /前名称和自定义路径ID /前名)是有效的,但自定义路由标识和前面的名字被优先考虑。

由于缺乏明确的初始规则,缺乏核心团队的坚持这些后来下旨规则,工作Magento的开发商将要熟悉这两个URL格式,并准备根据需要调试。

URL路由共享

如果你还没有挖出过深入Magento的核心代码,你可能想知道

等等-我以为每个Magento的模块声称特定的前名字-如何可以在多个模块,声称admin通过前面的名字adminhtml路由器?

这给我们带来了从1 Magento的另一个特点,使得该跳转到Magento的2:路由共享。

Magento的“1个模块,1名前”的政策可以追溯到到Zend Framework的早期路由/ MVC体系。Magento的1,而框架中的所有自己的,基于大量的核心Zend框架类的工作,而这个“1模块,1名前”功能凑凑热闹来了。模块开发者很快发现了如何限制,这是和Magento的推出了多个模块声称一个特定的前名的能力。

如果这没有意义

当Magento的1被创造了,你只能创建控制器文件开头的URL /foo/...在单一模块中
Magento的推出了多个模块具有启动使用URL控制文件的能力/foo/在Magento 1.3
的能力,坚持在Magento 2,和语法已大大简化。例如,如果你想回到第一个模块在这个系列(Pulsestorm_HelloWorldMVVM)和添加前端URL端点catalog/foo/bar,所有你需要做的就是添加以下配置

<!-- File: app/code/Pulsestorm/HelloWorldMVVM/etc/frontend/routes.xml-->
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="standard">
        <route id="hello_mvvm" frontName="hello_mvvm">
            <module name="Pulsestorm_HelloWorldMVVM"/>
        </route>

        <!-- START: new configuration -->        
        <route id="catalog">
            <module name="Pulsestorm_HelloWorldMVVM" after="Magento_Catalog"/>
        </route>
        <!-- END:   new configuration -->                
    </router>
</config>

和以下控制器文件。

File: app/code/Pulsestorm/HelloWorldMVVM/Controller/Foo/Bar.php

<?php    namespace Pulsestorm\HelloWorldMVVM\Controller\Foo;
class Bar extends \Magento\Framework\App\Action\Action
{    
    public function execute()
    {
        var_dump("Proof of life");
    }
}

与上面的地方,你现在就有了控制器文件的第二个模块catalog前面的名称,Magento的将使用您的控制器时,您加载catalog/foo/barURI。

不像Magento的1,对于这种配置是几乎相同的设置路由为单个模块

<!-- File: app/code/Pulsestorm/HelloWorldMVVM/etc/frontend/routes.xml-->
<route id="catalog">
    <module name="Pulsestorm_HelloWorldMVVM" after="Magento_Catalog"/>
</route>

两个主要的区别是

您不要配置frontName的属性<route/>标签
你需要(或者强烈建议)用before或after标记控制命令的Magento将检查比赛

当你使用上面的配置,你告诉Magento的

嘿,你知道,<route/>有一个标签id的catalog?我要你在合并额外的 <module/>节点。

当遇到Magento的多个<module/>在其全球配置中的节点,它会检查每个模块的控制器匹配,直到找到一个。使用after标签上方保证Magento的检查我们的模块后的Magento_Catalog模块。不这样做,有可能为我们意外地创建替换芯控制器在控制器文件vendor/magento/module-catalog/Controller。

需要注意的是,你要寻找的是很重要的<route/> id属性,而不是frontName在这里属性。例如,当一个模块要添加到admin前面的名字,一个Magento的芯显影剂将

标识首次添加模块 frontName="admin"
标识<module/>的<route/>ID
使用该ID在自己的模块
确保正确before或after标签就位
所以,第一步-最初添加的模块的admin前面名称是Magento_Backend

#File: vendor/magento/module-backend/etc/adminhtml/routes.xml 
<route id="adminhtml" frontName="admin">
    <module name="Magento_Backend" />
</route>

这个<route/>节点id是adminhtml。因此,使用的其他Magento的模块admin前面的名字配置自己与id="adminhtml"。

<!-- File: vendor/magento/module-variable/etc/adminhtml/routes.xml -->
<route id="adminhtml">
    <module name="Magento_Variable" before="Magento_Backend" />
</route>

<!-- File: vendor/magento/module-widget/etc/adminhtml/routes.xml -->
<route id="adminhtml">
    <module name="Magento_Widget" before="Magento_Backend" />
</route> 

默认操作字符串段

我们从先进的路由移动之前,有一些最后要提。偶尔你会看到这是一个操作字符串缺少了第二或第三段。

<!-- File: vendor/magento/module-tax/etc/adminhtml/menu.xml -->
<add 
    id="Magento_Tax::sales_tax_rules" 
    title="Tax Rules" 
    module="Magento_Tax" 
    sortOrder="10" 
    parent="Magento_Tax::sales_tax" 
    action="tax/rule" 
    resource="Magento_Tax::manage_tax"/>

当Magento的遇到一个动作字符串以丢失的数据段,它将替代字符串的索引。换言之,作用串tax/rule上面使用是功能等效的作用串tax/rule/index。

此外,在PHP代码,您偶尔可能会看到*一个URL操作字符串的字符。

$this->getUrl('*/*/*')

这些星号将被转换为当前的前名,控制器名称或动作名称。换言之,他们创建上下文相关的URL,并且在意味着在多个模块中使用碱UI类是有用的。

原文:http://alanstorm.com/magento_...


羊爸爸
935 声望41 粉丝

很懒,没什么好写的