Real-World Use Case:
A Laravel application displays posts from users in a page. Each post will have an option for users to Like and Unlike the post by clicking the thumbs up icon which will also display a Like counter.
Create a Post and Like Table using migration
php artisan make:migration create_posts_table
php artisan make:migration create_likes_table
Edit the create_posts_table and create_likes_table migration file
create_posts_table migration file
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('body');
$table->timestamps();
});
create_likes_table migration file
Schema::create('likes', function (Blueprint $table) {
$table->id();
$table->foreignId('post_id')->constrained()->onDelete('cascade');
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->boolean('like');
$table->timestamps();
});
Run the migration
php artisan migrate
Create a Post and Like Model
php artisan make:model Post
php artisan make:model Like
Update the Post, Like and User Model
Post Model
use HasFactory;
protected $fillable = ['title', 'body'];
public function likes()
{
return $this->hasMany(Like::class)->where('like', true);
}
Like Model
use HasFactory;
protected $fillable = ['post_id', 'user_id', 'like'];
public function post()
{
return $this->belongsTo(Post::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
User Model
public function likes()
{
return $this->hasMany(Like::class);
}
public function hasLiked($postId)
{
return $this->likes()->where('post_id', $postId)->where('like', true)->exists();
}
public function toggleLikeUnlike($postId, $like)
{
$existingLike = $this->likes()->where('post_id', $postId)->first();
if ($existingLike) {
if ($existingLike->like == $like) {
$existingLike->delete();
return [
'hasLiked' => false
];
} else {
$existingLike->update(['like' => $like]);
}
} else {
$this->likes()->create([
'post_id' => $postId,
'like' => $like
]);
}
return [
'hasLiked' => $this->hasLiked($postId)
];
}
Create route inside web.php
Route::get('/likeunlike', [App\Http\Controllers\PostController::class, 'likeunlike'])->name('likepage');
Route::post('posts/ajax-like-unlike', [App\Http\Controllers\PostController::class, 'ajaxLike'])->name('posts.ajax.like.unlike');
Create Post Controller
php artisan make:controller PostController
Update Post Controller
public function likeunlike()
{
$posts = Post::get();
return view('likepage',compact('posts'));
}
public function ajaxLike(Request $request)
{
$post = Post::find($request->id);
$response = auth()->user()->toggleLikeUnlike($post->id, $request->like);
return response()->json(['success' => $response]);
}
Display data in the post page (Add sample data in the Post Table if needed)
@foreach($posts as $post)
<div class="card-body">
<p class="card-title">{{ $post->title }}</p>
<p>{{$post->body}}</p>
<div class="like-box">
<i id="like-{{ $post->id }}" data-post-id="{{ $post->id }}"
class="like fa-thumbs-up {{ auth()->user()->hasLiked($post->id) ? 'fa-solid' : 'fa-regular' }}"></i>
<span class="like-count">{{ $post->likes->count() }}</span>
</div>
</div>
@endforeach
Add the javascript within the post page
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js" referrerpolicy="no-referrer"></script>
<script type="text/javascript">
$(document).ready(function() {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$('.like-box i').click(function(){
var id = $(this).attr('data-post-id');
var boxObj = $(this).parent('div');
var c = $(this).parent('div').find('span').text();
var like = $(this).hasClass('like') ? 1 : 0;
$.ajax({
type:'POST',
url: "{{ route('posts.ajax.like.unlike') }}",
data:{ id:id, like:like },
success:function(data){
if (data.success.hasLiked == true) {
$(boxObj).find(".like").removeClass("fa-regular");
$(boxObj).find(".like").addClass("fa-solid");
var likes = $(boxObj).find(".like-count").text();
$(boxObj).find(".like-count").text(parseInt(likes)+1);
} else {
if($(boxObj).find(".like").hasClass("fa-solid")){
var likes = $(boxObj).find(".like-count").text();
$(boxObj).find(".like-count").text(parseInt(likes)-1);
}
$(boxObj).find(".like").removeClass("fa-solid");
$(boxObj).find(".like").addClass("fa-regular");
}
}
});
});
});
</script>
