AMPでEC-CUBEがさらに便利に快適に!

第2回実践!EC-CUBEのAMP HTML化その1:商品詳細ページ]

EC-CUBEのAMP HTML化

このたびEC-CUB 4 AMPプラグインリリースの際、技術協力として設計~実装までを担当した、株式会社サンデイシステムズのフロントエンドエンジニア永沼と申します。どうぞよろしくお願いいたします。EC-CUBE 4のAMP HTML化の技術的な詳細を、これから3回に分けてご紹介してまいります。最後までお付き合いいただければ幸いです。

では、技術パート第1回目となる本稿ではEC-CUBEの商品詳細ページでの実装をメインに説明します。

EC-CUBE 4の商品詳細ページでのユーザインタラクション

EC-CUBE 4をAMP HTML化するにあたり、ユーザインタラクションと連動した商品情報の取り扱いは、とても重要なポイントとなります。

たとえば、EC-CUBE 4デフォルトの商品詳細ページでは、⁠サイズ」⁠カラー」などの商品規格がセレクトボックスとして実装されており、これらの操作を通じて以下のようなインタラクションが発生します。

  • 商品金額を変更
  • 商品コードを変更
  • セレクトボックスのoption要素の値を変更
  • 在庫有無の判定
  • フォーム送信時の値の変更
    •  商品詳細ページ
      図 商品詳細ページ

      EC-CUBE 4のデフォルトではインタラクションの制御をJavaScriptが担っていますが、AMP HTMLでは任意のJavaScriptの利用が大きく制限されているため、この動的な機能はAMP HTML ライブラリで提供される各コンポーネントを利用して実装することになります。

      セレクトボックスのユーザインタラクションに必要なAMPコンポーネント

      セレクトボックスを操作し、その操作に応じた動的な機能を実現するには、以下のAMPコンポーネントが必要になります。

      • amp-list
      • amp-mustache
      • amp-bind

      大まかな流れとしては、amp-listでバックエンド側で生成されたJSONファイルを取得、amp-mustacheで取得したJSONファイル内のデータをamp-list内にレンダリングします。その後、amp-bindでセレクトボックスの操作に応じた動的な機能を実現するというものになります。

      EC-CUBE 4への実装

      実装する際、まずは必要なAMPコンポーネントをheadタグ内に読み込みます。

      <script async src="https://cdn.ampproject.org/v0.js">
      <script async custom-element="amp-list" src="https://cdn.ampproject.org/v0/amp-list-0.1.js">
      <script async custom-template="amp-mustache" src="https://cdn.ampproject.org/v0/amp-mustache-0.2.js">
      <script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js">

      そして以下がAMPコンポーネントを組み込んだEC-CUBE 4の商品詳細ページのソースコードになります。

      実際はこのコードに加えて、EC-CUBE 4で採用してるPHPのテンプレートエンジンTwigのタグが組み込まれますが、今回はAMP HTMLの見通しを良くするために省略しています。

      AMP HTMLが組み込まれた詳細なTwigのテンプレートを確認したい場合は、プラグインを実際にインストールすることをおすすめします。

      <amp-list class="ec-selectList" layout="flex-item" src="https://◯◯◯.com/classCategories.json">
        <template type="amp-mustache">
          {{#classcategory_1.0}}
            {{^classcategory_1.0.classcategory_2}}
              <div class="ec-select">
                <select id="classcategory_id1" name="classcategory_id1" class="form-control" on="change: AMP.setState({selectResult: classCategories.items[0].classcategory_1.filter(elm => elm.id == event.value)[0]})">
                  <option value="__unselected">選択してください
                    {{#classcategory_1}}
                      <option value="{{id}}">{{name}}
                    {{/classcategory_1}}
                </select>
              </div>
            {{/classcategory_1.0.classcategory_2}}
            {{#classcategory_1.0.classcategory_2.0}}
              <div class="ec-select">
                <select id="classcategory_id1" name="classcategory_id1" class="form-control" on="change: AMP.setState({selectOption: classCategories.items[0].classcategory_1.filter(elm => elm.id == event.value)[0], selectResult: ''})">
                  <option value="__unselected">選択してください
                  {{#classcategory_1}}
                    <option value="{{id}}">{{name}}
                  {{/classcategory_1}}
                </select>
              </div>
            {{/classcategory_1.0.classcategory_2.0}}
          {{/classcategory_1.0}}
        </template>
      </amp-list>
      <amp-list class="ec-selectList" layout="flex-item" [src]="selectOption || 'https://◯◯◯.com/classCategories.json'" src="./classCategories.json">
        <template type="amp-mustache">
          {{^classcategory_2}}
            {{#classcategory_1.0.classcategory_2.0}}
              <div class="ec-select">
                <select id="classcategory_id2" name="classcategory_id2" class="form-control">
                  <option value="__unselected">選択してください
                </select>
              </div>
            {{/classcategory_1.0.classcategory_2.0}}
          {{/classcategory_2}}
          {{#classcategory_2.0}}
            <div class="ec-select">
              <select id="classcategory_id2" name="classcategory_id2" class="form-control" on="change: AMP.setState({selectResult: selectOption.classcategory_2.filter(elm => elm.id == event.value)[0]})">
                <option value="__unselected">選択してください
                {{#classcategory_2}}
                  <option value="{{id}}">{{name}}
                {{/classcategory_2}}
              </select>
            </div>
          {{/classcategory_2.0}}
        </template>
      </amp-list>

      後述しますが、今回はamp-bindコンポーネントに含まれるamp-stateコンポーネントを使い、ユーザのアクションに際して条件に従ってデータを絞り込む作業を行うため、下記のコードも記述しておきます。

      <amp-state id="classCategories" src="https://◯◯◯.com/classCategories.json">

      ここまでで、ひとまず準備は整いました。

      上記のセットアップが完了したページを読み込むと、まずは用意した2つのamp-listから、バックエンド側で作成したclassCategories.jsonのデータを参照します。読み込んだJSONデータはmustacheテンプレートで処理され、データの内容によって分岐処理を行って描画内容を変更しています。

      EC-CUBE 4は「規格が存在しない場合」⁠規格1がある場合」⁠規格1と2がある場合」といった具合に、商品によって3パターンのセレクトボックスの出し分けが必要になるので、amp-list、amp-mustacheといったAMPコンポーネントを用いて、商品情報に応じた情報内容の取得を行う必要があります。

      今回はここまでとし、次回はこの続きと本プラグインの概要機能まで解説します。次回もぜひご覧ください。

おすすめ記事

記事・ニュース一覧