2020-05-04

マーケットプレイス的なサイトを作ってみる:商品の登録・編集 #craftcms

Craft CMS でマーケットプレイス的なサイトのプロトタイプを作ってみる。
会員登録ができて、ユーザーが商品を登録し、ユーザーが商品を購入する、みたいなのをイメージして。

ユーザー登録とかその辺は以前に作ってあったのだけど、また別の時に振り返る。
完全に作りきるとか、このままリリースってレベルではなくて、それはちゃんとプロジェクトとしてやる時に精度をあげつつ、とりあえず大枠を通してやってみようという感じで。

  • 会員登録、情報編集
  • ユーザーが商品を登録
  • 購入時にStripeの決済を使う
  • 決済が終了したら注文情報をデータ(エントリ)として保存する

あたりを。

ユーザーが商品を登録する

セクションの構成としては「商品( product )」「注文状況( order )」。

エントリを追加するのは Craft CMS のドキュメントにある方法で問題なく行える。

Entry Form | Craft 3 Documentation
https://docs.craftcms.com/v3/d...

ここにあるように作る。画像の登録は先日のエントリにある通り。

画像を削除する方法とかも考えておいた方がよさそう。

コードとしてはこんな感じでたとえば addproduct.twig とかにしておく。

{% if currentUser.isInGroup('owner') %} // ユーザーグループとかで制御かけるなら分岐を入れておく
  <h2 class="h2">アイテム管理</h1>

  {% macro errorList(errors) %} // エラーの対応
      {% if errors %}
          <ul class="errors">
              {% for error in errors %}
                  <li>{{ error }}</li>
              {% endfor %}
          </ul>
      {% endif %}
  {% endmacro %}

  <form method="post" accept-charset="UTF-8" enctype="multipart/form-data"> // 画像アップするので変更しておく
    {{ csrfInput() }}
    {{ actionInput('entries/save-entry') }} // エントリを作成する時の投げ先
    {{ redirectInput('mypage/product') }} // エントリが作成された後のリダイレクト先のURLを指定
    {{ hiddenInput('sectionId', '1') }} // エントリを作成するセクションを指定
    {{ hiddenInput('enabled', '1') }} // 作成するエントリのステータスを指定

    <div class="form-group">
      <label for="title" class="col-form-label">商品名</label>
      <input id="title" type="text" name="title"
          {%- if entry is defined %} value="{{ entry.title }}"{% endif -%} class="form-control mx-2">
      {% if entry is defined %}
          {{ _self.errorList(entry.getErrors('title')) }}
      {% endif %}
    </div>

    <div class="form-group">
      <label for="productDescription" class="col-form-label">商品説明</label>
      <textarea id="productDescription" name="fields[productDescription]" class="form-control mx-2"> // name は fields[ハンドル名] になる
        {%- if entry is defined %}{{ entry.productDescription }}{% endif -%}
      </textarea>
      {% if entry is defined %}
        {{ _self.errorList(entry.getErrors('productDescription')) }}
      {% endif %}
    </div>
    <div class="form-group">
      <label for="productPrice" class="col-form-label">料金</label>
      <input type="number" id="productPrice" name="fields[productPrice]" {%- if entry is defined %} value="{{ entry.productPrice }}"{% endif -%} class="form-control mx-2">
      {% if entry is defined %}
        {{ _self.errorList(entry.getErrors('productPrice')) }}
      {% endif %}
    </div>

    <div class="form-group">
      <label for="productPicture" class="col-form-label">商品写真</label>
      <div class="row">
        <div class="col-md-9">
          <input id="photo" type="file" name="fields[productPicture][]" multiple accept="image/png,image/jpeg">
        </div>
      </div>
    </div>

    <button class="btn btn-primary btn-block" type="submit">上記の内容で商品を登録</button>
  </form>

{% endif %}

写真を登録するときのアップ先が今はCMSの設定として asset/product/{user.id} になってる。
商品ごとに分けてもよかったのだけど、この処理の時点でエントリIDが判明していないので一旦はユーザーごとに、ということで。

登録した商品情報を編集する

登録した商品情報(エントリ)を編集することがあると思うので、そこを考える。
だいたいは商品登録のテンプレートと同じになる。

とりあえず /editproduct?id=hoge みたいなURLで編集ページへ遷移してくる想定で考える。

editproduct.twig の先頭でエントリIDを取得しておく。
その上でエントリの情報を entry にセットする。

{% set eid = craft.request.getParam('id') %}
{% if eid is defined %}
{% set entry = craft.entries().id(eid).one() %}
{% endif %}

編集する内容をあらかじめvalueに設定しておく。

<div class="form-group">
      <label for="title" class="col-form-label">商品名</label>
      <input id="title" type="text" name="title"
          {%- if entry is defined %} value="{{ entry.title }}"{% endif -%} class="form-control mx-2">

      {% if entry is defined %}
          {{ _self.errorList(entry.getErrors('title')) }}
      {% endif %}
    </div>

    <div class="form-group">
      <label for="productDescription" class="col-form-label">商品説明</label>
      <textarea id="productDescription" name="fields[productDescription]" class="form-control mx-2">
        {%- if entry is defined %}{{ entry.productDescription }}{% endif -%}
      </textarea>
      {% if entry is defined %}
        {{ _self.errorList(entry.getErrors('productDescription')) }}
      {% endif %}
    </div>

画像を削除するだけのところを考える必要がある。一旦後回し。

あとはエントリのアップデートなので

{{ hiddenInput('entryId', eid) }}

を設定するのを忘れないようにする。

これで商品の登録、編集が可能になる。

特にプラグインとかは不要でテンプレートだけで作れる。
GraphQLの Mutation とかも考えなくてよかった。

なんかこの辺、難しく考え過ぎてた気がするなー