Routing 為 Magento 2 一個重要的部分,本文介紹基本應用
Magento 2請求的流程
在Magento 2中,請求URL將如下所示:
在該URL中,您將看到將用於查詢模組的front_name。路由器通過在routes.xml中定義為每個模組定義此名稱,我們將在下面看到更多細節。
當您在Magento 2中發出請求時,它將按照此流程查詢 controller/action
: index.php → HTTP app → FrontController → Routing → Controller processing → etc
該FrontController
會在HTTP中類中呼叫路由資訊,會發現該請求controller/action
匹配。
檔案: vendor/magento/framework/App/FrontController.php
public function dispatch(RequestInterface $request)
{
\Magento\Framework\Profiler::start('routers_match');
$routingCycleCounter = 0;
$result = null;
while (!$request->isDispatched() && $routingCycleCounter++ < 100) {
/** @var \Magento\Framework\App\RouterInterface $router */
foreach ($this->_routerList as $router) {
try {
$actionInstance = $router->match($request);
if ($actionInstance) {
$request->setDispatched(true);
$this->response->setNoCacheHeaders();
if ($actionInstance instanceof \Magento\Framework\App\Action\AbstractAction) {
$result = $actionInstance->dispatch($request);
} else {
$result = $actionInstance->execute();
}
break;
}
} catch (\Magento\Framework\Exception\NotFoundException $e) {
$request->initForward();
$request->setActionName('noroute');
$request->setDispatched(false);
break;
}
}
}
\Magento\Framework\Profiler::stop('routers_match');
if ($routingCycleCounter > 100) {
throw new \LogicException('Front controller reached 100 router match iterations');
}
return $result;
}
正如您在此dispatch()
方法中所看到的,路由器列表將迴圈以查詢與此請求匹配的路由器列表。如果它找到該請求的控制器操作,則將呼叫並執行該操作。
在frontend/adminhtml上建立自定義路由
在這部分中,我們將使用一個簡單的模組Mageplaza_HelloWorld。請按照上一篇文章瞭解如何在Magento 2中建立和註冊模組。
我們將找到如何建立前端路由,管理路由以及如何使用路由重寫控制器。
frontend路由
要註冊前端路由,我們必須建立一個routes.xml檔案:
檔案: app/code/Mageplaza/HelloWorld/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">
<!--Use router 'standard' for frontend route-->
<router id="standard">
<!--Define a custom route with id and frontName-->
<route frontName="helloworld" id="helloworld">
<!--The module which this route match to-->
<module name="Mageplaza_HelloWorld"/>
</route>
</router>
</config>
請檢視程式碼,您將看到註冊路由非常簡單。您必須使用標準路由器作為前端。此路由將有一個子節點,為其定義模組和2個屬性:
- id屬性是一個唯一的字串,用於標識此路由。您將使用此字串宣告此模組操作的佈局控制代碼
- frontName屬性也是一個唯一的字串,它將顯示在url請求中。例如,如果您宣告這樣的路線:
<route frontName="helloworld" id="helloworld">
該模組的URL應該是:
此操作的佈局控制代碼是:helloworld_controller_action.xml
因此,使用此示例路徑,您必須在此資料夾中建立操作類:{namespace}/{module}/Controller/{Controller}/{Action}.php
adminhtml 路由
此路由與前端路由相同,但您必須在adminhtml資料夾中將其宣告為路由器ID為admin
。
檔案: app/code/Mageplaza/HelloWorld/etc/adminhtml/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">
<!--Use router 'admin' for admin route -->
<router id="admin">
<!--Define a custom route with id and frontName -->
<route id="mageplaza_helloworld" frontName="mageplaza_helloworld">
<!--The module which this route match to-->
<module name="Mageplaza_HelloWorld"/>
</route>
</router>
</config>
管理頁面的url與前端頁面的結構相同,但是admin_area
之前會新增名稱route_frontName
以識別這是一個管理路由器。例如,admin cms頁面的url:
管理頁面的控制器操作將新增到資料夾內Controller/Adminhtml
。例如,對於以上網址:
{namespace}/{module}/Controller/Adminhtml/{Controller}/{Action}.php
使用route重寫控制器
在這條路徑中,我們將看到如何用路由器重寫控制器。如上面的路徑,您可以看到每個路由都有一個id屬性來識別。那麼如果我們定義具有相同id屬性的2路由會發生什麼?
答案是控制器操作將在兩個模組中找到。Magento系統在配置模組排序順序之前/之後提供屬性,該順序定義了首先找到的模組控制器。這是控制器重寫的邏輯。
例如,如果我們想重寫控制器customer / account / login,我們將在route.xml中定義更多路由,如下所示:
檔案: app/code/Mageplaza/HelloWorld/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">
<!--Use router 'standard' for frontend route-->
<router id="standard">
<!--Define a custom route with id and frontName-->
<route frontName="helloworld" id="helloworld">
<!--The module which this route match to-->
<module name="Mageplaza_HelloWorld"/>
</route>
<route id="customer">
<module name="Mageplaza_HelloWorld" before="Magento_Customer" />
</route>
</router>
</config>
和控制器檔案: app/code/Mageplaza/HelloWorld/Controller/Account/Login.php
所以frontController首先在我們的模組中找到Login動作,如果找到它,它將執行並且不會執行Magento_Customer的Login動作。我們成功地重寫了一個控制器。
您也可以使用它來使第二個模組與另一個模組具有相同的路由器。例如,通過上述宣告,您可以使用路由'customer'作為控制器操作。如果您有控制器'部落格'和操作'Index.php',您可以使用此網址: