Magento 2 ルーティング

routing magento2

routing magento2

この記事では、Magento 2 の Routing の重要な部分について説明します。ルートはモジュールの名前を定義するもので、モジュールを検索してコントローラのアクションを実行するためのURLに使用することができます。

1. Magento 2のリクエストフロー

Magento 2では、reques urlは以下のようになります。

http://example.com/index.php/front_name/controller/action

このURLの中には、モジュールを見つけるために使用される「front_name」があります。ルーターはこの名前を routes.xml で定義することで、モジュールごとに定義しています(詳細は後述)。

Magento 2 でリクエストを行うと、controller/action: index.phpを見つけるために次のような流れになります:index.php → HTTP アプリ → FrontController → Routing → Controller Processing → etc

FrontControllerはHttpクラスで呼び出され、コントローラとアクションが一致するリクエストをルーティングします。

ファイル: 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() メソッドを見ればわかるように、ルーターリストはループして、このリクエストにマッチするものを探します。このリクエストに対応するコントローラのアクションが見つかれば、そのアクションが呼び出されて実行されます。

2. フロントエンド/adminでカスタムルートを作成

本編では、シンプルなモジュールSmartosc_HelloWorldを使用します。

フロントエンドのルート

Routes.xml

フロントエンドのルートを登録するには、routes.xmlファイルを作成する必要があります。

ファイル:app/code/Smartosc/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="Smartosc_HelloWorld"/>
        </route>
    </router>
</config>

コードを見てみてください。ルートを登録するのはとても簡単なことだとわかります。フロントエンドには標準的なルーターを使用する必要があります。このルートは、モジュールを定義する子と、2つの属性を持ちます:

  • id属性は、このルートを識別するためのユニークな文字列です。この文字列を使って、このモジュールのアクションのレイアウトハンドルを宣言します。
  • frontName属性は、URLリクエストに表示される一意の文字列です。例えば、次のようなルートを宣言したとします:
 <route frontName="helloworld" id="helloworld">

このモジュールのURLは次のようになります:

http://example.com/index.php/helloworld/controller/action

そして、このアクションのレイアウトハンドルは、helloworld_controller_action.xml ですので、この例のパスでは、このフォルダにアクションクラスを作成する必要があります。{namespace}/{module}/Controller/{Controller}/{Action}.php

管理ルート

このルートはフロントエンドのルートと同じになりますが、adminhtmlフォルダでルータIDをadminにして宣言しなければなりません。

ファイル:app/code/Smartosc/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="Smartosc_helloworld" frontName="Smartosc_helloworld">
            <!--The module which this route match to-->
            <module name="Smartosc_HelloWorld"/>
        </route>
    </router>
</config>

管理ページのURLは、フロントエンドページと同じ構造ですが、admin_areaの名前がroute_frontNameの前に追加され、これが管理ルーターであることを認識します。例えば、admin cmsページのURLです:

http://example.com/index.php/admin/Smartosc_helloworld/controller/action

管理画面用のコントローラアクションは、Controller/Adminhtmlフォルダの中に追加されます。例えば、上記のURLの場合、以下のようになります。

{namespace}/{module}/Controller/Adminhtml/{Controller}/{Action}.php

ルートを使ってコントローラを書き換える

このパスでは、ルータを使ってコントローラを書き換える方法を見ていきます。上のパスのように、各ルートは識別のためのid属性を持っていることがわかります。では、もし同じid属性を持つ2つのルートを定義したらどうなるでしょうか?

答えは、コントローラのアクションが両方のモジュールに存在することになります。Magento システムはモジュールのソート順を設定するために before/after 属性を提供し、どのモジュールのコントローラが最初に見つかるかを定義します。これがコントローラの書き換えのためのロジックです。

例えば、コントローラ customer/account/login を書き換えたい場合は、以下のように route.xml でルートを定義します。

ファイル: app/code/Smartosc/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="Smartosc_HelloWorld"/>
        </route>
       <route id="customer">
           <module name="Smartosc_HelloWorld" before="Magento_Customer" />
       </route>
   </router>
</config>

コントローラーファイル: app/code/Smartosc/HelloWorld/Controller/Account/Login.php

つまり、frontControllerはまずモジュールのLoginアクションを見つけ、見つかればそれを実行し、Magento_CustomerのLoginアクションは実行しないということになります。これでコントローラの書き換えに成功しました。

この方法は、他のモジュールと同じルータを持つ第2のモジュールを作るのにも使えます。例えば、上記の宣言では、コントローラのアクションにルート ‘customer’ を使うことができます。もし、コントローラ「Blog」とアクション「Index.php」があれば、このURLを使うことができます。

http://example.com/customer/blog/index

 

デモを申し込む

弊社の専門家は最適なソリューションをサポートさせて頂きます。

►►►サービスについて