
九保すこひです(フリーランスのITコンサルタント、エンジニア)
さてさて、今回は少し前に公開した「【Laravel】ファイルのアップロード機能をつくる(ダウンロード可)」という記事と同じく「記事にしてなかったっけ」でお届けしたいと思います。
その内容はというと・・・
SNS時代によく見るようになった「いいね!」機能をつくる
というものです。
「いいね!」といえば、フェイスブックで見たのが初めてですが、その後ホントにこの機能はどこでも見るようになりました。
そこで!
今回はLaravel
でこの「いいね!」機能をつくってみます。
ぜひ楽しみながらやってみましょう
「生まれて初めて「いいね!」
されたときの興奮は今でも覚えてます」
開発環境: Laravel 7.x
目次 [非表示]
前提として
「いいね!」するデータはなんでもいいのですが、今回はログイン機能をインストールすると作成されるusers
テーブルで実装することにします。
そのため、まだインストールしていない方は「Laravel6.x以降でログイン機能をインストールする方法」を参考にしてテストデータを追加するところまでやっておいてください。
なお、テーブルはこのようになっていればOKです。
モデル&マイグレーションをつくる
では、「いいね!」されたデータを管理するlikes
テーブルとそのモデルを作っていきましょう。
以下のコマンドを実行してください。
php artisan make:model Like -m
次に、作成されたマイグレーション・ファイルを開いて中身を以下のようにします。
/database/migrations/****_**_**_******_create_likes_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateLikesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('likes', function (Blueprint $table) {
$table->id();
$table->string('model')->comment('モデル名');
$table->integer('parent_id')->comment('モデルのID');
$table->string('ip')->comment('IPアドレス');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('likes');
}
}
では、この状態でマイグレーションを実行しましょう。
php artisan migrate
するとテーブルはこうなります。
likesテーブルとのリレーションシップを設定する
次にusers
テーブルからlikes
テーブルのデータも取得できるように「1:多」のリレーションシップをつくっておきます。
// 省略
class User extends Authenticatable
{
// 省略
// Relationship
public function likes() { //
追加
return $this->hasMany(\App\Like::class, 'parent_id', 'id')
->where('model', self::class);
}
}
なお、重要なのはwhere()
の部分です。
この例で言うとmodel
フィールドが「App\User」ものだけ取得することになります。
ルートをつくる
続いてルートです。
Route::get('/like', 'LikeController@index'); //
ブラウザでアクセスする
Route::get('/ajax/like/user_list', 'LikeController@user_list'); //
ユーザー情報を取得
Route::post('/ajax/like', 'LikeController@like'); //
いいね!データを追加
1行目は、ブラウザでアクセスするURL
で、下の2つはAjax
通信用になります。
コントローラーをつくる
次にコントローラーをつくります。
以下のコマンドを実行してください。
php artisan make:controller LikeController
そして中身を次のようにします。
/app/Http/Controllers/LikeController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class LikeController extends Controller
{
public function index(Request $request) {
return view('like.index')->with('ip', $request->ip());
}
public function user_list() {
return $this->getUsers(); // 全ユーザーを取得
}
public function like(Request $request) {
$request->validate([
'user_id' => 'required|exists:users,id'
]);
$result = false;
$model = \App\User::class;
$exists = \App\Like::where('model', $model)
->where('parent_id', $request->user_id)
->where('ip', $request->ip())
->exists();
if(!$exists) {
$like = new \App\Like();
$like->model = $model;
$like->parent_id = $request->user_id;
$like->ip = $request->ip();
$result = $like->save();
}
return [
'result' => $result,
'users' => $this->getUsers() // 全ユーザーを取得
];
}
private function getUsers() {
return \App\User::with('likes')
->withCount('likes')
->get();
}
}
それでは、中身をメソッドごとに説明していきます。
index()
ブラウザからアクセスされるときに実行されるメソッドです。
なお、ビューで現在アクセスしている人のIPアドレスが取得できるようにしています。
user_list()
Ajax
でユーザーデータを取得するためのメソッドです。
like()
このメソッドで「いいね!」データを追加することになります。
getUsers()
LikeController
内でユーザーデータを取得する場所が2ヵ所あるのでひとつにまとめました。なお、private function
なのでこのクラスの中からしかアクセスすることはできません。
ビューをつくる
最後にビューです。
/resources/views/like/index.blade.php
<html>
<head>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div id="app" class="container pt-4">
<h1 class="mb-3">「いいね!」機能のサンプル</h1>
<p class="bg-light p-3">「いいね!」できるのは、IPアドレスごとに1回までです。</p>
<table class="table table-bordered">
<thead class="bg-info text-white">
<tr>
<th>名前</th>
<th class="text-nowrap">いいね!の回数</th>
<th></th>
</tr>
</thead>
<tbody>
<!-- ユーザーリストを表示 ・・・ ① -->
<tr v-for="u in users">
<td class="w-100" v-text="u.name"></td>
<td class="w-100" v-text="u.likes_count"></td>
<td class="text-nowrap">
<!-- いいね!を実行するボタン ・・・ ② -->
<button
type="button"
class="btn btn-info"
:disabled="hasMyLike(u.likes)"
@click="addLike(u.id)">いいね!</button>
</td>
</tr>
</tbody>
</table>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
users: [],
ip: '{{ $ip }}'
},
methods: {
addLike(userId) { // いいね!を追加 ・・・ ①
const url = '/ajax/like';
const params = { user_id: userId };
axios.post(url, params)
.then(response => {
if(response.data.result === true) { // 追加に成功したらデータを更新
this.users = response.data.users;
}
});
},
hasMyLike(likes) { // 自分のIPが含まれているかチェック ・・・ ②
if(likes.length) {
for(let like of likes) {
if(like.ip === this.ip) {
return true;
}
}
}
return false;
}
},
mounted() {
axios.get('/ajax/like/user_list')
.then(response => {
this.users = response.data;
});
}
});
</script>
</body>
</html>
この中でやっているのは次のとおりです。
①ユーザーリストを表示
Vue.js
を使ってAjax
通信で取得したユーザーデータをv-for
でループさせ、1つずつ表示していくことになります。
②いいね!を実行するボタン
クリックされると、likes
テーブルにデータが追加されることになります。
そしてさらに、:disabled
を使ってすでに「いいね!」している場合はクリックができないようにしています。
③いいね!を追加
「いいね!」ボタンがクリックされたときに実行されるコードです。
ここではAjax
で「いいね!」すべきユーザーIDを送信し、もし新規データが追加されたらusers
データを新しいものに置き換えることになります。
④自分のIPが含まれているかチェック
ここは、②で説明した:disabled
の部分で使われる「すでに「いいね!」しているかどうか」をチェックするコードです。
テストしてみる
では実際にテストしてみましょう
まずブラウザで「http://*****/like」にアクセスします。
では、太郎さんと次郎さんの「いいね!」ボタンをクリックしてみます。
すると「いいね!」の回数が増えて、ボタンがクリックできなくなりました。
では、テーブルを見てみましょう。
太郎さん(ユーザーID: 1)と次郎さん(ユーザーID: 2)のデータが存在していて、IPアドレスも保存されています。
では次に、太郎さんのIPアドレスを手動で変更します。
そして、ブラウザをリロードすると以下のように太郎さんの「いいね!」だけクリックできるようになります。
ではこれをクリックしてみましょう。
はい!
太郎さんの「いいね!」が2回になり、再度ボタンはクリックできなくなりました。
成功です
教材ソースコードをダウンロードする
今回実際に教材ソースコード一式を以下からダウンロードできます。
Laravelで「いいね!」機能をつくる※ただし、マイグレーションはご自身で実行してください。
おわりに
ということで、今回はLaravel
を使って「いいね!」機能をつくってみました。
なお、以前私はEvaluationというパッケージを公開していますので、もしよりシンプルに実現したい方はそちらもチェックしてみてくださいね(Evaluationn
で使えるのは「like」「dislike」「favorite」「remember」の4つです)
もしくは、今回の記事をじっくり勉強するのもありかもしれません
ではでは〜
「そういえば、当時はミクシィ
が人気でしたよね(まだアカウントあるかな)」