【Shopify】全Basicsをまとめてみた話

#はじめに
この記事は、LiquidのBasicsを全てまとめた記事になります。

ShopifyのLiquidを編集するのに必要な基礎知識なので、しっかり抑えておきましょう。

#Basics
Basicsは、ハンドルや、演算子などのLiquidの基礎をまとめたものです。

それぞれについて見てきましょう！

##Handles
`Object handles`の概要について[ドキュメント](https://shopify-dev.shopifycloud.com/docs/themes/liquid/reference/basics/handle)からの引用です。

ハンドル（handle）はLiquidオブジェクトにアクセスするために使用されます。

+ 商品（product）
+ コレクション（collections） 
+ ブログ（blogs）
+ ブログ記事（articles）
+ メニュー（menus）

に対して、ハンドルが存在します。

例えば、「About Us」というタイトルのページには、「about-us」というハンドルを使用することでLiquidでアクセスすることが可能です。

```.liquid
<!-- the content of the About Us page -->
{{ pages.about-us.content }}
```
デフォルトでは、ハンドルはオブジェクトのタイトル（商品名やページタイトルなど）を小文字で表したもので、スペースや特殊文字はハイフン（-）で置き換えられます。

タイトルが`Shirt`の商品を作成すると、自動的に`shirt`というハンドルが与えられます。

![ScreenClip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665523/cfd674bb-5dd8-7993-4175-ba71d0fad550.png)

すでに`shirt`というハンドルが使用されていた場合、ハンドルは自動的に違うハンドルに変更されます。

例えば、`Shirt`という商品が複数あった、二枚目と三枚目は「shirt-1」や「shirt-2」などのようなハンドルが与えられます。

###ハンドルの作成方法
タイトルの空白は、ハンドルのハイフンは置き換えられます。

例えば、「My Shiny New Title」というタイトルの場合、ハンドルは「my-shiny-new-title」になります。

![ScreenClip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665523/1207a214-349b-29c3-4042-d49d84e60f05.png)

ハンドルは、オブジェクトのURLも決定します。

例えば、`about-us`というハンドルを持つページURLは、`http://yourshop.myshopify.com/pages/about-us`となります。

ストアは、ストアのデザインやリンク切れを避けるために静的なハンドルを持っていることがあります。

例えば、ページタイトルを「About Us」から「About Shopify」に変更しても、ハンドルは「about-us」のままです。

![ScreenClip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665523/c4172cb7-655d-2955-2ecf-173b87178990.png)

もし、変更したい場合は、**URL&ハンドルボックスの値**を変更することで、オブジェクトのハンドルを手動で変更することが可能です。

![ScreenClip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665523/9d5333ba-abe4-6308-c7f0-825e2e69fa64.png)


###ハンドル属性へのアクセス
オブジェクトを複数形にして、以下のように、`[]` か `.` を使用することで、その属性にアクセスすることが可能です。

```.liquid
{{ pages.about-us.title }}
{{ pages["about-us"].title }}
```
>About Us
About Us

この表記法で、テーマエディタのオブジェクトを渡すこともできます。

```.liquid
{% for product in collections[settings.home_featured_collection].products %}
    {{ product.title }}
{% endfor %}
```
>Awesome Shoes
Cool Shirt
Wicked Socks

##Operators
`Logical and comparison operators`の概要について[ドキュメント](https://shopify-dev.shopifycloud.com/docs/themes/liquid/reference/basics/operators)からの引用です。

Liquidの多くはの論理演算子と比較演算子にアクセスできます。

演算子を使用して、制御フロータグでロジックを作成することができます。

Operatorについてみていきましょう！

###Basic operators
主な演算子は以下の通りです。

| Operator | Function |
|:--|:--|
| ==  | イコール  |
| != |  ノットイコール |
| >  |  大なり |
|  < |  小なり |
|  >= |  大なりイコール |
|  <= |  小なりイコール |
|  or | または  |
|  and |  かつ |


例えば、`and`と`or`を用いると、タグ内で複数の比較を行うことができます。

```.liquid
{% if customer.has_account == true %}
  Welcome back to our store!
{% endif %}
```

```.liquid
{% if product.type == "Shirt" or product.type == "Shoes" %}
  This is a shirt or a shoe.
{% endif %}
```

###contains

`contains`は、文字列の中に部分文字列が存在するかどうかを判断し`Boolean`の値を返します。

```.liquid
{% if customer.email contains "shopify.com" %}
  Hey there, Shopify employee!
{% endif %}
```

また、文字列の配列の中に、文字列が含まれているかどうかを調べることもできます。

```.liquid
{% if product.tags contains "outdoor" %}
  This product is great for using outdoors!
{% endif %}
```

`contains`は文字列のみを検索することができるので、オブジェクトの配列の中にオブジェクトがあるかどうかを調べることはできません。

###Order of operations
複数の`and`、`or`演算子を持つタグでは、演算子は右から左の順にチェックされます。

括弧は、Liquidでは無効な文字なので、括弧によって操作の順序を変更することはできません。


```.liquid
{% if true or false and false %}
  This evaluates to true, since the 'and' condition is checked first.
{% endif %}
```

```.liquid
{% if true and false and false or true %}
  This evaluates to false, since the tags are checked like this:

  true and (false and (false or true))
  true and (false and true)
  true and false
  false
{% endif %}
```


##Types
`Data types`の概要について[ドキュメント](https://shopify-dev.shopifycloud.com/docs/themes/liquid/reference/basics/types)からの引用です。

Liquidオブジェクトは、以下に示す6タイプのいずれかになります。

+ String
+ Number
+ Boolean
+ Nil
+ Array
+ EmptyDrop

`assign`や`capture`タグを使って、定義したLiquid変数を初期化することができます。


###String
Stringは、変数の値をシングルクォーテーション`''`やダブルクォーテーション`""`で囲むことで定義できます。

```.liquid
{% assign my_string = "Hello World!" %}
``` 

###Number
Numberには、浮動小数点と整数が含まれます。

```.liquid
{% assign my_int = 25 %}
{% assign my_float = 39.756 %}
``` 

###Boolean
Booleanは、`true`か`false`のどちらかの値を持ちます。

宣言するときは、ダブルクォーテーションなどの引用符は必要ありません。

```.liquid
{% assign foo = true %}
{% assign bar = false %}
``` 

###Nil
Nilは、Liquidコードで結果が出なかった時に返される特別な空の値です。

`nil`という文字列ではありません。

Nilは、真偽値をチェックする`if`ブロックや他のLiquidタグの条件では`false`として扱われます。

以下の例では、トラッキング番号が存在しない場合（つまり、`fulfillment.tracking_numbers`が`nil`を返す場合）、Liquidはテキストを表示しません。

つまり、`nil`が`false`として処理されていることになります。

```.liquid
{% if fulfillment.tracking_numbers %}
  There is a tracking number.
{% endif %}
``` 

nilを返すタグや出力はページに何も表示されません。

```.liquid
Tracking number: {{ fulfillment.tracking_numbers }}
``` 
>Tracking number:


###Array

Arrayは、任意の型の変数のリストを返します。

配列内の全ての項目にアクセスするには、`for`、`tablerow`タグを使用してループさせます。

```.liquid
{% for tag in product.tags %}
  {{ tag }}
{% endfor %}
``` 
>sale summer spring wholesale

配列内の特定の項目は、`[]`にインデックス番号を指定することでアクセスできます。

配列のインデックスは、**0**から始まります。

```.liquid
<!-- if product.tags = "sale", "spring", "summer", "wholesale" -->
{{ product.tag[0] }}
{{ product.tag[1] }}
{{ product.tag[2] }}
``` 
>sale
spring
summer

Liquidだけを用いて、配列を初期化することはできません。

しかし、`split`フィルターを用いると、単一の文字列を部分文字列の配列に分割することができます。


###EmptyDrop

削除されたオブジェクト（ページやブログ記事など）にハンドルでアクセスをしようとすると、`EmptyDrop`オブジェクトが返されます。

以下の例では、`page_1`、`page_2`、`page_3`がすべてEmptyDropオブジェクトになります。

```.liquid
{% assign variable = "hello" %}
{% assign page_1 = pages[variable] %}
{% assign page_2 = pages["does-not-exist"] %}
{% assign page_3 = pages.this-handle-does-not-exist %}
```

オブジェクトの属性にアクセスする前に、オブジェクトが存在するかどうかを確認することができます。

```.liquid
{% unless pages == empty %}
  <!-- This will only print if the page with handle "about" is not empty -->
  <h1>{{ pages.frontpage.title }}</h1>
  <div>{{ pages.frontpage.content }}</div>
{% endunless %}
```

最初にオブジェクトが空か否かをチェックしないと、Liquidは空のHTML要素を記述してしまいます。

```.liquid
<h1></h1>
<div></div>
```

コレクションでも空か否かをチェックすることができます。

```.liquid
{% unless collections.frontpage == empty %}
  {% for product in collections.frontpage.products %}
    {% include "product-grid-item" %}
  {% else %}
    <p>We have a "frontpage" collection, but it's empty.</p>
  {% endfor %}
{% endunless %}
```
EmptyDropオブジェクトは、`empty?`属性だけをもち、これは常に`true`を返します。

存在しているコレクションやページには、`empty?`属性はなく、`if`文で呼び出した時、`false`が返されます。


##Truthy and falsy
`Truthiness and falsiness in Liquid`の概要について[ドキュメント](https://shopify-dev.shopifycloud.com/docs/themes/liquid/reference/basics/true-and-false)からの引用です。

Booleanでないデータ型が`if`タグのような制御フローで使用される時、Liquidはデータを`true`か`false`で評価します。

デフォルトで`true`を返すデータ型は **truty**、`false`を返すデータ型は **falsy** と呼ばれます。

###Truthy

`nil`と`false`以外の値はすべて`truthy`です。

以下の例では、"Tobi"というテキストは、boolean値ではないですが、truthyとして処理されています。

```.liquid
{% assign name = "Tobi" %}

{% if name %}
  This text will always appear if "name" is defined.
{% endif %}
```

空の文字も`true`になります。

```.liquid
{% if page.title %}
  <h1>{{ page.title }}</h1>
{% endif %}
```
>\<h1>\</h1>

これを回避するためには、以下のように文字列が空欄になっていないかどうかを確認する必要があります。

```.liquid
{% unless settings.fp_heading == blank %}
    <h1>{{ settings.fp_heading }}</h1>
{% endunless %}
```

EmptyDropもtruthyになります。

以下の例のように、`settings.page`が空の文字列だったり、非公開のオブジェクト、削除されたオブジェクトの時、
空の`<div>`が生成されてしまいます。

```.liquid
{% if pages[settings.page] %}
<div>{{ pages[settings.page].content }}</div>
{% endif %}
```
>\<div>\</div>

###Falsy
`false`となる値は、`nil`と`false`だけです。

`nil`は、Liquidオブジェクトが返すべきものを持っていない時に返されます。

例えば、コレクションがコレクションイメージを持っていない場合、`collection.image`の値に`nil`が入ります。

```.liquid
{% if collection.image %}
<!-- output collection image -->
{% endif %}
```
`false`は、`product.available`のような多くのLiquidオブジェクトのプロパティを通して返されます。

##Whitespace control
`Whitespace control`の概要について[ドキュメント](https://shopify-dev.shopifycloud.com/docs/themes/liquid/reference/basics/whitespace)からの引用です。

Liquidでは、タグ構文`{{-`、`-}}`、`{%-`、`-%}`にハイフンを含めることで、レンダリングされたタグの左側または右側からホワイトスペースを取り除く事ができます。

通常、テキストを出力しない場合でも、テンプレート内のLiquidではレンダリングされたHTMLに空行が出力されます。

以下の例では、`{% if customer %}`分の空行が挿入されています。

```.liquid
Order history:

{% if customer %}
Welcome back, {{ customer.first_name }}
{% endif %}
```
>Order history:<br><br>
Welcome back, Martina

Liquidタグにハイフンを含めることで、レンダリングされたテンプレートから生成されたホワイトスペースを取り除く事ができます。

```.liquid
Order history:

{%- if customer -%}
Welcome back, {{ customer.first_name }}
{%- endif -%}
```
>Order history:<br>
Welcome back, Martina

Liquidタグの片方だけのホワイトスペースを制御する必要がある場合は、開始タグまたは終了タグだけにハイフンを含めます。

そうすると、ハイフンをつけた方だけホワイトスペースが削除されます。

```.liquid
Hello, {{ customer.name -}}  !
```
>Hello, Martina!

#終わりに
今回の記事はここまでになります。

お疲れさまでした。

# Shopify アプリのご紹介

Shopify アプリである、「商品ページ発売予告アプリ | リテリア Coming Soon」は、商品ページを買えない状態のまま、発売日時の予告をすることができるアプリです。Shopify で Coming Soon 機能を実現することができます。

https://coming-soon.reterior.jp/

https://apps.shopify.com/shopify-application-314?locale=ja&surface_detail=%E3%83%AA%E3%83%86%E3%83%AA%E3%82%A2&surface_inter_position=1&surface_intra_position=1&surface_type=search