Building a referral system with laravel REST API
Tags: laravel, php, system, webdev
Published: 2023-03-04 12:22:45

Recently, I was tasked with building a referral system as a feature in an e-commerce application I was working on.
I thought about different scenarios it could be done and even considered some laravel packages that could do the work. But I wanted to make it as simple and less complicated as possible, so I opted for building it from scratch.

Thinking about the fact that I was working on a REST API, the first instance I considered was that a user would have a referral code that can be shared and also another user would be able to input the referral code on registration to denote if he/she was invited by another user.
Therefore, a user can be referred  by another user and a user can refer many user.

Looking at the relationship between this; we have a `One-to-Many` relationship.
So we edit `create_user_table` migration file.

```php
$table->string('referral_code')->unique();
$table->unsignedBigInteger('referred_by_id');
$table->foreign('referred_by_id')->references('id')->on('users');
```
But in some instances, some users might not have a referrer, so we update the table schema to have it as;

```php
 Schema::create('users', function (Blueprint $table) {
          $table->id();
          $table->string('name');    
          $table->string('email')->unique();
          $table->string('phone')->unique()->nullable();            
          $table->string('password');
          $table->string('referral_code')->unique();
          $table->unsignedBigInteger('referred_by_id')- 
          >nullable();
          $table->foreign('referred_by_id')->references('id')- 
          >on('users');
          $table->rememberToken();
          $table->timestamps(); 
            
});
```
So we migrate the database and make the following changes changes to the User model.

```php

protected $fillable = [
    'referred_by_id', 'referral_code' 'name', 'email', 'password', 'phone'
];


public function referredBy()
{
    return $this->belongsTo(User::class, 'referred_by_id', 'id');
}


public function referrals()
{
    return $this->hasMany(User::class, 'referred_by_id', 'id');
}
```
So on registration of a new user, we update our registration controller: I have mine to be `AuthController`;

```php
class AuthController extends Controller {

  public function register(Request $request)
    {

        $validator = Validator::make(
            $request->all(),
            [
                'name' => ['required', 'string', 'max:255'],
                'email' => 'required|email|unique:users',
                'password' => 'required',

            ],
            $messages = [
                'email.unique' => __('Email already associated 
                 with an account')
            ]
        );

        if ($validator->fails()) {
            return response()->json([
                "message" => $validator->messages(),
            ], 400);
        }
      $referrer = User::where('referral_code', $request- 
      >referral_code)->first();
        try {

            DB::beginTransaction();
            
            $user = new User();
            $user->username = $request->username;
            $user->email = $request->email;
            $user->phone = $phone;
            $user->password = Hash::make($request->password);
            $user->referral_code = "RF_" . \Str::random(4);
            $user->referred_by_id => $referrer ? $referrer->id 
            : null,
            $user->save();

            

            DB::commit();
         if ($user->referrer !== null) {
         //perform any logic to gift the referrer or update 
        the referrer wallet

          }
            //generate tokens

            return $this->authObject($user);
            
        } catch (\Exception$error) {
            logger("General error", [$error]);
            DB::rollback();
            return response()->json([
                "message" => $error->getMessage(),
            ], 500);
        }
    }

   private function authObject($user)
    {
        $user = User::find($user->id);
        $token = $user->createToken('new_token')- 
       >plainTextToken;

        return response()->json([
            "token" => $token,
            "type" => "Bearer",
            "message" => __("User Registered successful 😃"),
        ]);
    }
}
```
In the above method; we validate the request and create a new user, with an autogenerated referral code of theirs and also update the user with the referrer id if there's any and you can also create any logic to gift the referrer or update their wallet if there is any 😃.