Hello Champ’s, Today i will show you how to add User follow/unfollow system in Laravel 9.
We will do this in steps wise.
- Download Laravel
- Install overtrue/laravel-follow Package
- Create Authentication
- Create Dummy Users using factory
- Changes in User Model
- Create Controller and Methods
- Create Blade files
- Add Routes
- Run the project
Step 1. Download Laravel
Let’s start this example, we will start it by installing a new laravel application. if you have already installed, then skip following step.
composer create-project laravel/laravel Laravel9FollowSystem
Step 2. Install overtrue/laravel-follow Package
Now here i will install laravel-follow package for follow/unfollow. So go to terminal and run the below command.
composer require overtrue/laravel-follow -vvv
When it’s done, open the config/app.php file and add service provider.
'providers' => [ .... .... Overtrue\LaravelFollow\FollowServiceProvider::class, ],
For publishing the migrations file run below command
php artisan vendor:publish --provider='Overtrue\LaravelFollow\FollowServiceProvider' --tag="migrations"
Step 3. Create Authentication
In this step, I create authentication of Laravel 9, so laravel provides an artisan command to create authentication, Here i am using JetStream. Install it from given link.
Step 4. Create Dummy Users using factory
In this step, I will create some dummy users for testing, so here i will use formate factory.
Note: Before running this command make sure you have correct setting of database in your .env file.
php artisan migrate
Use the below command for insertion of 100 users.
php artisan ti
then
App\Models\User::factory(100)->create();
Step 5. Changes in User Model
Here i need to use the CanLike trait in the User model. Follow the below code and change the same in your model.
App/Models/User.php
<?php namespace App\Models; // use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Laravel\Sanctum\HasApiTokens; use Overtrue\LaravelFollow\Traits\CanFollow; use Overtrue\LaravelFollow\Traits\CanBeFollowed; class User extends Authenticatable { use HasApiTokens, HasFactory, Notifiable, CanFollow, CanBeFollowed; protected $fillable = [ 'name', 'email', 'password', ]; protected $hidden = [ 'password', 'remember_token', ]; protected $casts = [ 'email_verified_at' => 'datetime', ]; }
Step 6. Create Controller and Methods
In this step i will create a controller using artisan command. Use the below command to create controller.
php artisan make:controller HomeController
Here HomeController is my controller name.
Now i will create some methods. Check my controller code.
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Models\User; class HomeController extends Controller { public function __construct() { // $this->middleware('auth'); } public function index() { return view('home'); } public function users() { $data['users'] = User::get(); return view('userList', $data); } public function user($id) { $data['user'] = User::find($id); return view('usersView', $data); } public function follwUserRequest($id){ $user = User::find($id); $response = auth()->user()->toggleFollow($user); // dd(auth()->user()->isFollowing($user)); if(auth()->user()->isFollowing($user)) { return response()->json(['success'=>true]); }else{ return response()->json(['success'=>$response]); } } }
Step 7. Create Blade files and JS File
In this step i will create some blade files. First i will create userList.blade.php
resources/views/userList.blade.php
<html> <head> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"> <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script> <meta name="csrf-token" content="{{ csrf_token() }}" /> </head> <body> <nav class="navbar navbar-expand-lg navbar-light bg-light"> <a class="navbar-brand" href="#">Follow Syatem</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav mr-auto"> <li class="nav-item active"> <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a> </li> <li class="nav-item"> <a class="nav-link" href="#">Link</a> </li> </ul> <form class="form-inline my-2 my-lg-0"> <input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search"> <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button> </form> </div> </nav> <div class="container"> <div class="row"> @include('users-component'); </div> </div> </body> {{-- <script src="{{ asset('js/custom.js') }}" defer></script> --}} <script> $(document).ready(function() { $.ajaxSetup({ headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') } }); $('.action-follow').click(function(){ var user_id = $(this).data('id'); // alert(user_id); var cObj = $(this); var c = $(this).parent("div").find(".tl-follower").text(); $.ajax({ type:'GET', url:'/follow/'+user_id, data:"", success:function(data){ // alert(data); console.log(data.success); if(!data.success){ cObj.find("strong").text("Follow"); cObj.parent("div").find(".tl-follower").text(parseInt(c)-1); }else{ cObj.find("strong").text("UnFollow"); cObj.parent("div").find(".tl-follower").text(parseInt(c)+1); } } }); }); }); </script> </html>
resources/views/usersView.blade.php
<html> <head> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"> <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script> <meta name="csrf-token" content="{{ csrf_token() }}" /> </head> <body> <nav class="navbar navbar-expand-lg navbar-light bg-light"> <a class="navbar-brand" href="#">Follow Syatem</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav mr-auto"> <li class="nav-item active"> <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a> </li> <li class="nav-item"> <a class="nav-link" href="#">Link</a> </li> </ul> <form class="form-inline my-2 my-lg-0"> <input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search"> <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button> </form> </div> </nav> <div class="container"> <div class="row justify-content-center"> <div class="col-md-12"> <div class="card"> <div class="card-header"> {{ $user->name }} <br/> <small> <strong>Website:</strong> <a href="https://readytocode.net/">readytocode.net</a>, <strong>Email: </strong>{{ $user->email }} </small> </div> <div class="card-body"> <nav> <div class="nav nav-tabs" id="nav-tab" role="tablist"> <a class="nav-item nav-link active" id="nav-home-tab" data-toggle="tab" href="#followers" role="tab" aria-controls="nav-home" aria-selected="true">Followers <span class="badge badge-primary">{{ $user->followers()->get()->count() }}</span></a> <a class="nav-item nav-link" id="nav-profile-tab" data-toggle="tab" href="#following" role="tab" aria-controls="nav-profile" aria-selected="false">Following <span class="badge badge-primary">{{ $user->followings()->get()->count() }}</span></a> </div> </nav> <div class="tab-content" id="nav-tabContent"> <div class="tab-pane fade show active" id="followers" role="tabpanel" aria-labelledby="nav-home-tab"> <div class="row pl-5"> @include('users-component', ['users'=>$user->followers()->get()]) </div> </div> <div class="tab-pane fade" id="following" role="tabpanel" aria-labelledby="nav-profile-tab"> <div class="row pl-5"> @include('users-component', ['users'=>$user->followings()->get()]) </div> </div> </div> </div> </div> </div> </div> </div> </body> </html>
resources/views/users-component.blade.php
@if($users->count()) @foreach($users as $user) <div class="col-2 profile-box border p-1 rounded text-center bg-light mr-4 mt-3"> <img src="https://picsum.photos/50/50" style="height: 50px; width: 50px; border-radius: 50%;" class="img-responsive"> <h5 class="m-0"><a href="{{ route('user.view', $user->id) }}"> <strong>{{ $user->name }}</strong> </a> </h5> <p class="mb-2"> <small> Following: <span class="badge badge-primary">{{ $user->followings()->get()->count() }}</span> </small> <small> Followers: <span class="badge badge-primary tl-follower">{{ $user->followers()->get()->count() }}</span> </small> </p> <button class="btn btn-info btn-sm action-follow" data-id="{{ $user->id }}"> <strong> @if(auth()->user()->isFollowing($user)) UnFollow @else Follow @endif </strong> </button> </div> @endforeach @endif
Step 8. Add Routes
In this step, i will create routes for follow and unfollow.
Route::get('users', [HomeController::class,'users'])->name('users'); Route::get('user/{id}', [HomeController::class,'user'])->name('user.view'); Route::get('follow/{id}', [HomeController::class,'follwUserRequest'])->name('follow');
Step 9. Run the project
Use the below command to run
php artisan serv
For User list URL is
http://127.0.0.1:8000/users
Happy Coding….