🎒 はじめに
超シンプルないいね機能をLaravelで実装してみました.
🎒 自己紹介
初めまして.趣味でweb開発を勉強している273*(ツナサンド) / Kei.と申します.フルスタック開発やツール制作を行なっています.まだまだ初心者です.
テーブル作成
- 中間テーブルを作成します.user,postテーブルは事前に用意しておきましょう.
- php artisan make:migration create_post_likes_table
- yyyy_mm_dd_hhmmss_create_likes_table.php
public function up(): void
{
Schema::create('likes', function (Blueprint $table) {
// constrainedの第一引数は参照するテーブル名.
// 何も指定しない場合は外部キー(foreignId)から自動で推測される.
$table->foreignId('user_id')->constrained("users")->onDelete('cascade');
$table->foreignId('post_id')->constrained("posts")->onDelete('cascade');
// 主キーをuser_idとpost_idの組み合わせにする
$table->primary(['user_id', 'post_id']);
$table->timestamps();
});
}
モデルの作成,追加
- php artisan make:model Like
- Like.php
// リレーション (Like belongs to a Post)
public function post()
{
return $this->belongsTo(Post::class);
}
// リレーション (Like belongs to a User)
public function user()
{
return $this->belongsTo(User::class);
}
- User.php / Post.php(追加)
public function likes()
{
// User / Post has many Likes
return $this->hasMany(Like::class);
}
ルーティング
- web.php
Route::post('/posts/{postId}/like', [LikeController::class, 'likePost'])->middleware("auth");
いいね登録・削除処理
- LikeController.php
public function likePost(Post $post)
{
// ログインユーザーのidを取得
$user_id = Auth::id();
// ログインユーザーがその投稿をいいねしているレコードを取得
$liked_post = $post->likes()->where('user_id', $user_id);
// 既に「いいね」しているか確認
if (!$liked_post->exists()) {
//「いいね」していない場合は,likesテーブルにレコードを追加
$like = new Like();
$like->user_id = $user_id;
$like->post_id = $post->id;
$like->save();
} else {
// 既に「いいね」をしていた場合は,likesテーブルからレコードを削除
$liked_post->delete();
}
// いいねの数を取得
$likes_count = $post->likes->count();
$param = [
'likes_count' => $likes_count, // いいねの数
];
// フロントにいいねの数を返す
return response()->json($param);
}
いいねボタンの挙動を実装
resourcesディレクトリにlike.jsを作成
流れ:全てのいいねボタンを取得,いいねボタンを押されたら,バックエンドにいいね処理を行うように送信.処理が成功したら,非同期でいいね数とアイコンを変更.
- resources/like.js
// 非同期でいいね機能を実装
// 全てのいいねボタン(ハートアイコン)の要素を取得
const likeBtns = document.querySelectorAll(".like-btn");
likeBtns.forEach((likeBtn) => {
// どれかのいいねボタンがクリックされた時の処理
likeBtn.addEventListener("click", async (e) => {
// クリックされたいいねボタンのid(post id)を取得
const postId = e.target.id;
// /posts/{postId}/likeにPOSTリクエストを送信
await fetch(`/posts/${postId}/like`, {
method: "POST", // リクエストメソッドはPOST
headers: {
//Content-Typeでサーバーに送るデータの種類を伝える。今回はapplication/json
"Content-Type": "application/json",
//csrfトークンを付与
"X-CSRF-TOKEN": document
.querySelector('meta[name="csrf-token"]')
.getAttribute("content"),
},
})
.then((res) => res.json()) // レスポンスをJSON形式に変換;
.then((data) => {
// いいねの数を更新
e.target.nextElementSibling.innerHTML = data.likesCount;
// いいねの状態によってハートアイコンの色を変更
if (e.target.classList.contains("text-pink-500")) {
e.target.classList.remove("text-pink-500");
e.target.setAttribute("name", "heart-outline");
} else {
e.target.classList.add("text-pink-500");
e.target.setAttribute("name", "heart");
}
})
// 失敗した場合はアラートを表示
.catch(() => alert("いいね処理が失敗しました"));
});
});
- app.js
import "./like"; // 追加
いいねボタンの作成
- アイコン:Ionicons: Premium Open Source Icon Pack for Ionic Framework
- 登録不要でscriptタグで読み込むだけで使用可能.
- index.blade.php / show.blade.php
<!-- bladeファイルのheadタグ -->
<head>
<meta charset="utf-8">
<title>Blog</title>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet">
<!-- アイコンの読み込み -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<script type="module" src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.esm.js"></script>
<script nomodule src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.js"></script>
</head>
<!--いいねボタンの作成 -->
<div class="flex items-center gap-3">
<h2 class='title text-xl text-blue-600 font-bold'>
<a href="/posts/{{ $post->id }}">{{ $post->title }}</a>
</h2>
@auth
<!--その投稿がいいねしているか判定 -->
@if (Auth::user()->likes()->where('post_id', $post->id)->exists())
<ion-icon name="heart" class="like-btn cursor-pointer text-pink-500" id={{$post->id}}></ion-icon>
@else
<ion-icon name="heart-outline" class="like-btn cursor-pointer" id={{$post->id}}></ion-icon>
@endif
<p class="count-num">{{$post->likes->count()}}</p>
@endauth
</div>
🎒 最後に
Laravelは非常に扱いやすいフレームワークですね.今後も触っていきたいと思います.最後まで読んでいただきありがとうございました!