1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

#7 いいね機能の実装 ~laravel×AWSで掲示板を作ろう~

Posted at

#laravel×AWSで掲示板を作ろう
本記事は、laravel×AWSの第7回です。
作ったサイト:https://vible.jp

#laravel×ajaxでのいいね機能
ajaxとはjavascriptに搭載されている機能の一つで、googlemapのように画面をリロードすることなく処理を実行してくれるものです。
ajaxを使うことでTwitterとかでも見られるようないいね機能が再現できます。
laravelmixを使っています。
like.gif

nayami_blade.php
@extends('layouts.layout')
<!DOCTYPE html>
<html>

<head>
  <title>nayami</title>
  <style>
    body {
      font-size: 16pt;
      color: #999;
    }

    th {
      background-color: #999;
      color: fff;
      padding: 5px 10px;
    }

    td {
      border: solid 1px #aaa;
      color: #999;
      padding: 5px 10px;
    }
  </style>

  <meta name="csrf-token" content="{{ csrf_token() }}">
</head>

@section('content')

<div class="outer">
  <div class="inner1">

    <br>
    <h1>投稿された悩み一覧</h1>
    <br>

    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
    <link href="https://use.fontawesome.com/releases/v5.6.1/css/all.css" rel="stylesheet">
  </div>

  <div class="inner2">
    @foreach($questions as $question)
    <div class="tw-block-parent">
      @auth
      @if((int)$question->user_id == Auth::user()->id)
      <div class="button2">
        <button class="btn btn-primary" data-toggle="modal" data-target="#modal-example{{$question->id }}">
          削除
        </button>
        <!-- 2.モーダルの配置 -->
        <div class="modal" id="modal-example{{$question->id }}" tabindex="-1">
          <div class="modal-dialog">
            <!-- 3.モーダルのコンテンツ -->
            <div class="modal-content">
              <!-- 4.モーダルのヘッダ -->
              <div class="modal-header">
                <p class="modal-title" id="modal-label">削除しますか</p>
              </div>
              <!-- 6.モーダルのフッタ -->
              <div class="modal-footer">
                <form method="POST" action="{{route('destroy',['id' => $question->id])}}">
                  @csrf
                  @method('delete')
                  <button class="btn btn-danger" data-id="{{ $question->id }}" type="submit">削除する</button>
                </form>
                <button type="button" class="btn btn-default" data-dismiss="modal">閉じる</button>
              </div>

            </div>
          </div>
        </div>
      </div>
      @endif
      @endauth

      <div class="timeline-TweetList-tweet">
        <div class="timeline-Tweet">
          <div class="timeline-Tweet-author">
            <div class="TweetAuthor">
              <a class="TweetAuthor-link" href="#channel"> </a>
              <span class="TweetAuthor-avatar">
                <div><i class="far fa-user"></i></div>
              </span>
              <form action="/test/mypage" method="post">
                @csrf
                <input type="submit" name="id" value="{{$users->find($question->id)->user->name}}">
                <span class="Icon Icon--verified"></span>
              </form>
              <!--<span class="TweetAuthor-name">{{$users->find($question->id)->user->name}}</span>-->
            </div>
          </div>
          <label>
            <a href="{{ action('QuestionController@detail', $question->id) }}">
              <div class="timeline-Tweet-text">
                <td>{{$question->title}}</td>
                <td>{{$question->content}}</td>
              </div>
            </a>
          </label>
          <div class="timeline-Tweet-metadata"><span class="timeline-Tweet-timestamp">{{$question->created_at}}</span></div>
          <ul class="timeline-Tweet-actions">
            @auth
            @if($likes->where('user_id',Auth::user()->id)->where('question_id',$question->id)->first())
            <li class="timeline-Tweet-action">
              <a class="js-like-toggle loved" href="" data-questionid="{{$question->id}}">
                <i class="fas fa-heart"></i>
              </a>
              <span class="likesCount">{{$question->question_likes_count}}</span>
            </li>
            @else
            <li class="timeline-Tweet-action">
              <a class="js-like-toggle" href="" data-questionid="{{$question->id}}">
                <i class="active far fa-heart"></i>
              </a>
              <span class="likesCount">{{$question->question_likes_count}}</span>
            </li>
            @endif
            @endauth

            @guest
            <p class="favorite-marke">
              <a class="js-like-toggle loved" href="" data-questionid="{{$question->id}}">
                <i class="fas fa-heart"></i>
              </a>
              <span class="likesCount">{{$question->question_likes_count}}</span>
            </p>
            @endguest

          </ul>
        </div>
      </div>
    </div>
    <br>
    @endforeach

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
    <script src="{{ mix('js/_questionlike.js') }}"></script>
  </div>
</div>
@endsection

下記ajaxによる処理を記載します。
"data-questionid"と定義されている箇所と$this.data('questionid')をjavascriptでリンクさせています。
いいねを表すハートマークには、fontawsomeを使用しています。
farが黒塗りハート(♥)、fasが白塗りハート(♡)と対応しています。
今まで何となくクラスとかインデントを記述していましたが、javascriptとの連携をやってみて、きちんと定義してあげることの必要性が分かった気がします。

_questionlike.js
$(function () {
    var like = $('.js-like-toggle');
    var likeQuestionId;
    like.on('click', function () {
        var $this = $(this);
        likeQuestionId = $this.data('questionid');
        $.ajaxSetup({
            headers: {
                'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
            }
        });

        $.ajax({
            headers: {
                'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
            },
            url: '/questionlike',  //routeの記述
            type: 'POST', //受け取り方法の記述(GETもある)
            data: {
                'question_id': likeQuestionId //コントローラーに渡すパラメーター
            },
        })

            // Ajaxリクエストが成功した場合
            .done(function (data) {
                //lovedクラスを追加
                $this.toggleClass('loved');
                $this.children('i').toggleClass('fas');
                $this.children('i').toggleClass('far');
                console.log('sucesssss');


                //.likesCountの次の要素のhtmlを「data.postLikesCount」の値に書き換える
                $this.next('.likesCount').html(data);

            })
            // Ajaxリクエストが失敗した場合
            .fail(function (data, xhr, err) {
                console.log('エラー');
                console.log(err);
                console.log(xhr);
            });

        return false;
    });
});
QuestionController.php
//いいね機能対応箇所のみ
public function ajaxlike(Request $request)
    {
        $id = Auth::user()->id;
        $question_id = $request->question_id;
        $like = QuestionLike::where('question_id', $question_id)->where('user_id', $id)->first();
        $question = Question::findOrFail($question_id);

        if ($like) {
            //likesテーブルのレコードを削除
            $like = QuestionLike::where('question_id', $question_id)->where('user_id', $id)->delete();
        } else {
            QuestionLike::create(['user_id' => $id, 'question_id' => $question_id]);
        }

        $questionLikesCount = $question->loadCount('question_likes')->question_likes_count;
        //これがajaxのdataとして渡される
        print($questionLikesCount);
    }

データベースと連携させてあげればトップ画面のような、よく見るいいねボタンが実装できると思います。

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?