Shopify Liquidで商品情報を取得する方法
Shopifyでストアを運営していると、例えば特集ページなどに商品情報を掲載したいことがありますよね。このとき、商品名や価格などを静的に記述すると商品情報が更新された場合に齟齬が生じてしまうので、動的に商品情報を取得したいところです。
all_productsを使う
最も簡単なのはall_productsオブジェクトを使う方法です。
{{ all_products['potion'].title }}
のように商品のhandleを指定して商品情報を取得することができます。
単一プロパティ(商品名など)だけ取得したい場合はこれでOKですが、たいてい1つの商品につき価格や商品画像など複数のプロパティにアクセスしたいと思うので、
{% assign product = all_products['potion'] %}
<div class="item">
<h3>{{ product.title }}</h3>
<p>価格:{{ product.price | money }}</p>
</div>
のように適当な変数に代入して使うと便利です。
ただし注意点として、all_productsで取得できるのは1ページ内で20商品までです。20商品を超えた分のリクエストは無視されます。
1つのliquidファイル内で20商品以内ではなく、1ページで20商品以内なので、ヘッダーやサイドバーなど他の場所でもall_productsで商品情報を取得しようとしている場合は要注意です。
コレクションを使う
1つのページで21商品以上の商品情報を取得する必要がある場合は、コレクションを使います。
まず、あらかじめ情報を取得したい商品を集めたコレクション(例えば「blackfriday」)を作ります。コレクションの商品は、
{% assign products = collections['blackfriday'].products %}
のようにして取得できるので、これを使って用途に応じてコードを書きます。
forループで出力
コレクションに集めた商品を全て一気にループで出力したい場合は、下記のようにします。
{% for product in collections['blackfriday'].products %}
<div class="item">
<h3>{{ product.title }}</h3>
<p>価格:{{ product.price | money }}</p>
</div>
{% endfor %}
ただし、forループも50商品までしかループさせることができません。Shopifyは制約だらけです。
paginate + forループで出力
50商品以上をループさせたい場合は、paginateを組み合わせます。
{% paginate collections['blackfriday'].products by 250 %}
{% for product in collections['blackfriday'].products %}
<div class="item">
<h3>{{ product.title }}</h3>
<p>価格:{{ product.price | money }}</p>
</div>
{% endfor %}
{% endpaginate %}
paginateは主にコレクションページやブログページでページネーションを実装するときに使うタグ。paginateは配列を複数のチャンクに分割して処理します。forループの50商品制限は1回の反復処理での制限なので、paginateで分割された各チャンク内でforループが動作することで、全体としては50商品を超える商品を扱うことができます。
ちなみに、paginateで指定できる値は公式ドキュメントでは1から250の間で設定できることになっていますが、なぜか1000などを設定しても動作するようです。いつ動作しなくなるかわからないので、個人的には250以内に抑えておくのが無難だと思います。
補足:全商品一覧コレクションを使う
あらかじめ全商品一覧コレクション「all」を作成しているという前提で、全商品一覧から商品情報を取得する方法もあります。
{% paginate collections.all.products by 250 %}
{% for product in collections.all.products %}
{% if product.handle == 'potion' %}
<div class="item">
<h3>{{ product.title }}</h3>
<p>価格:{{ product.price | money }}</p>
</div>
{% endif %}
{% if product.handle == 'supplement' %}
<div class="item">
<h3>{{ product.title }}</h3>
<p>価格:{{ product.price | money }}</p>
</div>
{% endif %}
...
{% endfor %}
{% endpaginate %}
一度全商品一覧を作っておけば、いちいちコレクションを新規作成する必要がないので簡単ですが、商品数が多いストアでは対応できません。適宜使い分けるのがよいと思います。
Discussion