HowTo

Magento 2のサイトURLを国や言語ごとにカスタマイズ!(サブフォルダ編)

Magento 2のURLにサブフォルダ、マルチストア構成

前編に続いて、URLにサブフォルダを用いたMagentoでの複数のウェブサイト・ストアを設定する方法をご紹介いたします。

このようなURL: http://domain.tld/countryname/

このやり方は前編で紹介した方法と比べたら、たいへんハードルが高い内容となりますが、一部のビジネスモデル、特に越境ECにおいて、どうしてもこの手段で実現したいという要望もあるかと思います。

以下で典型的な理由の例を挙げます。

  • 現時点で運営しているECサイトはもともとサブドメインを利用中
  • ドメインを自由に取得・追加できない
  • サブドメインは他部署や支社にのみ割り当てられている
  • SSL証明書が1ドメインしか発行できない

などなどMagentoでのサブフォルダ構造のURLでストアを構築する需要はかなりあります。

今回の目標は架空のmaruweb.comをベースドメインとして、Magentoを以下のように、3つの国に使い分けます。サブフォルダ名は国名としましょう。

日本(デフォルト):maruweb.com/japan/…
中国:maruweb.com/china/…
アメリカ:maruweb.com/unitedstates/…

実現方法複数存在・・・。しかも、どれもおすすめできません!

さて、どうすればいいかと思って、検索してみたら、インターネットに出回っているやり方はだいたい2種類存在します。

1.管理画面で、店舗→設定→ウェブ→URLオプションに進んで、「店舗コードをURLに追加」を「はい」にします。

店舗コードをURLに追加
店舗コード実はStore View Code

一見この方法は簡単そうで、すぐにでもできますが、デメリットというか、致命的な問題点があります。まずここMagento自体の説明に問題があって、「店舗コードをURLに追加(元の英語: Add Store Code to URLs、日本語翻訳は問題ない)」の「店舗コード」実際はStore View Codeです。

ここまでの内容で理解できている人は、たぶんMagento利用経験者だと思いますが、Store Viewスコープの制限があるので1つのウェブサイトでしか運用できません。。。

例えば、日本国内向けサイトで、言語・通貨は1種類しか選べません。サイトで日本語と英語の切り替えは無理です。

さらに、もう1つのデメリットとしては、サブフォルダ名はStore View Codeと紐付けられてしまいます。

2.実際のファイルシステム上、本当にサブフォルダを作ります。

Magentoのルートディレクトリに/china、/unitedstatesのフォルダを作成して、Magentoルートディレクトリのindex.phpと.htaccessをそれぞれ作成したフォルダにコピペします。次に、サブフォルダにあるindex.phpに以下の箇所を編集します。

require realpath(__DIR__) . '/../app/bootstrap.php';
$params = $_SERVER;
$params[\Magento\Store\Model\StoreManager::PARAM_RUN_CODE] = '<countryname>'; //ここは管理画面で設定したウェブサイトのコードです
$params[\Magento\Store\Model\StoreManager::PARAM_RUN_TYPE] = 'website';

 

その場しのぎで実現はできましたが、Magentoのファイルの構造を変えてしまったので、アップグレードやパッチ適応に不向きです。

たくさんのトライ&エラーで、ついに・・・

上記のやり方はどれもデメリットが大きくて、運用には躊躇しますね。
本当にいい方法はないかと思っていますが、ではMagento自体はどのようにウェブサイト・ストアを判断しているのかから考えましょう。

公式ドキュメントを参考すると、Magentoは$_SERVER[‘MAGE_RUN_TYPE’]と$_SERVER[‘MAGE_RUN_CODE’]で実行するウェブサイトを決めます。
最初はApacheのSetEnvIfやRewriteRuleでなんとか行けると思っています。しかし.htaccessにこのRewrite Ruleがあります。

RewriteRule .* index.php [L]

つまり、すべてをindex.phpにリライトします。Magentoは$_SERVER[‘REQUEST_URI’]で動くんですね。

これじゃApacheレベルの設定だけではどうしようもないんです。
やはりindex.phpを変えなければならないのでしょうか?

[解決]ひらめきました!

実はphp自体に開発者がよく利用するauto prepend file機能があります。.htaccessでも、一行加えたら、この便利な機能が使えるようになります。
では、さっそく実戦していきましょう。

Magentoルートディレクトリの.htaccessの最初のところに

php_value auto_prepend_file “absolute/path/to/MaruwebURLRouter.php”

を入れます。(アップグレード後はこの一行を入れ直してください)

MagentoのルートディレクトリにMaruwebURLRouter.phpを作成します。

MaruwebURLRouter.php

