Simple Laravel referral system using referral code

Nov 09, 2023
laravel
php

The referral is going to work like this:

  1. - A user signs up and a code gets auto generated as their referral code which they can give to others 
    - When a user registers, they're prompted to add a referral code
    - The user whose referral code was used would be notified that someone registered with their code

We are going to be creating 2 migration tables.

The user table and the referral table.


Our eloquent model should be a case where a user can be referred by another user and a user can refer many users but it's going to be (One to One) while we have a column that adds each time a new user uses an existing user referral code. 

#. Creating a laravel referral app

laravel new referral-app

After installing laravel, we make the referral model, migration and controller

php artisan make:model Referral -mc

Now we edit our migration table, first the users table 👇

public function up(): void    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->string('referral_status')->default('off');
            $table->string('referral_by')->nullable();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }

Now we edit the referral table

public function up(): void    {
        Schema::create('referrals', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->constrained()->cascadeOnDelete();
            $table->string('referral_code')->unique()->nullable();
            $table->integer('total_referred_users')->default(0);
            $table->timestamps();
        });
    }

We are using foreignId cause of our Eloquent relationship with the users table One-To-Many.


Let's not forget the auth

composer require laravel/ui
php artisan ui bootstrap
php artisan ui bootstrap --auth

Let's edit our models, starting with the User Model

protected $fillable = [
        'name',
        'email',
        'password',
        'referral_status',
        'referral_by'];

public function referral(){
    return $this->hasOne(Referral::class);
}

  1. - First we added referral_status and referral_by to the $fillable in the User model

  2. - Then we specified the eloquent relationship hasOne

On the other hand the Referral model eloquent relationship should belongsTothe User model and we add 

user_id, referral_code and total_referred_users to the Referral model $fillable

protected $fillable = [
        'user_id',
        "referral_code",
        "total_referred_users"    ];


    public function user(){
        return $this->belongsTo(User::class);
    }

Using MySql, we're going to create a database referral_app and link it to through our .env file.

Now we migrate and the add Auth route to our routes/web.php file

php artisan migrate

In the web.php file add this👇

Auth::routes();

Now let's add referral code to every user who signs up but first we need a page for users to enter their referral code after signing up. We would create a new file in our view/auth folder called referral.blade.php and place this code below in it

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8 card">
            <div class="card-header">{{ __('Referral') }}</div>
            <div class="card-body">
                <form method="POST" action="{{ route('referral.verify') }}">
                    @csrf
                    @method('PATCH')

                    <div class="row mb-3">
                        <label for="referral" class="col-md-4 col-form-label text-md-end">{{ __('Referral Code') }}</label>
                        <div class="col-md-6">
                            <input id="referral" type="text" class="form-control @error('referral') is-invalid @enderror" name="referral" value="{{ old('referral') }}" required autocomplete="referral" autofocus>
                            @error('referral')
                                <span class="invalid-feedback" role="alert">
                                    <strong>{{ $message }}</strong>
                                </span>
                            @enderror
                        </div>
                    </div>

                    <div class="row mb-0">
                        <div class="col-md-8 offset-md-4">
                            <button type="submit" class="btn btn-primary">
                                {{ __('Proceed') }}
                            </button>
                        </div>
                    </div>
                </form>
            </div>
        </div>
    </div>
</div>
@endsection

The form is being submitted to a patch route referral.store which we are going to add the web.php file later on, for now let's add this to the web.php

Route::get('/referral', function(){ return view('auth.referral');})->name('referral');

Now we let's get back to generating a referral code to every user who signs up

Locate the  RegisterController , we're going to edit the protected function create(array $data)

Replace the function with this edited version

protected function create(array $data)    {
        $user = User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => Hash::make($data['password']),
        ]);
        Referral::create([
            'user_id'=> $user->id,
            'referral_code'=>Str::random(6),
        ]);

        return $user;

    }

Also in your view/home.blade.php replace the existing code with this

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Dashboard') }}</div>
                <div class="card-body">
                    @if (session('status'))
                        <div class="alert alert-success" role="alert">
                            {{ session('status') }}
                        </div>
                    @endif

                    <p>Your referral code is {{ auth()->user()->referral->referral_code }}</p>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

Now let's add the referral part. First locate  App/Providers/RouteServiceProvider  and edit

Change from this:

public const HOME = '/home';

To this:

public const HOME = '/referral';

Now it's time to add our route /referral/store and verify referrals.
In your web.php file, add the patch route for storing the referrals

Route::patch('/referral/store', [App\Http\Controllers\ReferralController::class, 'store'])->name('referral.store');

In the ReferralController add the store function

public function store(Request $request){
     $user = User::find(Referral::where("referral_code", $request->referral)->first()->user_id);
     $total_referred_users = $user->referral->total_referred_users + 1;
     $user->referral->update(['total_referred_users'=> $total_referred_users]);
     DB::table('users')->where('id', auth()->user()->id)->update(['referral_by' => $request->referral]);
     Notification::route('mail', $user->email)->notify(new UserNotification());
     return redirect()->action([HomeController::class,'index']);
 }

Let me explain the code

- First we got the user using the referral code that was submitted then we added to it counts of user

- We then proceeded to update the new user's referral_by  column to add a referral code

- Finally, we send a notification to the user who referred that someone signed up with their referral code

Don't forget to make notification to generate the email notification

php artisan make:notification UserNotification

Edit the contents and replace with this code

<?php
namespace App\Notifications;

use Illuminate\Bus\Queueable;
use App\Models\User;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;

class UserNotification extends Notification{
    use Queueable;

    /**
     * Create a new notification instance.
     */    public function __construct()    {
        //    }

    /**
     * Get the notification's delivery channels.
     *
     * @return array<int, string>
     */    public function via(object $notifiable): array    {
        return ['mail'];
    }

    /**
     * Get the mail representation of the notification.
     */    public function toMail(object $notifiable): MailMessage    {
        return (new MailMessage)
                    ->line("A user just joined ".getenv('APP_NAME')." using your referral code")
                    ->line('Thank you for using our application!');
    }

    /**
     * Get the array representation of the notification.
     *
     * @return array<string, mixed>
     */    public function toArray(object $notifiable): array    {
        return [
            //        ];
    }
}

Our Laravel referral system using referral code is now done, don't forget

php artisan serve
npm install
npm run dev

You can check the code out on my github.
https://github.com/hen8y/laravel-referral-system
In case you want to make the notifcation mail send faster, make sure to check laravel queue

© 2024 Ogbonna Henry.