LoginSignup
4
6

More than 3 years have passed since last update.

laravel vue.jsでお気に入り機能を作る

Posted at

使用するファイル

・User.php
・ProductController.php
・index.blade.php
・LikeComponent.vue
・app.js
・LikeController.php

Userモデルにて多対多のリレーションを行う。

User.php
  public function likeProducts()
    {
        return $this->belongsToMany(Product::class, 'like_products');
    }

多対多のリレーションを行う。
belongsToManyの第一引数にリレーション先モデル名、第二引数に中間テーブル名を指定している。

ProductControllerからindex.blade.phpに商品データを送る

ProductController.php
 public function index(ProductSearchService $productSearchService, Request $request)
    {
        $likeProducts = Auth::user()->likeProducts()->pluck('product_id');
        $products = $productSearchService($request);
        return view('products.index', compact([
            'products',
            'likeProducts',
        ]));
    }

Auth::user()->likeProducts()->pluck('product_id');
先ほど多対多のリレーションを行なったのでそれを使用する。
中間テーブルであるlike_productsにログインユーザーが登録したproduct_idをコレクションで取得している。

viewを用意(ここにlike-component)を埋め込む

index.blade.php
<div class="row pt-2 px-5">
    @foreach ($products as $product)
    <a href="{{ route('products.show', $product->id) }}" class="mb-5 ml-5">
        <img src="{{ asset('storage/product_images/'.$product->image_path_one) }}" style="width: 100px; height: 100px;"
            class="img-thumbnail mx-auto d-block">
        <div class="center-block">
            <p class="text-center">{{ $product->name }}</p>
            <p class="text-center">¥{{ number_format($product->price) }}</p>
        </div>
    </a>

    <div id="app">
        <like-component :product-id="{{ $product->id }}" :liked-data="{{ $likeProducts  }}"></like-component>
    </div>
    @endforeach
</div>

foreachでコントローラーから送られてきた商品データのコレクションを一つずつ展開している。
like-componentへv-bindで展開したproductIdとログインユーザーがlike_productsテーブルに格納しているproductIdを渡している。
v-bindでの変数はケバブケースでないといけない。

LikeComponent.vue
<template>
  <div>
    <i
      v-on:click="storeOrDelete"
      :class="[isActiveTrue === true ? 'far fa-heart ml-3' : 'fas fa-heart ml-3']"
    ></i>
  </div>
</template>

<script>
export default {
  props: ["productId", "likedData"],
  data() {
    return {
      isActiveTrue: this.likedData.includes(this.productId) ? false : true
    };
  },
  methods: {
    change() {
      this.isActiveTrue = !this.isActiveTrue;
    },
    storeProductId() {
      axios
        .post("like/" + this.productId, {
          productId: this.productId
        })
        .then(response => {
          console.log("success");
        })
        .catch(err => {
          console.log("error");
        });
    },
    deleteProductId() {
      axios
        .delete("like/" + this.productId, {
          data: {
            productId: this.productId
          }
        })
        .then(response => {
          console.log("success");
        })
        .catch(err => {
          console.log("error");
        });
    },
    storeOrDelete() {
      const isTrue = this.likedData.includes(this.productId);
      if (isTrue === true) {
        this.deleteProductId();
        this.change();
      } else {
        this.storeProductId();
        this.change();
      }
    }
  }
};
</script>

propsで先ほどindex.blade.phpから渡されたproduct-idとliked-dataを受け取っている。
先ほど渡す時はケバブケースだったが、こちらではローワーキャメルケースで書かないといけない。

storeOrDeleteメソッドの説明をする。
const isTrue = this.likedData.includes(this.productId);
likeData(ユーザーがお気にいりしているproductIdが配列で格納されている)の中にその商品のIDがあるかincludesメソッドで調べている。もし、ある商品(お気にりしているということ)ならお気に入りから外し、なければお気に入り登録する。
changeメソッドでstyleの切り替えを行なっている。

:class="[isActiveTrue === true ? 'far fa-heart ml-3' : 'fas fa-heart ml-3']"
はisActiveTrueがtrueかfalseでスタイルの切り替えをおこなっている。

作成したコンポーネントを使用できるようにする

app.js
Vue.component('like-component', require('./components/LikeComponent.vue').default);

new Vue({
    el: '#app',
});

Vue.component('like-component', require('./components/LikeComponent.vue').default);

で先ほど作成したlike-componentを読み込んでいる。

new Vue({
el: '#app',
});

でindex.blade.phpの#app内でvue.jsが使えるようになる。

like-componentから非同期で送られてきたproductIdをlike_productsテーブルに登録・削除を行う。

LikeProductController.php
  public function store(Product $product)
    {
        Auth::user()->likeProducts()->attach($product);
    }


    public function delete(Product $product)
    {
        Auth::user()->likeProducts()->detach($product);
    }
}

storeメソッドでは、like_productsテーブルにログインしているユーザーのIDとメソッドインジェクションの$product(like-componentから非同期で送られてきたproductId)をインサートしている。deletメソッドでは、反対に削除している。

これでお気に入り機能が完成した。

4
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
6