<?php
  switch(true){
    case preg_match('/^\/japan($|\/.*$)/', 
        $_SERVER['REQUEST_URI'], 
        $maruwebURLRouter_matches):
      $_SERVER['MAGE_RUN_TYPE']='website';
      $_SERVER['MAGE_RUN_CODE']='JP';
      $_SERVER['REQUEST_URI']=$maruwebURLRouter_matches[1];
      break;
    case preg_match('/^\/china($|\/.*$)/', 
        $_SERVER['REQUEST_URI'], 
        $maruwebURLRouter_matches):
      $_SERVER['MAGE_RUN_TYPE']='website';
      $_SERVER['MAGE_RUN_CODE']='JP';
      $_SERVER['REQUEST_URI']=$maruwebURLRouter_matches[1];
      break;
    case preg_match('/^\/unitedstates($|\/.*$)/', 
        $_SERVER['REQUEST_URI'], 
        $maruwebURLRouter_matches):
      $_SERVER['MAGE_RUN_TYPE']='website';
      $_SERVER['MAGE_RUN_CODE']='US';
      $_SERVER['REQUEST_URI']=$maruwebURLRouter_matches[1];
      break;
  }

ここで$_SERVER[‘REQUEST_URI’]でウェブサイト・ストアを判断した後、/<countryname>を削除します。

ウェブサイトコード
<countryname>は前編にも言及されたウェブサイトのコードです

URLをたたくと、動きます。
ただし、管理画面を開くと、残念ながら動きません。

原因は…
管理画面のAdmin Keyを除外していませんでした。

対応した内容が以下になります。
ついでに、http://maruweb.com/awesome-productのようなcountrynameがない既存のものをデフォルトのウェブサイト・ストアhttp://maruweb.com/japan/awesome-productにリダイレクトさせます。

MaruwebURLRouter.php

<?php
  $maruwebAdminKey='maruwebadmin';
  switch(true){
    case preg_match('/^\/' . $maruwebAdminKey . '($|\/.*$)/', 
        $_SERVER['REQUEST_URI']):
      break;
    case preg_match('/^\/japan($|\/.*$)/', 
        $_SERVER['REQUEST_URI'], 
        $maruwebURLRouter_matches):
      $_SERVER['MAGE_RUN_TYPE']='website';
      $_SERVER['MAGE_RUN_CODE']='JP';
      $_SERVER['REQUEST_URI']=$maruwebURLRouter_matches[1];
      break;
    case preg_match('/^\/china($|\/.*$)/', 
        $_SERVER['REQUEST_URI'], 
        $maruwebURLRouter_matches):
      $_SERVER['MAGE_RUN_TYPE']='website';
      $_SERVER['MAGE_RUN_CODE']='JP';
      $_SERVER['REQUEST_URI']=$maruwebURLRouter_matches[1];
      break;
    case preg_match('/^\/unitedstates($|\/.*$)/', 
        $_SERVER['REQUEST_URI'], 
        $maruwebURLRouter_matches):
      $_SERVER['MAGE_RUN_TYPE']='website';
      $_SERVER['MAGE_RUN_CODE']='US';
      $_SERVER['REQUEST_URI']=$maruwebURLRouter_matches[1];
      break;
    default:
      header('Location: '.'/japan'.$_SERVER['REQUEST_URI'], 
	    true, 301);
      exit;
      break;
  }

検証したら、すべてのリンクに<countryname>は入っていません。

店舗→設定→ウェブ→スコープ変更→ベースURLs(HTTPSならベースURL(セキュア)も)で、「リンクベースURL」に画像のように<countryname>を入れるのも忘れないようにしてください。

リンクベースURL
ウェブページに貼るリンクの生成用

以上でオッケーです。

ほかにもいろんな方法を考えてみましたが、全体的にはやはりこれがベストだなと思っています。

越境ECにこの需要が高い使い方はなぜか公式にサポートを受けていないようです。
実装する前に、必ず注意事項も合わせて考慮してください。

おまけ: Nginx設定のヒント

nginx.conf

server {
  ...省略...
  server_name maruweb.com
  location <@your_handler> {
    ...省略...
    fastcgi_param PHP_VALUE "auto_prepend_file=/absolute/path/to/MaruwebURLRouter.php";
    ...省略...
  }
  ...省略...
}

弊社ではMagento2を利用した多機能ECサイトの構築・越境EC/中国越境ECの開発をして企業様をサポートしています。 ご興味ある方は是非問い合わせください。

ABOUT ME
ジェームス
オーストラリアでプログラミングを勉強しました。ずっとMagento 1の開発をやっていましたが、今年からようやくMagento 2を扱うことになりました。

※注意

本ブログの投稿内容に関するお問い合わせをして頂いてもご返信できませんので、何卒ご了承ください。