shopify開発でliquid分野まで手を伸ばし始めると、ゆくゆくは避けて通れないのがschemaと言う謎のコードをいじる必要が出てくることです。
結構難しいのですが、のちのちsectionを自由自在に自作したくなった時には避けて通れない道になってくるので、難しいところだけど、意外と序盤で概念だけでも知っておくといいかと思います。
これ読んでおくだけで、liquidのコード読む時の理解度が相当上がると思います!
そもそもschemaって何?
google先生によると「schema スキーマ」・・・いやそうじゃねーんだよ。意味知りたいんだよ。先生もたまには適当なこと言うんだな。なのでほかの英語辞書で引いてみたら「図式,図表」ですって。スッキリしたわ。
そう図式って意味を調べると確かに当てはまる感じがします。
端的に言えば「sectionで指定したいことをjson形式で図式にしている」のが「schema」ってイメージですね。
字面だけ読んでも、ほぼ意味わからんですよね。なのでその辺りを解説していきましょう。
ちなみにsectionはテンプレートから見た2階層目。「template」→「section」→「snippet」と3階層あるので、まずはそこもチェックしましょう!
この記事辺りに書いてあります。
んでももって重要なのが、schemaを定義する事で出来ることですね。
これはカスタマイズ画面からの操作です!
この左側の赤丸で囲った、ここから操作できる奴を自作するってことですね!出来たら便利そうでしょ?だって自由に操作できるようになるんだよ?!
schemaには階層がある
まずこのjson形式で書かれることになるschemaには「階層」があると言う事を知っておきましょう。これは先にちょっと説明してる、テンプレートの階層とは違くて、section内にさらに階層がある感じです。
★まずは一番浅い階層。ここはsectionに対する名前とか、その下に来るsettingを定義するための階層です。
★お次はsetting階層。ここでsectionファイル内の文字通りセッティングをします。
★一番下はblock階層。ここはsettingsの中のsettingみたいなイメージです。
さぁ、さっそくよくわからん構造ですね。なので、まずは見た目を見てみましょうかね。
See the Pen debut slideshow by むーさん (@kyo_mura) on CodePen.
今回、長いので初めてCodePenを使ってみましたが、これだと小さくて、これはこれで見づらいすね。
ともあれこんなコードが書かれています。上の部分はHTMLにliquidのコードが埋め込まれてる感じですね。今回解説するshcemaは下の方で
{% schema %}
・・・・・・
{% endschema %}
が開始タグと終了タグですshopifyの無料テンプレートは多言語対応しているので、ものすごくコード量が多いですし、読めない言語の情報も盛りだくさんですね^^;
さて、これだと長いし、めちゃ複雑なので見づらいし、理解にも時間がかかります。そこで今回は解説用に小さめのsectionを作ってみましょう。まずは元となるHTMLを作ります。
<section class="lesson-section">
<h2>ここがタイトル</h2>
<p>ここがコメント1</p>
<div class="lesson-section-img">
<img src="img/kumachan.jpg">
</div>
<div class="lesson-section-img">
<img src="img/kuma-2.jpg">
</div>
<p>ここにコメント2</p>
</section>
例えばこの程度のセクションをHTMLで作ったとしましょう。スタイルを若干整えて、出力した画面がこちら
きわめてシンプルな奴ですよね。これをliquidでsection化してschemaを定義することによって、コメントも画像もshopifyのカスタマイズ画面上から変更できるようになるんです!
画像があえて2枚入れてあるのは、後々blockの解説をする為です。
先に完成したコードを書いて、階層の解説に入りますよー!
<section class="lesson-section">
<h2>{{section.settings.title}}</h2>
<p>{{section.settings.content1}}</p>
{% for block in section.blocks %}
<div class="lesson-section-img">
{{ block.settings.image_pic | img_url: "master" | img_tag }}
</div>
{% endfor %}
<p>{{section.settings.content2}}</p>
</section>
{% schema %}
{
"name": "Lesson for Schema",
"settings": [
{
"type": "text",
"id": "title",
"label": "タイトル",
"default": "ここがタイトル"
},
{
"type": "text",
"id": "content1",
"label": "コメント1",
"default": "ここがコメント1"
},
{
"type": "text",
"id": "content2",
"label": "コメント2",
"default": "ここがコメント2"
}
],
"blocks": [
{
"type": "image_picker",
"name": "Image picker",
"settings":[
{
"type": "image_picker",
"id": "image_pic",
"label": "画像を入れる"
}
]
}
],
"presets": [
{
"category": "my custom part",
"name": "lesson schema"
}
]
}
{% endschema %}
これが最初のHTMLをsection化してschemaを定義したコードです。
技術的にはsectionに対してsettingを施し、さらにその中にblockを定義していると言う所ですね。ほかにも使える属性はあって、typeで指定していくのですが、今回はわかりやすくテキストを扱う「text」と画像を扱う「image_picker」だけを使ってます。
さてこの構造からまずは図解しましょう。
shopifyのテンプレートの構造はこんな感じです。templateファイルがsectionを読み込んで、そのsectionの中にblockを呼び出します。ちなみにコード次第ではsnippetも呼び出せますが、その辺りはここでは割愛します。
snippetについてはとりあえずこちらがいいかな?!
ちなみに上記記事では「snippetはsectionの下層っぽい物(正確には違うけど)」と書いてありますが、blockと同列でもありません。blockの方が正式に下層です!snippetは上記の記事でも書いている通り、正確には下層ではなくて、本当は階層関係にはなっていません。「snippetはどこにでも呼び出せるパーツファイル」が正しい解釈ですかね。schemaを扱うようになった頃には認識を改めましょう!(最初は「snippetは下層」で入った方がわかりやすいと思います)
階層については何となくわかりましたかね?
schemaを定義する
今回問題なのは
ここの部分ですね。これをどうやって定義しているのかと言う所です。
<section class="lesson-section">
<h2>{{section.settings.title}}</h2>
<p>{{section.settings.content1}}</p>
{% for block in section.blocks %}
<div class="lesson-section-img">
{{ block.settings.image_pic | img_url: "master" | img_tag }}
</div>
{% endfor %}
<p>{{section.settings.content2}}</p>
</section>
上部のHTML部分から見てみましょう。ここでは呼び出しとして {{ … }} で囲まれて書かれている部分が2種類あるのがわかりますか?
settingsの中身
1つは {{section.settings.title}} のように sectionで始まっている部分ですね。ここに対応するschemaがどこかと言うと
{
"type": "text",
"id": "title",
"label": "タイトル",
"default": "ここがタイトル"
},
の部分です。さらにこれを上の階層まで見ると settings:[] の中に書かれているのがわかりますか?この中に書かれているので、sectionのsettingのさらにidでがtitleを呼び出してね!とプログラミングで言う所のobject構造になっています。
ちなみにlabelは見出しなので、後でカスタマイズ画面上で見出しになってます。defaultgは設定してもしなくてもいいです。単にdefaultでテキストが入力されるだけです。
ついでにですが、全体を囲む時は ”settings”[]: と 角括弧になっているのがわかりますか?さらによくよく見るとsettingsと複数形なのにも注意をしましょう!結構この文字1つで保存すること自体を拒んできますので、セーブすらさせてくれなくなりますから^^;
blockがあるといっぱい呼び出せる
さぁ、さらに見ていくとsetting「 ] 」で終わった後に ”blocks”:[] 定義されて、さらにその中に settings:[] がもう1回定義されています。
ここがsectionファイルの最大のポイントです!
blocksで指定した物はforで囲うことで同じセクション内で何回でも呼び出せます(maxをの数も定義も出来ますが今回は割愛)
{% for block in section.blocks %}
<div class="lesson-section-img">
{{ block.settings.image_pic | img_url: "master" | img_tag }}
</div>
{% endfor %}
この部分ですね。blocksをblockに置き換えてループ処理しろや!っていう命令になってわけです。これでカスタマイズ画面で無限に増やせるblockができます。
そして呼び出すときはこのblockに対するsettingよ呼び出して、さらにそれに呼応するidを指定しているので
{{ block.settings.image_pic | img_url: “master” | img_tag }}
こうなってます。後ろのフィルターはimg_urlの方は画像のサイズ、img_tagのの方は<img src=””>部分を読みだしてますね。
定義はともかく、言ってることがわかり辛いと思うので画像で見てみましょう。
実際にshopifyのカスタマイズのindexで呼び出してみると、このファイルはこんな感じで呼び出されます。
上の部分がblocks。見ての通り「+」がついていて増やせることがわかりますよね?それに対して、最初の階層で定義しているsettingは表の画面にもう出てきています。
こちらはループ処理しない部分なので、最初のところで書き換えていくわけです。
これを普通にカスタマイズ画面上から操作すると・・・
ほれ、見てくださいまし!写真が2枚入ってて、書き換えた文章も書き変わってるでしょ?!こんな風に自分でカスタマイズ画面からいじれるsectionを作っていくわけです。
これの応用編では、例えば動画のセクションを作ったり、スライドショーの自作も可能です!でも、とりあえずはまず、簡単なsection作りからいろいろ、いじくってみましょう!
まとめと注意事項
まとめる前にとっても重要な注意事項です。
schemaはjson形式で書いていくのですが、このjson君は結構融通が利きません!しかも書き方失敗するとローカル開発してようが、shopify上のコード編集から編集していようが
「お前のschema書き間違えてるから、保存しないよ?!」
っと保存すらさせてくれずに、延々と悩むことになります。(セーブポイントにたどり着かないロープレでお母さんに「ご飯だからゲームやめなさ」って言われている気分になります)
僕の場合結構なケースで「,」カンマにやられます。これたとえば
{
"type": "text",
"id": "title",
"label": "タイトル",
"default": "ここがタイトル"
},
{
"type": "text",
"id": "content1",
"label": "コメント1",
"default": "ここがコメント1"
},
{
"type": "text",
"id": "content2",
"label": "コメント2",
"default": "ここがコメント2"
}
ここ見てください。1つめから2つめの波括弧のところでは「,」ついてるけど、最後の閉じのところには「,」ついてないんですよ。これは絶対です!!
ここに「,」つけてるだけで保存させてくれません。そしてこれは[]の方でも同じです。わがままなんですよね。この微妙な記述に。
それと最後の方に書いてある
"presets": [
{
"category": "my custom part",
"name": "lesson schema"
}
]
ここは、indexでsectionを増やすために定義している部分。こちらは詳しくは
こちらをどうぞ!
って、ことでまとめると
schemaはsectionのsettingを書くものでsettingの中にはblocksが書けて、blockは繰り返し使えるパーツ。んでもってblockの中身はblokcs内のsettingで書く
うーん、まとめてもそこそこ長いけど、そう言う事ですね。
まずはレッツトライです!簡単なsectionから作ってみましょう^^