Skip to main content

Black Friday 2025! Only until December 1st: coupon FRIDAY25 for 40% off Yearly/Lifetime membership!

Read more here
Premium Members Only
Join to unlock this tutorial and all of our courses.
Tutorial Premium Tutorial

Livewire Like/Dislike Component for Social Networks: Step-by-Step

April 25, 2023
15 min read

In this tutorial, we will use Livewire to create a component for Like/Dislike, similar to YouTube or any social network. We will show the count of likes and dislikes, also minimizing the number of queries to the DB.

finished livewire component


Laravel Project Preparation

We'll show the list of posts and the number of votes for every post.

For this demo, we'll use our own Laravel Breeze Pages Skeleton which will give use Breeze-like layout but with a public page for posts list.

First, we need a Post Model, Controller, and View. For now, without any Livewire.

php artisan make:model Post -mc

database/migrations/xxxx_create_posts_table.php:

return new class extends Migration {
public function up(): void
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('text');
$table->timestamps();
});
}
};

app/Models/Post.php:

class Post extends Model
{
protected $fillable = [
'title',
'text',
];
}

app/Http/Controllers/PostController.php:

class PostController extends Controller
{
public function __invoke(): View
{
$posts = Post::latest()->paginate();
 
return view('posts', compact('posts'));
}
}

And a simple Blade file to show the list of the posts.

resources/views/posts.blade.php:

<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
{{ __('Posts') }}
</h2>
</x-slot>
 
<div class="py-12">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8">
<div class="overflow-hidden bg-white shadow-sm dark:bg-gray-800 sm:rounded-lg">
<div class="p-6 text-gray-900 dark:text-gray-100">
@foreach($posts as $post)
<h3 class="text-xl font-medium">{{ $post->title }}</h3>
<p>{{ $post->text }}</p>
<hr class="my-4">
@endforeach
 
{{ $posts->links() }}
</div>
</div>
</div>
</div>
</x-app-layout>

list of posts

Next, we need to save votes. For this, we will create a Vote Model.

php artisan make:model Vote -m

database/migrations/xxxx_create_votes_table.php:

return new class extends Migration {
public function up(): void
{
Schema::create('votes', function (Blueprint $table) {
$table->id();
$table->foreignId('post_id')->constrained()->cascadeOnDelete();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->smallInteger('vote');
$table->timestamps();
});
}
};

app/Models/Vote.php:

class Vote extends Model
{
protected $fillable = [
'post_id',
'user_id',
'vote',
];
}

Now let's add Vote relations to the Post Model.

app/Models/Post.php:

use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Relations\HasMany;
 
class Post extends Model
{
protected $fillable = [
'title',
'text',
];
 
public function votes(): HasMany
{
return $this->hasMany(Vote::class);
}
 
public function userVotes(): HasOne
{
return $this->votes()->one()->where('user_id', auth()->id());
}
}

We'll need two relations. The first one is just a regular One To Many relation which we will use to create and update the vote for the post.

The second one is more interesting: the userVotes relation will return null if a user hasn't voted yet. Otherwise, it will return the Vote model from which we will be able to tell if a user liked or disliked a post.


Livewire Component

Now let's create a Livewire component.

php artisan make:livewire LikeDislike

First, let's add the Livewire component after the post text and...

Premium Members Only

This advanced tutorial is available exclusively to Laravel Daily Premium members.

Premium membership includes:

Access to all premium tutorials
Video and Text Courses
Private Discord Channel

Comments & Discussion

AA
Adediji Abiodun (Kayode) ✓ Link copied!

A quick question:

First, I'll like to say thanks a lot for this free weekend. This particular feature caught my interest and I tried implementing it on my application but I'm crrently having this error:

Call to undefined relationship [userVotes] on model [App\Models\Post].

on the error page this particular controller instance was highlighted.

public function post(Post $post){
        $user = Auth::user();
        $users = User::all();
        $comments = Comment::all();
        $posts = Post::latest()
        ->with('userVotes')
        ->withCount(['votes as likesCount' => fn (Builder $query) => $query->where('vote', '>', 0)], 'vote')
        ->withCount(['votes as dislikesCount' => fn (Builder $query) => $query->where('vote', '<', 0)], 'vote')
        ->filter(request(['search']))->get(); 

        $likes = Like::all();
        
        return view('fans.postcard')
            ->with('user', $user)
            ->with('users', $users)
            ->with('comments', $comments)
            ->with('posts', $posts)
            ->with('likes', $likes);
    }
		```
		It's an existing apllication, so I have a number of parameters already in the function.  The instance of the userVotes on the model [App\Models\Post] is, as stated in the tutorial:
		```
		public function userVotes() {
        return $this->votes()->one()->where('user_id', auth()->id());
    }
		```
PK
Povilas Korop ✓ Link copied!

The error "Call to undefined relationship [userVotes] on model [App\Models\Post]." means that you literally don't have that method in the Model class. Maybe you named it somehow differently? Could you put your code and GitHub and I would debug for you?

AA
Adediji Abiodun (Kayode) ✓ Link copied!

Thank you very much for your reply. I have sent an email with the link to the project on GitHub.

Thanks again.

We'd Love Your Feedback

Tell us what you like or what we can improve

Feel free to share anything you like or dislike about this page or the platform in general.