#laravel×AWSで掲示板を作ろう
本記事は、laravel×AWSの第7回です。
作ったサイト:https://vible.jp
#laravel×ajaxでのいいね機能
ajaxとはjavascriptに搭載されている機能の一つで、googlemapのように画面をリロードすることなく処理を実行してくれるものです。
ajaxを使うことでTwitterとかでも見られるようないいね機能が再現できます。
laravelmixを使っています。
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);
}
データベースと連携させてあげればトップ画面のような、よく見るいいねボタンが実装できると思います。