【EC-CUBE 4】公開状態に応じて商品を非表示にする方法

EC-CUBE 4で商品一覧ページやブロックを自作すると、公開ステータスが「非公開」「廃止」の商品まで表示されてしまいます。これを直す方法を2つ紹介します。どちらも数行の追記で済みます。

自作した一覧ページで非公開の商品を隠すには?

Twig側で絞り込むか、Controller側で絞り込むかの2通りあります。どちらか一方で構いません。

{% if Product.status.id == 1 %}
   ~~商品情報~~
{% endif %}
$products = $this->productRepository->findBy(
  ['Status' => 1],
  ['id' => 'DESC']
);

公開ステータスの「公開」は 1 です。Controller側で絞り込むほうが、無駄なデータを取り出さずに済みます。

これまで本サイトでは、条件に合った商品だけを表示するページやブロックの作り方を紹介してきました。

ところがこれらのコードのままだと、商品の公開状態(公開・非公開・廃止)に関係なく、すべての商品が表示されてしまいます。

EC-CUBEの管理画面で、商品サンプル_4の公開ステータスを非公開に設定している画面

商品管理で「サンプル_4」を非公開にしているのに……

自作した新着商品一覧ページに、非公開にしたはずのサンプル_4が表示されている画面

自作ページを開くと、そのまま表示されてしまう

デフォルトで用意されている商品一覧ページは、非公開・廃止の商品が自動で非表示になります。修正が必要なのは自作したページ・ブロックだけです。

【動作環境】EC-CUBEのバージョン:4.3.0 / サーバー:XServer

目次

非公開や廃止でも表示されてしまう理由

理由は単純で、自作したページに「公開状態を見て表示を切り替える」処理を入れていないからです。デフォルトの一覧ページには入っていますが、自分で作ったものには当然入っていません。

つまり、次のどちらかを足せば解決します。

  • Twigテンプレート側で、公開状態が「公開」のときだけ表示する if を書く
  • Controller側で、商品を取り出すときの検索条件に「公開のもの」を足す

公開ステータスは3種類ある

商品の公開状態は、データベースの mtb_product_status というマスタに入っています。

EC-CUBEのデータベースmtb_product_statusの中身。公開・非公開・廃止の3行が並んでいる

mtb_product_status の中身(初期状態)

名称フロント画面での扱い
1公開表示される
2非公開表示されない
3廃止表示されない

今回はこのうち 「公開」=1 だけを通せばよい、ということになります。

「廃止」は削除の代わりです。商品情報は受注情報などに紐づいているため、消してしまうと過去の注文が壊れます。そのため物理的には消さず、廃止という状態にして表から見えなくする作りになっています。

EC-CUBE本体では、この3つの値に ProductStatus::DISPLAY_SHOW(1)・DISPLAY_HIDE(2)・DISPLAY_ABOLISHED(3)という名前が付けられています。Controller側で書く場合は、数字の 1 よりこの定数を使うほうが意図が伝わります。

【方法1】Twigテンプレートに if 文を足す

自動更新される新着商品一覧ページ のTwigテンプレートを例に修正します。

Controllerから渡された商品情報は Product に入っており、公開状態は Product.status で、その値は Product.status.id で取り出せます。したがって次のように囲めば、公開の商品だけが表示されます。

{% if Product.status.id == 1 %}
   ~~商品情報~~
{% endif %}

実際に、新着商品一覧のTwigテンプレート全体へ適用すると次のようになります。

{% extends 'default_frame.twig' %}

{% block main %}
    <h1>新着商品ページ</h1>
    <div class="ec-shelfRole">
      <ul class="ec-shelfGrid">
          {% for Product in Products %}
              {# 公開状態が「公開」の場合のみ商品を表示 #}
              {% if Product.status.id == 1 %}
                <li class="ec-shelfGrid__item">
                  <a href="{{ url('product_detail', {'id': Product.id}) }}">
                    <p class="ec-shelfGrid__item-image">
                        <img src="{{ asset(Product.main_list_image|no_image_product, 'save_image') }}" alt="{{ Product.name }}">
                    </p>
                    <p>ID: {{ Product.id }}</p>
                    <p>{{ Product.name }}</p>
                    <p class="price02-default">
                        {% if Product.hasProductClass %}
                            {% if Product.getPrice02Min == Product.getPrice02Max %}
                                {{ Product.getPrice02IncTaxMin|price }}
                            {% else %}
                                {{ Product.getPrice02IncTaxMin|price }} ~ {{ Product.getPrice02IncTaxMax|price }}
                            {% endif %}
                        {% else %}
                            {{ Product.getPrice02IncTaxMin|price }}
                        {% endif %}
                    </p>
                  </a>
                </li>
              {% endif %}
          {% endfor %}
      </ul>
    </div>
{% endblock %}

先ほどと同じように「サンプル_4」を非公開にしてページを開くと、今度はきちんと消えています。

if文を追加した新着商品一覧ページ。非公開にしたサンプル_4が表示されなくなっている

非公開にした「サンプル_4」が一覧から消えた

{% if %}{% for %} の書き方は Twig まとめ(2) にまとめています。

【方法2】findBy に条件を足す

そもそもController側で商品を取り出すときに、公開の商品だけを取ってくるという手もあります。商品を検索する部分を次のように書き換えてください。

$products = $this->productRepository->findBy(
  ['Status' => 1],
  ['id' => 'DESC']
);

findBy() の第1引数には絞り込み条件を配列で渡せるので、そこへ ['Status' => 1] を加えました。第2引数はこれまでどおり並び順の指定です。

この方法なら公開状態が「公開」の商品だけがTwigへ渡るため、Twig側は一切変更しなくて構いません。

findBy() をはじめとするRepositoryのメソッドについては リポジトリでよく使われるメソッド解説 にまとめています。

どちらを使えばいい?

方法1(Twigのif)方法2(findByの条件)
直す場所TwigテンプレートController
データベースから取る件数全件(表示時に間引く)公開の商品のみ
表示件数を絞っているとき件数が合わなくなる正しく揃う
向いている場面Controllerを触りたくないとき基本はこちら

「3件だけ表示」のように件数を絞っている場合は方法2を選んでください。方法1は取り出したあとに間引くため、取ってきた3件のうち2件が非公開だと1件しか並ばないということが起きます。

まとめ

商品の公開ステータスに応じて表示を切り替える方法を2つ紹介しました。

  • 自作した一覧ページ・ブロックは、公開状態を見ていないため非公開の商品まで出てしまう
  • 公開ステータスは 1=公開 / 2=非公開 / 3=廃止 の3種類
  • Twig側なら {% if Product.status.id == 1 %} で囲む
  • Controller側なら findBy() の条件に ['Status' => 1] を足す
  • 表示件数を絞っているならController側で対応する

商品が廃盤になったり、一時的に非公開にしたい場面はよくあります。応用すれば、商品ページに「完売」「SOLD OUT」と出すといったこともできます。ぜひ試してみてください。

EC-CUBEのカスタマイズに関する記事

この記事に出てきた用語

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次